xref: /illumos-gate/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c (revision bfed486ad8de8b8ebc6345a8e10accae08bf2f45)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * NSS keystore wrapper
23  *
24  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <synch.h>
35 
36 #include <kmfapiP.h>
37 #include <ber_der.h>
38 /* NSS related headers */
39 
40 #include <mps/nss.h>
41 #include <mps/cert.h>
42 #include <mps/certdb.h>
43 #include <mps/secoid.h>
44 #include <mps/secder.h>
45 #include <mps/secerr.h>
46 #include <mps/cryptohi.h>
47 #include <mps/keyhi.h>
48 #include <mps/keythi.h>
49 #include <mps/pk11func.h>
50 #include <mps/pk11pqg.h>
51 #include <mps/pkcs12.h>
52 #include <mps/p12plcy.h>
53 #include <mps/prerror.h>
54 
55 #define	NSS_OK		0
56 
57 mutex_t init_lock = DEFAULTMUTEX;
58 static int nss_initialized = 0;
59 
60 KMF_RETURN
61 NSS_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
62 
63 KMF_RETURN
64 NSS_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
65 
66 void
67 NSS_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
68 
69 KMF_RETURN
70 NSS_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
71 
72 KMF_RETURN
73 NSS_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
74 
75 KMF_RETURN
76 NSS_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
77 
78 KMF_RETURN
79 NSS_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
80 
81 KMF_RETURN
82 NSS_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
83 
84 KMF_RETURN
85 NSS_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
86 
87 KMF_RETURN
88 NSS_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
89 	KMF_DATA *, KMF_DATA *);
90 
91 KMF_RETURN
92 NSS_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
93 
94 KMF_RETURN
95 NSS_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
96 
97 KMF_RETURN
98 NSS_FindCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
99 
100 KMF_RETURN
101 NSS_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
102 
103 KMF_RETURN
104 NSS_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
105 
106 KMF_RETURN
107 NSS_GetErrorString(KMF_HANDLE_T, char **);
108 
109 KMF_RETURN
110 NSS_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
111 
112 KMF_RETURN
113 NSS_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
114 
115 KMF_RETURN
116 NSS_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
117 	KMF_DATA *, KMF_DATA *);
118 
119 KMF_RETURN
120 NSS_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
121 
122 KMF_RETURN
123 NSS_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
124 
125 KMF_RETURN
126 NSS_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
127 
128 KMF_RETURN
129 NSS_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
130 
131 static
132 KMF_PLUGIN_FUNCLIST nss_plugin_table =
133 {
134 	1,				/* Version */
135 	NSS_ConfigureKeystore,
136 	NSS_FindCert,
137 	NSS_FreeKMFCert,
138 	NSS_StoreCert,
139 	NSS_ImportCert,
140 	NSS_ImportCRL,
141 	NSS_DeleteCert,
142 	NSS_DeleteCRL,
143 	NSS_CreateKeypair,
144 	NSS_FindKey,
145 	NSS_EncodePubKeyData,
146 	NSS_SignData,
147 	NSS_DeleteKey,
148 	NULL    /* ListCRL */,
149 	NSS_FindCRL,
150 	NSS_FindCertInCRL,
151 	NSS_GetErrorString,
152 	NSS_FindPrikeyByCert,
153 	NSS_DecryptData,
154 	NSS_ExportPK12,
155 	NSS_CreateSymKey,
156 	NSS_GetSymKeyValue,
157 	NSS_SetTokenPin,
158 	NULL, /* VerifyData */
159 	NSS_StoreKey,
160 	NULL /* Finalize */
161 };
162 
163 /* additions for importing and exporting PKCS 12 files */
164 typedef struct p12uContextStr {
165 	char		*filename;	/* name of file */
166 	PRFileDesc	*file;		/* pointer to file */
167 	PRBool		error;		/* error occurred? */
168 	int		errorValue;	/* which error occurred? */
169 } p12uContext;
170 
171 #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_NSS; \
172 	h->lasterr.errcode = c;
173 
174 KMF_PLUGIN_FUNCLIST *
175 KMF_Plugin_Initialize()
176 {
177 	SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
178 	SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
179 	SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
180 	SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
181 	SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
182 	SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
183 	SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
184 
185 	return (&nss_plugin_table);
186 }
187 
188 static char *
189 /*ARGSUSED*/
190 nss_getpassword(PK11SlotInfo *slot, PRBool retry, void *arg)
191 {
192 	if (retry)
193 		return (NULL);
194 	if (arg != NULL)
195 		return ((char *)strdup(arg));
196 	else
197 		return (NULL);
198 }
199 
200 static KMF_RETURN
201 nss_authenticate(KMF_HANDLE_T handle,
202 	PK11SlotInfo *nss_slot, KMF_CREDENTIAL *cred)
203 {
204 
205 	SECStatus nssrv = SECSuccess;
206 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
207 
208 	/* If a password was given, try to login to the slot */
209 	if (cred == NULL || cred->cred == NULL || cred->credlen == 0 ||
210 	    nss_slot == NULL) {
211 		return (KMF_ERR_BAD_PARAMETER);
212 	}
213 
214 	if (PK11_IsLoggedIn(nss_slot, NULL)) {
215 		return (KMF_OK);
216 	}
217 
218 	PK11_SetPasswordFunc(nss_getpassword);
219 	nssrv = PK11_Authenticate(nss_slot, PR_TRUE, (void *)cred->cred);
220 
221 	if (nssrv != SECSuccess) {
222 		SET_ERROR(kmfh, nssrv);
223 		PK11_FreeSlot(nss_slot);
224 		return (KMF_ERR_AUTH_FAILED);
225 	}
226 
227 	return (KMF_OK);
228 }
229 
230 static SECStatus
231 Init_NSS_DBs(const char *configdir,
232 	const char *certPrefix,
233 	const char *keyPrefix,
234 	const char *secmodName)
235 {
236 	SECStatus rv = NSS_OK;
237 
238 	(void) mutex_lock(&init_lock);
239 
240 	/* If another thread already did it, return OK. */
241 	if (nss_initialized) {
242 		(void) mutex_unlock(&init_lock);
243 		return (SECSuccess);
244 	}
245 
246 	rv = NSS_Initialize((configdir && strlen(configdir)) ?
247 	    configdir : "./", certPrefix, keyPrefix,
248 	    secmodName ? secmodName : "secmod.db", NSS_INIT_COOPERATE);
249 	if (rv != SECSuccess) {
250 		goto end;
251 	}
252 
253 	nss_initialized++;
254 end:
255 	(void) mutex_unlock(&init_lock);
256 	return (rv);
257 }
258 
259 /*
260  * When it is called the first time, it will intialize NSS.  Once the NSS
261  * is initialized, this function returns KMF_KEYSTORE_ALREADY_INITIALIZED
262  * if it is called again.
263  */
264 KMF_RETURN
265 NSS_ConfigureKeystore(KMF_HANDLE_T handle,
266 	int numattr, KMF_ATTRIBUTE *attrlist)
267 {
268 	KMF_RETURN rv = KMF_OK;
269 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
270 	char    *configdir;
271 	char    *certPrefix;
272 	char    *keyPrefix;
273 	char    *secModName;
274 
275 	configdir = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
276 	certPrefix = kmf_get_attr_ptr(KMF_CERTPREFIX_ATTR, attrlist, numattr);
277 	keyPrefix = kmf_get_attr_ptr(KMF_KEYPREFIX_ATTR, attrlist, numattr);
278 	secModName = kmf_get_attr_ptr(KMF_SECMODNAME_ATTR, attrlist, numattr);
279 
280 	(void) mutex_lock(&init_lock);
281 	if (nss_initialized == 0) {
282 		SECStatus err;
283 
284 		(void) mutex_unlock(&init_lock);
285 		err = Init_NSS_DBs(configdir, certPrefix,
286 		    keyPrefix, secModName);
287 		if (err != SECSuccess) {
288 			SET_ERROR(kmfh, err);
289 			return (KMF_ERR_INTERNAL);
290 		}
291 	} else {
292 		rv = KMF_KEYSTORE_ALREADY_INITIALIZED;
293 		(void) mutex_unlock(&init_lock);
294 	}
295 
296 	return (rv);
297 }
298 
299 /*
300  * This function sets up the slot to be used for other operations.
301  * This function is basically called by every NSS SPI function.
302  * For those functions that can only be performed in the internal slot, the
303  * boolean "internal_slot_only" argument needs to be TRUE.
304  * A slot pointer will be returned when this function is executed successfully.
305  */
306 KMF_RETURN
307 do_nss_init(void *handle, int numattr,
308 	KMF_ATTRIBUTE *attrlist,
309 	boolean_t internal_slot_only,
310 	PK11SlotInfo **nss_slot)
311 {
312 	KMF_RETURN rv = KMF_OK;
313 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
314 	char *slotlabel = NULL;
315 
316 	if (!nss_initialized)
317 		return (KMF_ERR_PLUGIN_INIT);
318 
319 	slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
320 	/*
321 	 * NSS Is already initialized, but we need to find
322 	 * the right slot.
323 	 */
324 	if (slotlabel == NULL ||
325 	    strcmp(slotlabel, "internal") == 0) {
326 		*nss_slot = PK11_GetInternalKeySlot();
327 	} else if (internal_slot_only == TRUE)  {
328 		rv = KMF_ERR_SLOTNAME;
329 		goto end;
330 	} else {
331 		*nss_slot = PK11_FindSlotByName(slotlabel);
332 	}
333 
334 	if (*nss_slot == NULL) {
335 		SET_ERROR(kmfh, PORT_GetError());
336 		rv = KMF_ERR_SLOTNAME;
337 		goto end;
338 	}
339 
340 	/*
341 	 * If the token was not yet initialized, return an error.
342 	 */
343 	if (PK11_NeedUserInit(*nss_slot)) {
344 		rv = KMF_ERR_UNINITIALIZED_TOKEN;
345 	}
346 
347 end:
348 	return (rv);
349 }
350 
351 static KMF_RETURN
352 nss2kmf_cert(CERTCertificate *nss_cert, KMF_X509_DER_CERT *kmf_cert)
353 {
354 	kmf_cert->kmf_private.keystore_type = KMF_KEYSTORE_NSS;
355 	kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID;
356 
357 	kmf_cert->certificate.Length = nss_cert->derCert.len;
358 
359 	if ((kmf_cert->certificate.Data = malloc(nss_cert->derCert.len)) ==
360 	    NULL) {
361 		kmf_cert->certificate.Length = 0;
362 		return (KMF_ERR_MEMORY);
363 	}
364 	(void) memcpy(kmf_cert->certificate.Data, nss_cert->derCert.data,
365 	    nss_cert->derCert.len);
366 	if (nss_cert->nickname != NULL)
367 		kmf_cert->kmf_private.label =
368 		    (char *)strdup(nss_cert->nickname);
369 	return (KMF_OK);
370 }
371 
372 static KMF_RETURN
373 nss_getcert_by_label(KMF_HANDLE *kmfh,
374 	char *name, KMF_X509_DER_CERT *kmf_cert,
375 	uint32_t *num_certs, KMF_CERT_VALIDITY find_criteria)
376 {
377 	KMF_RETURN rv = KMF_OK;
378 	CERTCertificate *nss_cert;
379 	SECCertTimeValidity validity;
380 
381 	nss_cert = PK11_FindCertFromNickname(name, NULL);
382 	if (nss_cert == NULL) {
383 		*num_certs = 0;
384 		SET_ERROR(kmfh, PORT_GetError());
385 		*num_certs = 0;
386 		return (KMF_ERR_CERT_NOT_FOUND);
387 	} else {
388 		*num_certs = 1;
389 	}
390 
391 	switch (find_criteria) {
392 	case KMF_ALL_CERTS:
393 		break;
394 	case KMF_NONEXPIRED_CERTS:
395 		validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
396 		    PR_FALSE);
397 		if (validity != secCertTimeValid) {
398 			/* this is an invalid cert, reject it */
399 			*num_certs = 0;
400 			CERT_DestroyCertificate(nss_cert);
401 			return (KMF_OK);
402 		}
403 		break;
404 	case KMF_EXPIRED_CERTS:
405 		validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
406 		    PR_FALSE);
407 		if (validity == secCertTimeValid) {
408 			/* this is a valid cert, reject it in this case. */
409 			*num_certs = 0;
410 			CERT_DestroyCertificate(nss_cert);
411 			return (KMF_OK);
412 		}
413 		break;
414 	default:
415 		return (KMF_ERR_BAD_PARAMETER);
416 	}
417 
418 	if (kmf_cert != NULL)
419 		rv = nss2kmf_cert(nss_cert, kmf_cert);
420 
421 	/* We copied the data we need, so cleanup the internal record */
422 	CERT_DestroyCertificate(nss_cert);
423 
424 	if (rv != KMF_OK)
425 		*num_certs = 0;
426 
427 	return (rv);
428 }
429 
430 static KMF_RETURN
431 nss_find_matching_certs(PK11SlotInfo *slot,
432 	char *issuer, char *subject, KMF_BIGINT *serial,
433 	CERTCertList **certlist, KMF_CERT_VALIDITY find_criteria)
434 {
435 	KMF_RETURN rv = KMF_OK;
436 	SECStatus ret;
437 	CERTCertList *list;
438 	CERTCertListNode *node;
439 	KMF_X509_NAME issuerDN, subjectDN;
440 	boolean_t findIssuer = FALSE;
441 	boolean_t findSubject = FALSE;
442 	boolean_t findSerial = FALSE;
443 
444 	if (issuer != NULL && strlen(issuer)) {
445 		rv = kmf_dn_parser(issuer,  &issuerDN);
446 		if (rv != KMF_OK)
447 			return (rv);
448 		findIssuer = TRUE;
449 	}
450 	if (subject != NULL && strlen(subject)) {
451 		rv = kmf_dn_parser(subject, &subjectDN);
452 		if (rv != KMF_OK)
453 			return (rv);
454 		findSubject = TRUE;
455 	}
456 	if (serial != 0 && serial->val != NULL && serial->len > 0)
457 		findSerial = TRUE;
458 
459 	list = PK11_ListCertsInSlot(slot);
460 	if (list) {
461 		node = CERT_LIST_HEAD(list);
462 		while (!CERT_LIST_END(node, list)) {
463 			KMF_X509_NAME cmpDN;
464 			KMF_DATA der;
465 			boolean_t match;
466 			CERTCertListNode *freenode;
467 
468 			if (findIssuer) {
469 				der.Data = node->cert->derIssuer.data;
470 				der.Length = node->cert->derIssuer.len;
471 				rv = DerDecodeName(&der, &cmpDN);
472 				if (rv == KMF_OK) {
473 					match = !KMF_CompareRDNs(&issuerDN,
474 					    &cmpDN);
475 					kmf_free_dn(&cmpDN);
476 					if (!match)
477 						goto delete_and_cont;
478 				} else {
479 					goto delete_and_cont;
480 				}
481 			}
482 			if (findSubject) {
483 				der.Data = node->cert->derSubject.data;
484 				der.Length = node->cert->derSubject.len;
485 				rv = DerDecodeName(&der, &cmpDN);
486 				if (rv == KMF_OK) {
487 					match = !KMF_CompareRDNs(&subjectDN,
488 					    &cmpDN);
489 					kmf_free_dn(&cmpDN);
490 					if (!match)
491 						goto delete_and_cont;
492 				} else {
493 					goto delete_and_cont;
494 				}
495 			}
496 			if (findSerial) {
497 				SECItem *sernum;
498 
499 				sernum = &node->cert->serialNumber;
500 
501 				if (serial->len != sernum->len)
502 					goto delete_and_cont;
503 
504 				if (memcmp(sernum->data, serial->val,
505 				    serial->len))
506 					goto delete_and_cont;
507 			}
508 
509 			/* select the certs using find criteria */
510 			switch (find_criteria) {
511 			case KMF_ALL_CERTS:
512 				break;
513 			case KMF_NONEXPIRED_CERTS:
514 				ret = CERT_CertTimesValid(node->cert);
515 				if (ret == SECFailure) {
516 					/* this is an invalid cert */
517 					goto skip;
518 				}
519 				break;
520 
521 			case KMF_EXPIRED_CERTS:
522 				ret = CERT_CertTimesValid(node->cert);
523 				if (ret != SECFailure) {
524 					/* this is a valid cert */
525 					goto skip;
526 				}
527 				break;
528 			}
529 skip:
530 			node = CERT_LIST_NEXT(node);
531 			continue;
532 delete_and_cont:
533 			freenode = node;
534 			node = CERT_LIST_NEXT(node);
535 			CERT_RemoveCertListNode(freenode);
536 		}
537 	}
538 
539 	if (rv == KMF_OK && certlist != NULL) {
540 		*certlist = list;
541 	} else {
542 		CERT_DestroyCertList(list);
543 	}
544 	return (rv);
545 }
546 
547 static KMF_RETURN
548 convertCertList(void *kmfhandle,
549 	CERTCertList *nsscerts, KMF_X509_DER_CERT *kmfcerts,
550 	uint32_t *numcerts)
551 {
552 	KMF_RETURN rv = KMF_OK;
553 	CERTCertListNode *node;
554 	uint32_t maxcerts = *numcerts;
555 
556 	maxcerts = *numcerts;
557 	if (maxcerts == 0)
558 		maxcerts = 0xFFFFFFFF;
559 
560 	*numcerts = 0;
561 
562 	/*
563 	 * Don't copy more certs than the caller wanted.
564 	 */
565 	for (node = CERT_LIST_HEAD(nsscerts);
566 	    !CERT_LIST_END(node, nsscerts) && rv == KMF_OK &&
567 	    (*numcerts) < maxcerts;
568 	    node = CERT_LIST_NEXT(node), (*numcerts)++) {
569 		if (kmfcerts != NULL)
570 			rv = nss2kmf_cert(node->cert, &kmfcerts[*numcerts]);
571 	}
572 
573 	/*
574 	 * If we failed, delete any certs allocated so far.
575 	 */
576 	if (rv != KMF_OK) {
577 		int i;
578 		for (i = 0; i < *numcerts; i++)
579 			kmf_free_kmf_cert(kmfhandle, &kmfcerts[i]);
580 
581 		*numcerts = 0;
582 	}
583 	return (rv);
584 }
585 
586 KMF_RETURN
587 NSS_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
588 {
589 	KMF_RETURN rv = KMF_OK;
590 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
591 	PK11SlotInfo *nss_slot = NULL;
592 	CERTCertList *certlist = NULL;
593 	uint32_t maxcerts;
594 	uint32_t *num_certs;
595 	KMF_X509_DER_CERT *kmfcerts = NULL;
596 	char *certlabel = NULL;
597 	char *issuer = NULL;
598 	char *subject = NULL;
599 	KMF_BIGINT *serial = NULL;
600 	KMF_CERT_VALIDITY  validity;
601 
602 	if (handle == NULL || attrlist == NULL || numattr == 0) {
603 		return (KMF_ERR_BAD_PARAMETER);
604 	}
605 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
606 	if (rv != KMF_OK)
607 		return (rv);
608 
609 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
610 	if (num_certs == NULL)
611 		return (KMF_ERR_BAD_PARAMETER);
612 
613 	maxcerts = *num_certs;
614 	if (maxcerts == 0)
615 		maxcerts = 0xFFFFFFFF;
616 	*num_certs = 0;
617 
618 	/* Get the optional returned certificate list  */
619 	kmfcerts = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, numattr);
620 
621 	/* Get optional search criteria attributes */
622 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
623 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
624 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
625 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
626 
627 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
628 	    &validity, NULL);
629 	if (rv != KMF_OK) {
630 		validity = KMF_ALL_CERTS;
631 		rv = KMF_OK;
632 	}
633 
634 	if (certlabel != NULL) {
635 		/* This will only find 1 certificate */
636 		rv = nss_getcert_by_label(kmfh,	certlabel, kmfcerts, num_certs,
637 		    validity);
638 	} else {
639 		/*
640 		 * Build a list of matching certs.
641 		 */
642 		rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
643 		    &certlist, validity);
644 
645 		/*
646 		 * If the caller supplied a pointer to storage for
647 		 * a list of certs, convert up to 'maxcerts' of the
648 		 * matching certs.
649 		 */
650 		if (rv == KMF_OK && certlist != NULL) {
651 			rv = convertCertList(handle, certlist, kmfcerts,
652 			    &maxcerts);
653 			CERT_DestroyCertList(certlist);
654 			if (rv == KMF_OK)
655 				*num_certs = maxcerts;
656 		}
657 	}
658 
659 	if (nss_slot != NULL) {
660 		PK11_FreeSlot(nss_slot);
661 	}
662 
663 	if (rv == KMF_OK && *num_certs == 0)
664 		rv = KMF_ERR_CERT_NOT_FOUND;
665 
666 	return (rv);
667 }
668 
669 void
670 /*ARGSUSED*/
671 NSS_FreeKMFCert(KMF_HANDLE_T handle,
672 	KMF_X509_DER_CERT *kmf_cert)
673 {
674 	if (kmf_cert != NULL) {
675 		if (kmf_cert->certificate.Data != NULL) {
676 			free(kmf_cert->certificate.Data);
677 			kmf_cert->certificate.Data = NULL;
678 			kmf_cert->certificate.Length = 0;
679 		}
680 		if (kmf_cert->kmf_private.label != NULL) {
681 			free(kmf_cert->kmf_private.label);
682 			kmf_cert->kmf_private.label = NULL;
683 		}
684 	}
685 }
686 
687 
688 KMF_RETURN
689 NSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
690 {
691 	KMF_RETURN rv = KMF_OK;
692 	int nssrv;
693 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
694 	CERTCertificate *cert = NULL;
695 	PK11SlotInfo *nss_slot = NULL;
696 	char *certlabel = NULL;
697 	char *issuer = NULL;
698 	char *subject = NULL;
699 	KMF_BIGINT *serial = NULL;
700 	KMF_CERT_VALIDITY  validity;
701 
702 	if (handle == NULL || attrlist == NULL || numattr == 0) {
703 		return (KMF_ERR_BAD_PARAMETER);
704 	}
705 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
706 	if (rv != KMF_OK)
707 		return (rv);
708 
709 	/* Get the search criteria attributes.  They are all optional. */
710 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
711 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
712 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
713 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
714 
715 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
716 	    &validity, NULL);
717 	if (rv != KMF_OK) {
718 		validity = KMF_ALL_CERTS;
719 		rv = KMF_OK;
720 	}
721 
722 	/* Start finding the matched certificates and delete them. */
723 	if (certlabel != NULL) {
724 		cert = PK11_FindCertFromNickname(certlabel, NULL);
725 		if (cert == NULL) {
726 			return (KMF_ERR_CERT_NOT_FOUND);
727 		}
728 
729 		switch (validity) {
730 		case KMF_ALL_CERTS:
731 			break;
732 		case KMF_NONEXPIRED_CERTS:
733 			nssrv = CERT_CertTimesValid(cert);
734 			if (nssrv == SECFailure) {
735 				/* this is an invalid cert - skip it */
736 				goto out;
737 			}
738 			break;
739 		case KMF_EXPIRED_CERTS:
740 			nssrv = CERT_CertTimesValid(cert);
741 			if (nssrv != SECFailure) {
742 				/* this is a valid cert - skip it */
743 				goto out;
744 			}
745 			break;
746 		}
747 		/* delete it from database */
748 		nssrv = SEC_DeletePermCertificate(cert);
749 		if (nssrv) {
750 			SET_ERROR(kmfh, nssrv);
751 			rv = KMF_ERR_INTERNAL;
752 		}
753 	} else {
754 		CERTCertListNode *node;
755 		CERTCertList *certlist = NULL;
756 
757 		rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
758 		    &certlist, validity);
759 
760 		for (node = CERT_LIST_HEAD(certlist);
761 		    !CERT_LIST_END(node, certlist) && rv == KMF_OK;
762 		    node = CERT_LIST_NEXT(node)) {
763 
764 			nssrv = SEC_DeletePermCertificate(node->cert);
765 			if (nssrv) {
766 				SET_ERROR(kmfh, nssrv);
767 				rv = KMF_ERR_INTERNAL;
768 			}
769 		}
770 
771 		if (rv == KMF_OK && certlist != NULL) {
772 			CERT_DestroyCertList(certlist);
773 		} else if (rv == KMF_OK && certlist == NULL) {
774 			rv = KMF_ERR_CERT_NOT_FOUND;
775 		}
776 	}
777 out:
778 	if (nss_slot != NULL) {
779 		PK11_FreeSlot(nss_slot);
780 	}
781 
782 	if (cert != NULL) {
783 		CERT_DestroyCertificate(cert);
784 	}
785 
786 	return (rv);
787 }
788 
789 static void
790 InitRandom(char *filename)
791 {
792 	char buf[2048];
793 	int fd;
794 	PRInt32 count;
795 
796 	fd = open(filename, O_RDONLY);
797 	if (!fd)
798 		return;
799 
800 	count = read(fd, buf, sizeof (buf));
801 	if (count > 0) {
802 		PK11_RandomUpdate(buf, count);
803 	}
804 
805 	(void) close(fd);
806 }
807 
808 KMF_RETURN
809 NSS_CreateKeypair(KMF_HANDLE_T handle,
810 	int numattr, KMF_ATTRIBUTE *attrlist)
811 {
812 	KMF_RETURN rv = KMF_OK;
813 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
814 	PK11RSAGenParams rsaparams;
815 	void *nssparams;
816 	CK_MECHANISM_TYPE mechanism;
817 	ulong_t publicExponent = 0x010001;
818 	PK11SlotInfo *nss_slot = NULL;
819 	SECKEYPrivateKey *NSSprivkey = NULL;
820 	SECKEYPublicKey *NSSpubkey = NULL;
821 	PQGParams *pqgParams = NULL;
822 	KMF_CREDENTIAL cred;
823 	boolean_t storekey = TRUE;
824 	uint32_t keylen = 1024, len;
825 	uint32_t keylen_size = sizeof (uint32_t);
826 	KMF_KEY_ALG keytype = KMF_RSA;
827 	KMF_KEY_HANDLE *pubkey = NULL;
828 	KMF_KEY_HANDLE *privkey = NULL;
829 	char *keylabel = NULL;
830 
831 	if (handle == NULL || attrlist == NULL || numattr == 0) {
832 		return (KMF_ERR_BAD_PARAMETER);
833 	}
834 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
835 	if (rv != KMF_OK) {
836 		return (rv);
837 	}
838 
839 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
840 	    (void *)&cred, NULL);
841 	if (rv != KMF_OK)
842 		return (rv);
843 
844 	rv = nss_authenticate(handle, nss_slot, &cred);
845 	if (rv != KMF_OK) {
846 		return (rv);
847 	}
848 
849 	/* "storekey" is optional. Default is TRUE */
850 	(void) kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
851 	    &storekey, NULL);
852 
853 	/* keytype is optional.  KMF_RSA is default */
854 	(void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
855 	    (void *)&keytype, NULL);
856 
857 	rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
858 	    &keylen, &keylen_size);
859 	if (rv == KMF_ERR_ATTR_NOT_FOUND)
860 		/* Default keylen = 1024 */
861 		rv = KMF_OK;
862 	else if (rv != KMF_OK)
863 		return (KMF_ERR_BAD_PARAMETER);
864 
865 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
866 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
867 	if (pubkey == NULL || privkey == NULL)
868 		return (KMF_ERR_BAD_PARAMETER);
869 
870 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
871 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
872 
873 	rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr,	NULL, &len);
874 	if (rv == KMF_OK && len > 0) {
875 		keylabel = malloc(len + 1);
876 		if (keylabel == NULL)
877 			return (KMF_ERR_MEMORY);
878 		/* Now fill in the label value */
879 		(void) memset(keylabel, 0, len + 1);
880 		rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr,
881 		    keylabel, NULL);
882 		if (rv != KMF_OK) {
883 			free(keylabel);
884 			goto cleanup;
885 		}
886 	}
887 
888 	/* Get some random bits */
889 	InitRandom("/dev/urandom");
890 	if (keytype == KMF_RSA) {
891 		KMF_BIGINT rsaexp;
892 
893 		rsaparams.keySizeInBits = keylen;
894 		/*
895 		 * NSS only allows for a 4 byte exponent.
896 		 * Ignore the exponent parameter if it is too big.
897 		 */
898 		if ((rv = kmf_get_attr(KMF_RSAEXP_ATTR, attrlist, numattr,
899 		    &rsaexp, NULL)) == KMF_OK) {
900 			if (rsaexp.len > 0 &&
901 			    rsaexp.len <= sizeof (publicExponent) &&
902 			    rsaexp.val != NULL) {
903 				(void) memcpy(&publicExponent, rsaexp.val,
904 				    rsaexp.len);
905 			}
906 		}
907 		rsaparams.pe = publicExponent;
908 		mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
909 		nssparams = &rsaparams;
910 	} else if (keytype == KMF_DSA) {
911 		PQGVerify *pqgVerify = NULL;
912 		int ks;
913 		SECStatus	nssrv, passed;
914 
915 		mechanism = CKM_DSA_KEY_PAIR_GEN;
916 
917 		ks = PQG_PBITS_TO_INDEX(keylen);
918 		nssrv = PK11_PQG_ParamGen(ks, &pqgParams, &pqgVerify);
919 		if (nssrv != SECSuccess) {
920 			SET_ERROR(kmfh, rv);
921 			PK11_PQG_DestroyVerify(pqgVerify);
922 			rv = KMF_ERR_KEYGEN_FAILED;
923 			goto cleanup;
924 		}
925 
926 		nssrv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
927 		if (nssrv != SECSuccess || passed != SECSuccess) {
928 			SET_ERROR(kmfh, rv);
929 			rv = KMF_ERR_KEYGEN_FAILED;
930 		}
931 
932 		PK11_PQG_DestroyVerify(pqgVerify);
933 
934 		if (rv != KMF_OK) {
935 			SET_ERROR(kmfh, PORT_GetError());
936 			goto cleanup;
937 		}
938 
939 		nssparams = pqgParams;
940 	} else {
941 		rv = KMF_ERR_BAD_PARAMETER;
942 		goto cleanup;
943 	}
944 
945 	NSSprivkey = PK11_GenerateKeyPair(nss_slot, mechanism, nssparams,
946 	    &NSSpubkey,
947 	    storekey, /* isPermanent */
948 	    PR_TRUE, /* isSensitive */
949 	    (void *)cred.cred);
950 
951 	if (NSSprivkey == NULL || NSSpubkey == NULL) {
952 		SET_ERROR(kmfh, PORT_GetError());
953 		rv = KMF_ERR_KEYGEN_FAILED;
954 	} else {
955 		if (keylabel != NULL && strlen(keylabel)) {
956 			(void) PK11_SetPrivateKeyNickname(NSSprivkey,
957 			    keylabel);
958 			(void) PK11_SetPublicKeyNickname(NSSpubkey, keylabel);
959 		}
960 		/* Now, convert it to a KMF_KEY object for the framework */
961 		privkey->kstype = KMF_KEYSTORE_NSS;
962 		privkey->keyalg = keytype;
963 		privkey->keyclass = KMF_ASYM_PRI;
964 		privkey->keylabel = PK11_GetPrivateKeyNickname(NSSprivkey);
965 		privkey->keyp = (void *)NSSprivkey;
966 
967 		pubkey->kstype = KMF_KEYSTORE_NSS;
968 		pubkey->keyalg = keytype;
969 		pubkey->keyp = (void *)NSSpubkey;
970 		pubkey->keyclass = KMF_ASYM_PUB;
971 		pubkey->keylabel = PK11_GetPublicKeyNickname(NSSpubkey);
972 
973 		rv = KMF_OK;
974 	}
975 cleanup:
976 	if (rv != KMF_OK) {
977 		if (NSSpubkey)
978 			PK11_DeleteTokenPublicKey(NSSpubkey);
979 		if (NSSprivkey)
980 			PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE);
981 
982 		privkey->keyp = NULL;
983 		pubkey->keyp = NULL;
984 	}
985 
986 	if (keylabel)
987 		free(keylabel);
988 
989 	if (pqgParams != NULL)
990 		PK11_PQG_DestroyParams(pqgParams);
991 
992 	if (nss_slot != NULL)
993 		PK11_FreeSlot(nss_slot);
994 
995 	return (rv);
996 }
997 
998 KMF_RETURN
999 NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1000     KMF_OID *AlgOID, KMF_DATA *tobesigned,
1001     KMF_DATA *output)
1002 {
1003 	KMF_RETURN		ret = KMF_OK;
1004 	KMF_ALGORITHM_INDEX	AlgId;
1005 	SECOidTag		signAlgTag;
1006 	SECKEYPrivateKey	*NSSprivkey = NULL;
1007 	SECStatus		rv;
1008 	SECItem			signed_data;
1009 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1010 
1011 	signed_data.data = 0;
1012 	if (key == NULL || AlgOID == NULL ||
1013 	    tobesigned == NULL || output == NULL ||
1014 	    tobesigned->Data == NULL ||
1015 	    output->Data == NULL)
1016 		return (KMF_ERR_BAD_PARAMETER);
1017 
1018 	/* Map the OID to a NSS algorithm */
1019 	AlgId = x509_algoid_to_algid(AlgOID);
1020 	if (AlgId == KMF_ALGID_NONE)
1021 		return (KMF_ERR_BAD_PARAMETER);
1022 
1023 	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1024 
1025 	if (AlgId == KMF_ALGID_MD5WithRSA)
1026 		signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1027 	else if (AlgId == KMF_ALGID_MD2WithRSA)
1028 		signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1029 	else if (AlgId == KMF_ALGID_SHA1WithRSA)
1030 		signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1031 	else if (AlgId == KMF_ALGID_SHA1WithDSA)
1032 		signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
1033 	else
1034 		return (KMF_ERR_BAD_PARAMETER);
1035 
1036 	rv = SEC_SignData(&signed_data, tobesigned->Data,
1037 	    tobesigned->Length, NSSprivkey, signAlgTag);
1038 
1039 	if (rv != 0) {
1040 		SET_ERROR(kmfh, rv);
1041 		return (KMF_ERR_INTERNAL);
1042 	}
1043 
1044 	if (signed_data.len <= output->Length) {
1045 		(void) memcpy(output->Data, signed_data.data, signed_data.len);
1046 		output->Length = signed_data.len;
1047 	} else {
1048 		output->Length = 0;
1049 		ret = KMF_ERR_BAD_PARAMETER;
1050 	}
1051 	free(signed_data.data);
1052 
1053 	return (ret);
1054 }
1055 
1056 KMF_RETURN
1057 NSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1058 	KMF_DATA *encoded)
1059 {
1060 	KMF_RETURN ret = KMF_OK;
1061 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1062 	SECItem *rvitem;
1063 	CERTSubjectPublicKeyInfo *spki = NULL;
1064 
1065 	if (keyp == NULL || encoded == NULL || keyp->keyp == NULL)
1066 		return (KMF_ERR_BAD_PARAMETER);
1067 
1068 	spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp);
1069 	if (spki == NULL) {
1070 		SET_ERROR(kmfh, PORT_GetError());
1071 		return (KMF_ERR_MEMORY);
1072 	}
1073 
1074 	rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki,
1075 	    CERT_SubjectPublicKeyInfoTemplate);
1076 	if (rvitem != NULL) {
1077 		encoded->Data = malloc(rvitem->len);
1078 		if (encoded->Data == NULL) {
1079 			ret = KMF_ERR_MEMORY;
1080 		} else {
1081 			(void) memcpy(encoded->Data, rvitem->data, rvitem->len);
1082 			encoded->Length = rvitem->len;
1083 		}
1084 		SECITEM_FreeItem(rvitem, TRUE);
1085 	} else {
1086 		SET_ERROR(kmfh, PORT_GetError());
1087 		encoded->Data = NULL;
1088 		encoded->Length = 0;
1089 		ret = KMF_ERR_ENCODING;
1090 	}
1091 	SECKEY_DestroySubjectPublicKeyInfo(spki);
1092 
1093 	return (ret);
1094 }
1095 
1096 KMF_RETURN
1097 NSS_DeleteKey(KMF_HANDLE_T handle,
1098 	int numattr, KMF_ATTRIBUTE *attrlist)
1099 {
1100 	KMF_RETURN rv = KMF_OK;
1101 	PK11SlotInfo *nss_slot = NULL;
1102 	KMF_KEY_HANDLE *key;
1103 	KMF_CREDENTIAL cred;
1104 	boolean_t delete_token = B_TRUE;
1105 
1106 	if (handle == NULL || attrlist == NULL || numattr == 0) {
1107 		return (KMF_ERR_BAD_PARAMETER);
1108 	}
1109 	/*
1110 	 * "delete_token" means to clear it from the token storage as well
1111 	 * as from memory.
1112 	 */
1113 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1114 	if (key == NULL || key->keyp == NULL)
1115 		return (KMF_ERR_BAD_PARAMETER);
1116 
1117 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1118 	    (void *)&delete_token, NULL);
1119 	if (rv != KMF_OK)
1120 		/* "delete_token" is optional. Default is TRUE */
1121 		rv = KMF_OK;
1122 
1123 	if (delete_token) {
1124 		SECStatus nssrv = SECSuccess;
1125 		if (key->keyclass != KMF_ASYM_PUB &&
1126 		    key->keyclass != KMF_ASYM_PRI &&
1127 		    key->keyclass != KMF_SYMMETRIC)
1128 			return (KMF_ERR_BAD_KEY_CLASS);
1129 
1130 		rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1131 		if (rv != KMF_OK) {
1132 			return (rv);
1133 		}
1134 
1135 		rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1136 		    (void *)&cred, NULL);
1137 		if (rv != KMF_OK)
1138 			return (KMF_ERR_BAD_PARAMETER);
1139 
1140 		rv = nss_authenticate(handle, nss_slot, &cred);
1141 		if (rv != KMF_OK) {
1142 			return (rv);
1143 		}
1144 
1145 		if (key->keyclass == KMF_ASYM_PUB) {
1146 			nssrv = PK11_DeleteTokenPublicKey(
1147 			    (SECKEYPublicKey *)key->keyp);
1148 		} else if (key->keyclass == KMF_ASYM_PRI) {
1149 			nssrv = PK11_DeleteTokenPrivateKey(
1150 			    (SECKEYPrivateKey *)key->keyp, PR_TRUE);
1151 		} else if (key->keyclass == KMF_SYMMETRIC) {
1152 			nssrv = PK11_DeleteTokenSymKey(
1153 			    (PK11SymKey *) key->keyp);
1154 			if (nssrv == SECSuccess)
1155 				PK11_FreeSymKey((PK11SymKey *) key->keyp);
1156 		}
1157 		if (nssrv != SECSuccess) {
1158 			SET_ERROR(handle, PORT_GetError());
1159 			rv = KMF_ERR_INTERNAL;
1160 		}
1161 	} else {
1162 		if (key->keyclass == KMF_ASYM_PUB) {
1163 			SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp);
1164 		} else if (key->keyclass == KMF_ASYM_PRI) {
1165 			SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp);
1166 		} else if (key->keyclass == KMF_SYMMETRIC) {
1167 			PK11_FreeSymKey((PK11SymKey *) key->keyp);
1168 		} else {
1169 			return (KMF_ERR_BAD_KEY_CLASS);
1170 		}
1171 	}
1172 	key->keyp = NULL;
1173 
1174 	return (rv);
1175 }
1176 
1177 KMF_RETURN
1178 NSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1179 {
1180 	KMF_RETURN ret = KMF_OK;
1181 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1182 	char *str;
1183 
1184 	/* Get the error string in the default language */
1185 	str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode);
1186 
1187 	if (str != NULL) {
1188 		*msgstr = (char *)strdup(str);
1189 		if ((*msgstr) == NULL)
1190 			ret = KMF_ERR_MEMORY;
1191 	} else {
1192 		*msgstr = NULL;
1193 	}
1194 
1195 	return (ret);
1196 }
1197 
1198 KMF_RETURN
1199 NSS_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1200 {
1201 	KMF_RETURN rv = KMF_OK;
1202 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1203 	PK11SlotInfo *nss_slot = NULL;
1204 	KMF_CREDENTIAL cred;
1205 	KMF_KEY_HANDLE *key = NULL;
1206 	KMF_DATA *cert = NULL;
1207 	CERTCertificate *nss_cert = NULL;
1208 	SECKEYPrivateKey* privkey = NULL;
1209 
1210 	if (handle == NULL || attrlist == NULL || numattr == 0) {
1211 		return (KMF_ERR_BAD_PARAMETER);
1212 	}
1213 
1214 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1215 	if (rv != KMF_OK)
1216 		return (rv);
1217 
1218 	/* Get the credential */
1219 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1220 	    (void *)&cred, NULL);
1221 	if (rv != KMF_OK)
1222 		return (KMF_ERR_BAD_PARAMETER);
1223 	rv = nss_authenticate(handle, nss_slot, &cred);
1224 	if (rv != KMF_OK)
1225 		return (rv);
1226 
1227 	/* Get the key handle */
1228 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1229 	if (key == NULL)
1230 		return (KMF_ERR_BAD_PARAMETER);
1231 
1232 	/* Get the cert data and decode it */
1233 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1234 	if (cert == NULL || cert->Data == NULL)
1235 		return (KMF_ERR_BAD_PARAMETER);
1236 
1237 	nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
1238 	    cert->Length);
1239 	if (nss_cert == NULL) {
1240 		SET_ERROR(kmfh, PORT_GetError());
1241 		return (KMF_ERR_BAD_CERT_FORMAT);
1242 	}
1243 
1244 	privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL);
1245 	if (privkey == NULL) {
1246 		SET_ERROR(kmfh, PORT_GetError());
1247 		return (KMF_ERR_KEY_NOT_FOUND);
1248 	}
1249 
1250 	key->kstype = KMF_KEYSTORE_NSS;
1251 	key->keyclass = KMF_ASYM_PRI;
1252 	key->keyp = (void *)privkey;
1253 	key->keylabel = PK11_GetPrivateKeyNickname(privkey);
1254 
1255 	CERT_DestroyCertificate(nss_cert);
1256 
1257 	return (KMF_OK);
1258 }
1259 
1260 
1261 KMF_RETURN
1262 NSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1263 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
1264 	KMF_DATA *output)
1265 {
1266 	KMF_RETURN		ret = KMF_OK;
1267 	SECKEYPrivateKey	*NSSprivkey = NULL;
1268 	SECStatus		rv;
1269 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1270 	unsigned int in_len = 0, out_len = 0;
1271 	unsigned int total_decrypted = 0, modulus_len = 0;
1272 	uint8_t *in_data, *out_data;
1273 	int i, blocks;
1274 
1275 	if (key == NULL || AlgOID == NULL ||
1276 	    ciphertext == NULL || output == NULL ||
1277 	    ciphertext->Data == NULL ||
1278 	    output->Data == NULL)
1279 		return (KMF_ERR_BAD_PARAMETER);
1280 
1281 	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1282 	modulus_len = PK11_GetPrivateModulusLen(NSSprivkey);
1283 
1284 	blocks = ciphertext->Length/modulus_len;
1285 	out_data = output->Data;
1286 	in_data = ciphertext->Data;
1287 	out_len = modulus_len - 11;
1288 	in_len = modulus_len;
1289 
1290 	for (i = 0; i < blocks; i++) {
1291 		rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data,
1292 		    &out_len, ciphertext->Length, in_data, in_len);
1293 
1294 		if (rv != 0) {
1295 			SET_ERROR(kmfh, rv);
1296 			return (KMF_ERR_INTERNAL);
1297 		}
1298 
1299 		out_data += out_len;
1300 		total_decrypted += out_len;
1301 		in_data += in_len;
1302 	}
1303 
1304 	output->Length = total_decrypted;
1305 
1306 	return (ret);
1307 }
1308 
1309 static KMF_KEY_ALG
1310 pk11keytype2kmf(CK_KEY_TYPE type)
1311 {
1312 	switch (type) {
1313 	case CKK_RSA:
1314 		return (KMF_RSA);
1315 	case CKK_DSA:
1316 		return (KMF_RSA);
1317 	case CKK_AES:
1318 		return (KMF_AES);
1319 	case CKK_RC4:
1320 		return (KMF_RC4);
1321 	case CKK_DES:
1322 		return (KMF_DES);
1323 	case CKK_DES3:
1324 		return (KMF_DES3);
1325 	default:
1326 		/* not supported */
1327 		return (KMF_KEYALG_NONE);
1328 	}
1329 }
1330 
1331 KMF_RETURN
1332 NSS_FindKey(KMF_HANDLE_T handle,
1333 	int numattr, KMF_ATTRIBUTE *attrlist)
1334 {
1335 	KMF_RETURN rv;
1336 	SECKEYPrivateKeyList *prilist;
1337 	SECKEYPrivateKeyListNode *prinode;
1338 	SECKEYPublicKeyList *publist;
1339 	SECKEYPublicKeyListNode *pubnode;
1340 	PK11SlotInfo *nss_slot = NULL;
1341 	PK11SymKey *symlist = NULL;
1342 	int count;
1343 	uint32_t maxkeys;
1344 	KMF_KEY_HANDLE *keys;
1345 	uint32_t *numkeys;
1346 	KMF_CREDENTIAL *cred = NULL;
1347 	KMF_KEY_CLASS keyclass;
1348 	char *findLabel;
1349 	char *nick;
1350 	int match = 0;
1351 	KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
1352 
1353 	if (handle == NULL || attrlist == NULL || numattr == 0) {
1354 		return (KMF_ERR_BAD_PARAMETER);
1355 	}
1356 
1357 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1358 	if (numkeys == NULL)
1359 		return (KMF_ERR_BAD_PARAMETER);
1360 
1361 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1362 	if (rv != KMF_OK) {
1363 		return (rv);
1364 	}
1365 
1366 	/* It is OK if this is NULL, we dont need a cred to find public keys */
1367 	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1368 
1369 	if (cred != NULL) {
1370 		rv = nss_authenticate(handle, nss_slot, cred);
1371 		if (rv != KMF_OK) {
1372 			return (rv);
1373 		}
1374 	}
1375 
1376 	maxkeys = *numkeys;
1377 	if (maxkeys == 0)
1378 		maxkeys = 0xFFFFFFFF;
1379 	*numkeys = 0;
1380 
1381 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
1382 	    (void *)&keyclass, NULL);
1383 	if (rv != KMF_OK)
1384 		return (KMF_ERR_BAD_PARAMETER);
1385 
1386 	findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1387 
1388 	if (keyclass == KMF_ASYM_PUB) {
1389 		publist = PK11_ListPublicKeysInSlot(nss_slot, findLabel);
1390 		if (publist == NULL) {
1391 			rv = KMF_ERR_KEY_NOT_FOUND;
1392 			goto cleanup;
1393 		}
1394 	} else if (keyclass == KMF_ASYM_PRI) {
1395 		prilist = PK11_ListPrivKeysInSlot(nss_slot, findLabel, NULL);
1396 		if (prilist == NULL) {
1397 			rv = KMF_ERR_KEY_NOT_FOUND;
1398 			goto cleanup;
1399 		}
1400 	} else if (keyclass == KMF_SYMMETRIC) {
1401 		symlist = PK11_ListFixedKeysInSlot(nss_slot, findLabel, NULL);
1402 		if (symlist == NULL) {
1403 			rv = KMF_ERR_KEY_NOT_FOUND;
1404 			goto cleanup;
1405 		}
1406 	} else {
1407 		rv = KMF_ERR_BAD_KEY_CLASS;
1408 		goto cleanup;
1409 	}
1410 
1411 	keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1412 	/* it is okay to have "keys" contains NULL */
1413 
1414 	if (keyclass == KMF_ASYM_PUB) {
1415 		for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist);
1416 		    !PUBKEY_LIST_END(pubnode, publist) && count < maxkeys;
1417 		    pubnode = PUBKEY_LIST_NEXT(pubnode)) {
1418 			match = 0;
1419 			/*
1420 			 * Due to bug in NSS, we have to manually match
1421 			 * the labels to be sure we have a match.
1422 			 */
1423 			nick = PK11_GetPublicKeyNickname(pubnode->key);
1424 			if (findLabel) {
1425 				match = (nick &&
1426 				    (strcmp(nick, findLabel) == 0));
1427 			} else {
1428 				/* always match if findLabel is NULL */
1429 				match = 1;
1430 			}
1431 			if (keys != NULL && match) {
1432 				keys[count].kstype = KMF_KEYSTORE_NSS;
1433 				keys[count].keyclass = KMF_ASYM_PUB;
1434 				keys[count].keyp = (void *)pubnode->key;
1435 				keys[count].keylabel = nick;
1436 
1437 				if (pubnode->key->keyType == rsaKey)
1438 					keys[count].keyalg = KMF_RSA;
1439 				else if (pubnode->key->keyType == dsaKey)
1440 					keys[count].keyalg = KMF_DSA;
1441 			}
1442 			if (match)
1443 				count++;
1444 		}
1445 		*numkeys = count;
1446 	} else if (keyclass == KMF_ASYM_PRI) {
1447 		for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist);
1448 		    !PRIVKEY_LIST_END(prinode, prilist) && count < maxkeys;
1449 		    prinode = PRIVKEY_LIST_NEXT(prinode)) {
1450 			match = 0;
1451 			/*
1452 			 * Due to bug in NSS, we have to manually match
1453 			 * the labels to be sure we have a match.
1454 			 */
1455 			nick = PK11_GetPrivateKeyNickname(prinode->key);
1456 			if (findLabel) {
1457 				match = (nick &&
1458 				    (strcmp(nick, findLabel) == 0));
1459 			} else {
1460 				/* always match if findLabel is NULL */
1461 				match = 1;
1462 			}
1463 			if (keys != NULL && match) {
1464 				keys[count].kstype = KMF_KEYSTORE_NSS;
1465 				keys[count].keyclass = KMF_ASYM_PRI;
1466 				keys[count].keyp = (void *)prinode->key;
1467 				keys[count].keylabel = nick;
1468 
1469 				if (prinode->key->keyType == rsaKey)
1470 					keys[count].keyalg = KMF_RSA;
1471 				else if (prinode->key->keyType == dsaKey)
1472 					keys[count].keyalg = KMF_DSA;
1473 			}
1474 			if (match)
1475 				count++;
1476 		}
1477 		*numkeys = count;
1478 	} else if (keyclass == KMF_SYMMETRIC) {
1479 		count = 0;
1480 		rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1481 		    (void *)&keytype, NULL);
1482 		if (rv != KMF_OK)
1483 			rv = KMF_OK;
1484 		while (symlist && count < maxkeys) {
1485 			PK11SymKey *symkey = symlist;
1486 			CK_KEY_TYPE type;
1487 			KMF_KEY_ALG keyalg;
1488 
1489 			match = 0;
1490 			type = PK11_GetSymKeyType(symkey);
1491 			keyalg = pk11keytype2kmf(type);
1492 
1493 			symlist = PK11_GetNextSymKey(symkey);
1494 
1495 			/*
1496 			 * If keytype is specified in the searching parameter,
1497 			 * check the keytype and skip the key if its keytype
1498 			 * doesn't match.
1499 			 */
1500 			if (keytype != KMF_KEYALG_NONE && keytype != keyalg) {
1501 				/* free that key since we arent using it */
1502 				PK11_FreeSymKey(symkey);
1503 				continue;
1504 			}
1505 			/*
1506 			 * Due to bug in NSS, we have to manually match
1507 			 * the labels to be sure we have a match.
1508 			 */
1509 			nick = PK11_GetSymKeyNickname(symkey);
1510 			if (findLabel) {
1511 				match = (nick &&
1512 				    (strcmp(nick, findLabel) == 0));
1513 			} else {
1514 				/* always match if findLabel is NULL */
1515 				match = 1;
1516 			}
1517 
1518 			if (keys != NULL && match) {
1519 				keys[count].kstype = KMF_KEYSTORE_NSS;
1520 				keys[count].keyclass = KMF_SYMMETRIC;
1521 				keys[count].keyp = (void *) symkey;
1522 				keys[count].keylabel = nick;
1523 				keys[count].keyalg = keyalg;
1524 			} else {
1525 				PK11_FreeSymKey(symkey);
1526 			}
1527 			if (match)
1528 				count++;
1529 		}
1530 		/*
1531 		 * Cleanup memory for unused keys.
1532 		 */
1533 		while (symlist != NULL) {
1534 			PK11SymKey *symkey = symlist;
1535 
1536 			PK11_FreeSymKey(symkey);
1537 			symlist = PK11_GetNextSymKey(symkey);
1538 		}
1539 		*numkeys = count;
1540 	}
1541 
1542 cleanup:
1543 	if (nss_slot != NULL) {
1544 		PK11_FreeSlot(nss_slot);
1545 	}
1546 
1547 	return (rv);
1548 }
1549 
1550 static SECStatus
1551 p12u_SwapUnicodeBytes(SECItem *uniItem)
1552 {
1553 	unsigned int i;
1554 	unsigned char a;
1555 	if ((uniItem == NULL) || (uniItem->len % 2)) {
1556 		return (SECFailure);
1557 		}
1558 	for (i = 0; i < uniItem->len; i += 2) {
1559 		a = uniItem->data[i];
1560 		uniItem->data[i] = uniItem->data[i+1];
1561 		uniItem->data[i+1] = a;
1562 	}
1563 	return (SECSuccess);
1564 }
1565 
1566 static PRBool
1567 p12u_ucs2_ascii_conversion_function(
1568 	PRBool		toUnicode,
1569 	unsigned char	*inBuf,
1570 	unsigned int	inBufLen,
1571 	unsigned char	*outBuf,
1572 	unsigned int	maxOutBufLen,
1573 	unsigned int	*outBufLen,
1574 	PRBool		swapBytes)
1575 {
1576 	SECItem it = { 0 };
1577 	SECItem *dup = NULL;
1578 	PRBool ret;
1579 
1580 	it.data = inBuf;
1581 	it.len = inBufLen;
1582 	dup = SECITEM_DupItem(&it);
1583 	/*
1584 	 * If converting Unicode to ASCII, swap bytes before conversion
1585 	 * as neccessary.
1586 	 */
1587 	if (!toUnicode && swapBytes) {
1588 		if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
1589 			SECITEM_ZfreeItem(dup, PR_TRUE);
1590 			return (PR_FALSE);
1591 		}
1592 	}
1593 	/* Perform the conversion. */
1594 	ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
1595 	    outBuf, maxOutBufLen, outBufLen);
1596 	if (dup)
1597 		SECITEM_ZfreeItem(dup, PR_TRUE);
1598 
1599 	return (ret);
1600 }
1601 
1602 static PRBool
1603 p12u_OpenFile(p12uContext *p12ctx, PRBool fileRead)
1604 {
1605 	if (!p12ctx || !p12ctx->filename) {
1606 		return (PR_FALSE);
1607 	}
1608 
1609 	if (fileRead) {
1610 		p12ctx->file = PR_Open(p12ctx->filename, PR_RDONLY, 0400);
1611 	} else {
1612 		p12ctx->file = PR_Open(p12ctx->filename,
1613 		    PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600);
1614 	}
1615 
1616 	if (!p12ctx->file) {
1617 		p12ctx->error = PR_TRUE;
1618 		return (PR_FALSE);
1619 	}
1620 
1621 	return (PR_TRUE);
1622 }
1623 
1624 static void
1625 p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
1626 {
1627 	if (!ppCtx || !(*ppCtx)) {
1628 		return;
1629 	}
1630 
1631 	if ((*ppCtx)->file != NULL) {
1632 		PR_Close((*ppCtx)->file);
1633 	}
1634 
1635 	if ((*ppCtx)->filename != NULL) {
1636 		if (removeFile) {
1637 			PR_Delete((*ppCtx)->filename);
1638 		}
1639 		free((*ppCtx)->filename);
1640 	}
1641 
1642 	free(*ppCtx);
1643 	*ppCtx = NULL;
1644 }
1645 
1646 static p12uContext *
1647 p12u_InitContext(PRBool fileImport, char *filename)
1648 {
1649 	p12uContext *p12ctx;
1650 
1651 	p12ctx = PORT_ZNew(p12uContext);
1652 	if (!p12ctx) {
1653 		return (NULL);
1654 	}
1655 
1656 	p12ctx->error = PR_FALSE;
1657 	p12ctx->errorValue = 0;
1658 	p12ctx->filename = strdup(filename);
1659 
1660 	if (!p12u_OpenFile(p12ctx, fileImport)) {
1661 		p12u_DestroyContext(&p12ctx, PR_FALSE);
1662 		return (NULL);
1663 	}
1664 
1665 	return (p12ctx);
1666 }
1667 
1668 static void
1669 p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
1670 {
1671 	p12uContext *p12cxt = arg;
1672 	int writeLen;
1673 
1674 	if (!p12cxt || (p12cxt->error == PR_TRUE)) {
1675 		return;
1676 	}
1677 
1678 	if (p12cxt->file == NULL) {
1679 		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1680 		p12cxt->error = PR_TRUE;
1681 		return;
1682 	}
1683 
1684 	writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
1685 
1686 	if (writeLen != (int)len) {
1687 		PR_Close(p12cxt->file);
1688 		free(p12cxt->filename);
1689 		p12cxt->filename = NULL;
1690 		p12cxt->file = NULL;
1691 		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1692 		p12cxt->error = PR_TRUE;
1693 	}
1694 }
1695 
1696 #define	HANDLE_NSS_ERROR(r) {\
1697 	SET_ERROR(kmfh, PORT_GetError()); \
1698 	rv = r; \
1699 	goto out; }
1700 
1701 static KMF_RETURN
1702 add_cert_to_bag(SEC_PKCS12ExportContext *p12ecx,
1703 	CERTCertificate *cert, SECItem *pwitem)
1704 {
1705 	KMF_RETURN rv = KMF_OK;
1706 	SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
1707 
1708 	keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
1709 	if (PK11_IsFIPS()) {
1710 		certSafe = keySafe;
1711 	} else {
1712 		certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
1713 		    SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
1714 	}
1715 
1716 	if (!certSafe || !keySafe) {
1717 		rv = KMF_ERR_INTERNAL;
1718 		goto out;
1719 	}
1720 
1721 	if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
1722 	    CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
1723 	    SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
1724 	    != SECSuccess) {
1725 		rv = KMF_ERR_INTERNAL;
1726 	}
1727 out:
1728 	return (rv);
1729 }
1730 
1731 KMF_RETURN
1732 NSS_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1733 {
1734 	KMF_RETURN rv;
1735 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
1736 	SEC_PKCS12ExportContext *p12ecx = NULL;
1737 	p12uContext *p12ctx = NULL;
1738 	CERTCertList *certlist = NULL;
1739 	CERTCertificate *nsscert = NULL;
1740 	CERTCertListNode* node = NULL;
1741 	PK11SlotInfo	*slot = NULL;
1742 	SECItem pwitem = {NULL, 0};
1743 	KMF_CREDENTIAL *cred = NULL;
1744 	KMF_CREDENTIAL *p12cred = NULL;
1745 	char *certlabel = NULL;
1746 	char *issuer = NULL;
1747 	char *subject = NULL;
1748 	KMF_BIGINT *serial = NULL;
1749 	char *filename = NULL;
1750 
1751 	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1752 		return (KMF_ERR_BAD_PARAMETER);
1753 	}
1754 
1755 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &slot);
1756 	if (rv != KMF_OK)
1757 		return (rv);
1758 
1759 	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1760 	if (cred == NULL)
1761 		return (KMF_ERR_BAD_PARAMETER);
1762 
1763 	rv = nss_authenticate(handle, slot, cred);
1764 	if (rv != KMF_OK)
1765 		return (rv);
1766 
1767 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
1768 	if (p12cred  == NULL)
1769 		return (KMF_ERR_BAD_PARAMETER);
1770 
1771 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
1772 	    numattr);
1773 	if (filename == NULL)
1774 		return (KMF_ERR_BAD_PARAMETER);
1775 
1776 	/* Get optional search criteria attributes */
1777 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
1778 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1779 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1780 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1781 
1782 	/*
1783 	 * Find the certificate(s) first.
1784 	 */
1785 	if (certlabel != NULL) {
1786 		nsscert = PK11_FindCertFromNickname(certlabel, NULL);
1787 		if (nsscert == NULL) {
1788 			HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND)
1789 		}
1790 	} else {
1791 		rv = nss_find_matching_certs(slot, issuer, subject, serial,
1792 		    &certlist, 0);
1793 
1794 		if (rv == KMF_OK && certlist == NULL) {
1795 			return (KMF_ERR_CERT_NOT_FOUND);
1796 		}
1797 		if (rv != KMF_OK)
1798 			return (rv);
1799 	}
1800 
1801 	/*
1802 	 * The KMF_CREDENTIAL holds the password to use for
1803 	 * encrypting the PKCS12 key information.
1804 	 */
1805 	pwitem.data = (uchar_t *)p12cred->cred;
1806 	pwitem.len = p12cred->credlen;
1807 
1808 	p12ctx = p12u_InitContext(PR_FALSE, filename);
1809 	if (!p12ctx) {
1810 		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1811 	}
1812 
1813 	PORT_SetUCS2_ASCIIConversionFunction(
1814 	    p12u_ucs2_ascii_conversion_function);
1815 
1816 	p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, NULL);
1817 	if (!p12ecx) {
1818 		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1819 	}
1820 
1821 	if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
1822 	    != SECSuccess) {
1823 		HANDLE_NSS_ERROR(KMF_ERR_INTERNAL)
1824 	}
1825 
1826 	/*
1827 	 * NSS actually supports storing a list of keys and certs
1828 	 * in the PKCS#12 PDU.  Nice feature.
1829 	 */
1830 	if (certlist != NULL) {
1831 		for (node = CERT_LIST_HEAD(certlist);
1832 		    !CERT_LIST_END(node, certlist) && rv == KMF_OK;
1833 		    node = CERT_LIST_NEXT(node)) {
1834 			rv = add_cert_to_bag(p12ecx, node->cert, &pwitem);
1835 		}
1836 	} else if (nsscert != NULL) {
1837 		rv = add_cert_to_bag(p12ecx, nsscert, &pwitem);
1838 	}
1839 
1840 	if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx)
1841 	    != SECSuccess) {
1842 		HANDLE_NSS_ERROR(KMF_ERR_ENCODING)
1843 	}
1844 out:
1845 	if (nsscert)
1846 		CERT_DestroyCertificate(nsscert);
1847 
1848 	if (certlist)
1849 		CERT_DestroyCertList(certlist);
1850 
1851 	if (p12ctx)
1852 		p12u_DestroyContext(&p12ctx, PR_FALSE);
1853 
1854 	if (p12ecx)
1855 		SEC_PKCS12DestroyExportContext(p12ecx);
1856 
1857 	return (rv);
1858 }
1859 
1860 #define	SETATTR(t, n, atype, value, size) \
1861 	t[n].type = atype; \
1862 	t[n].pValue = (CK_BYTE *)value; \
1863 	t[n].ulValueLen = (CK_ULONG)size;
1864 
1865 KMF_RETURN
1866 NSS_CreateSymKey(KMF_HANDLE_T handle,
1867 	int numattr, KMF_ATTRIBUTE *attrlist)
1868 {
1869 	KMF_RETURN rv = KMF_OK;
1870 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1871 	PK11SlotInfo *nss_slot = NULL;
1872 	PK11SymKey *nsskey = NULL;
1873 	CK_MECHANISM_TYPE keyType;
1874 	SECStatus nssrv;
1875 	int keySize;
1876 	KMF_KEY_HANDLE *symkey;
1877 	KMF_CREDENTIAL cred;
1878 	uint32_t keylen;
1879 	uint32_t keylen_size = sizeof (uint32_t);
1880 	KMF_KEY_ALG keytype;
1881 	char *keylabel = NULL;
1882 
1883 	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1884 		return (KMF_ERR_BAD_PARAMETER);
1885 	}
1886 
1887 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1888 	if (symkey == NULL)
1889 		return (KMF_ERR_BAD_PARAMETER);
1890 
1891 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, (void *)&keytype,
1892 	    NULL);
1893 	if (rv != KMF_OK)
1894 		return (KMF_ERR_BAD_PARAMETER);
1895 
1896 	rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, &keylen,
1897 	    &keylen_size);
1898 	if (rv == KMF_ERR_ATTR_NOT_FOUND &&
1899 	    (keytype == KMF_DES || keytype == KMF_DES3))
1900 		/* keylength is not required for DES and 3DES */
1901 		rv = KMF_OK;
1902 	if (rv != KMF_OK)
1903 		return (KMF_ERR_BAD_PARAMETER);
1904 
1905 	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1906 	if (keylabel == NULL)
1907 		return (KMF_ERR_BAD_PARAMETER);
1908 
1909 	switch (keytype) {
1910 	case KMF_AES:
1911 		keyType = CKM_AES_KEY_GEN;
1912 		keySize = keylen;
1913 		if (keySize == 0 || (keySize % 8) != 0)
1914 			return (KMF_ERR_BAD_KEY_SIZE);
1915 		break;
1916 	case KMF_RC4:
1917 		keyType = CKM_RC4_KEY_GEN;
1918 		keySize = keylen;
1919 		if (keySize == 0 || (keySize % 8) != 0)
1920 			return (KMF_ERR_BAD_KEY_SIZE);
1921 		break;
1922 	case KMF_DES:
1923 		keyType = CKM_DES_KEY_GEN;
1924 		keySize = 0; /* required by PK11_TokenKeyGen()  */
1925 		break;
1926 	case KMF_DES3:
1927 		keyType = CKM_DES3_KEY_GEN;
1928 		keySize = 0; /* required by PK11_TokenKeyGen() */
1929 		break;
1930 	case KMF_GENERIC_SECRET:
1931 		keyType = CKM_GENERIC_SECRET_KEY_GEN;
1932 		keySize = keylen;
1933 		if (keySize == 0 || (keySize % 8) != 0)
1934 			return (KMF_ERR_BAD_KEY_SIZE);
1935 		break;
1936 	default:
1937 		rv = KMF_ERR_BAD_KEY_TYPE;
1938 		goto out;
1939 	}
1940 
1941 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1942 	if (rv != KMF_OK) {
1943 		return (rv);
1944 	}
1945 
1946 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1947 	    (void *)&cred, NULL);
1948 	if (rv != KMF_OK)
1949 		return (KMF_ERR_BAD_PARAMETER);
1950 
1951 	rv = nss_authenticate(handle, nss_slot, &cred);
1952 	if (rv != KMF_OK) {
1953 		return (rv);
1954 	}
1955 
1956 	nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize,  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 		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 		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 		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 		SEC_DestroyCrl(crl);
2891 	}
2892 
2893 	return (rv);
2894 }
2895