xref: /illumos-gate/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c (revision 5bbb4db2c3f208d12bf0fd11769728f9e5ba66a2)
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 2009 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <synch.h>
33 
34 #include <kmfapiP.h>
35 #include <ber_der.h>
36 /* NSS related headers */
37 
38 #include <mps/nss.h>
39 #include <mps/cert.h>
40 #include <mps/certdb.h>
41 #include <mps/secoid.h>
42 #include <mps/secder.h>
43 #include <mps/secerr.h>
44 #include <mps/cryptohi.h>
45 #include <mps/keyhi.h>
46 #include <mps/keythi.h>
47 #include <mps/pk11func.h>
48 #include <mps/pk11pqg.h>
49 #include <mps/pkcs12.h>
50 #include <mps/p12plcy.h>
51 #include <mps/prerror.h>
52 
53 #define	NSS_OK		0
54 
55 mutex_t init_lock = DEFAULTMUTEX;
56 static int nss_initialized = 0;
57 
58 KMF_RETURN
59 NSS_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
60 
61 KMF_RETURN
62 NSS_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
63 
64 void
65 NSS_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
66 
67 KMF_RETURN
68 NSS_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
69 
70 KMF_RETURN
71 NSS_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
72 
73 KMF_RETURN
74 NSS_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
75 
76 KMF_RETURN
77 NSS_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
78 
79 KMF_RETURN
80 NSS_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
81 
82 KMF_RETURN
83 NSS_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
84 
85 KMF_RETURN
86 NSS_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
87 	KMF_DATA *, KMF_DATA *);
88 
89 KMF_RETURN
90 NSS_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
91 
92 KMF_RETURN
93 NSS_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
94 
95 KMF_RETURN
96 NSS_FindCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
97 
98 KMF_RETURN
99 NSS_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
100 
101 KMF_RETURN
102 NSS_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
103 
104 KMF_RETURN
105 NSS_GetErrorString(KMF_HANDLE_T, char **);
106 
107 KMF_RETURN
108 NSS_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
109 
110 KMF_RETURN
111 NSS_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
112 
113 KMF_RETURN
114 NSS_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
115 	KMF_DATA *, KMF_DATA *);
116 
117 KMF_RETURN
118 NSS_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
119 
120 KMF_RETURN
121 NSS_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
122 
123 KMF_RETURN
124 NSS_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
125 
126 KMF_RETURN
127 NSS_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
128 
129 static
130 KMF_PLUGIN_FUNCLIST nss_plugin_table =
131 {
132 	1,				/* Version */
133 	NSS_ConfigureKeystore,
134 	NSS_FindCert,
135 	NSS_FreeKMFCert,
136 	NSS_StoreCert,
137 	NSS_ImportCert,
138 	NSS_ImportCRL,
139 	NSS_DeleteCert,
140 	NSS_DeleteCRL,
141 	NSS_CreateKeypair,
142 	NSS_FindKey,
143 	NSS_EncodePubKeyData,
144 	NSS_SignData,
145 	NSS_DeleteKey,
146 	NULL    /* ListCRL */,
147 	NSS_FindCRL,
148 	NSS_FindCertInCRL,
149 	NSS_GetErrorString,
150 	NSS_FindPrikeyByCert,
151 	NSS_DecryptData,
152 	NSS_ExportPK12,
153 	NSS_CreateSymKey,
154 	NSS_GetSymKeyValue,
155 	NSS_SetTokenPin,
156 	NULL, /* VerifyData */
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 	SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
176 	SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
177 	SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
178 	SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
179 	SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
180 	SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
181 	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 
686 KMF_RETURN
687 NSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
688 {
689 	KMF_RETURN rv = KMF_OK;
690 	int nssrv;
691 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
692 	CERTCertificate *cert = NULL;
693 	PK11SlotInfo *nss_slot = NULL;
694 	char *certlabel = NULL;
695 	char *issuer = NULL;
696 	char *subject = NULL;
697 	KMF_BIGINT *serial = NULL;
698 	KMF_CERT_VALIDITY  validity;
699 
700 	if (handle == NULL || attrlist == NULL || numattr == 0) {
701 		return (KMF_ERR_BAD_PARAMETER);
702 	}
703 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
704 	if (rv != KMF_OK)
705 		return (rv);
706 
707 	/* Get the search criteria attributes.  They are all optional. */
708 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
709 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
710 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
711 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
712 
713 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
714 	    &validity, NULL);
715 	if (rv != KMF_OK) {
716 		validity = KMF_ALL_CERTS;
717 		rv = KMF_OK;
718 	}
719 
720 	/* Start finding the matched certificates and delete them. */
721 	if (certlabel != NULL) {
722 		cert = PK11_FindCertFromNickname(certlabel, NULL);
723 		if (cert == NULL) {
724 			return (KMF_ERR_CERT_NOT_FOUND);
725 		}
726 
727 		switch (validity) {
728 		case KMF_ALL_CERTS:
729 			break;
730 		case KMF_NONEXPIRED_CERTS:
731 			nssrv = CERT_CertTimesValid(cert);
732 			if (nssrv == SECFailure) {
733 				/* this is an invalid cert - skip it */
734 				goto out;
735 			}
736 			break;
737 		case KMF_EXPIRED_CERTS:
738 			nssrv = CERT_CertTimesValid(cert);
739 			if (nssrv != SECFailure) {
740 				/* this is a valid cert - skip it */
741 				goto out;
742 			}
743 			break;
744 		}
745 		/* delete it from database */
746 		nssrv = SEC_DeletePermCertificate(cert);
747 		if (nssrv) {
748 			SET_ERROR(kmfh, nssrv);
749 			rv = KMF_ERR_INTERNAL;
750 		}
751 	} else {
752 		CERTCertListNode *node;
753 		CERTCertList *certlist = NULL;
754 
755 		rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
756 		    &certlist, validity);
757 
758 		for (node = CERT_LIST_HEAD(certlist);
759 		    !CERT_LIST_END(node, certlist) && rv == KMF_OK;
760 		    node = CERT_LIST_NEXT(node)) {
761 
762 			nssrv = SEC_DeletePermCertificate(node->cert);
763 			if (nssrv) {
764 				SET_ERROR(kmfh, nssrv);
765 				rv = KMF_ERR_INTERNAL;
766 			}
767 		}
768 
769 		if (rv == KMF_OK && certlist != NULL) {
770 			CERT_DestroyCertList(certlist);
771 		} else if (rv == KMF_OK && certlist == NULL) {
772 			rv = KMF_ERR_CERT_NOT_FOUND;
773 		}
774 	}
775 out:
776 	if (nss_slot != NULL) {
777 		PK11_FreeSlot(nss_slot);
778 	}
779 
780 	if (cert != NULL) {
781 		CERT_DestroyCertificate(cert);
782 	}
783 
784 	return (rv);
785 }
786 
787 static void
788 InitRandom(char *filename)
789 {
790 	char buf[2048];
791 	int fd;
792 	PRInt32 count;
793 
794 	fd = open(filename, O_RDONLY);
795 	if (!fd)
796 		return;
797 
798 	count = read(fd, buf, sizeof (buf));
799 	if (count > 0) {
800 		PK11_RandomUpdate(buf, count);
801 	}
802 
803 	(void) close(fd);
804 }
805 
806 KMF_RETURN
807 NSS_CreateKeypair(KMF_HANDLE_T handle,
808 	int numattr, KMF_ATTRIBUTE *attrlist)
809 {
810 	KMF_RETURN rv = KMF_OK;
811 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
812 	PK11RSAGenParams rsaparams;
813 	void *nssparams;
814 	CK_MECHANISM_TYPE mechanism;
815 	ulong_t publicExponent = 0x010001;
816 	PK11SlotInfo *nss_slot = NULL;
817 	SECKEYPrivateKey *NSSprivkey = NULL;
818 	SECKEYPublicKey *NSSpubkey = 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 {
939 		rv = KMF_ERR_BAD_PARAMETER;
940 		goto cleanup;
941 	}
942 
943 	NSSprivkey = PK11_GenerateKeyPair(nss_slot, mechanism, nssparams,
944 	    &NSSpubkey,
945 	    storekey, /* isPermanent */
946 	    PR_TRUE, /* isSensitive */
947 	    (void *)cred.cred);
948 
949 	if (NSSprivkey == NULL || NSSpubkey == NULL) {
950 		SET_ERROR(kmfh, PORT_GetError());
951 		rv = KMF_ERR_KEYGEN_FAILED;
952 	} else {
953 		if (keylabel != NULL && strlen(keylabel)) {
954 			(void) PK11_SetPrivateKeyNickname(NSSprivkey,
955 			    keylabel);
956 			(void) PK11_SetPublicKeyNickname(NSSpubkey, keylabel);
957 		}
958 		/* Now, convert it to a KMF_KEY object for the framework */
959 		privkey->kstype = KMF_KEYSTORE_NSS;
960 		privkey->keyalg = keytype;
961 		privkey->keyclass = KMF_ASYM_PRI;
962 		privkey->keylabel = PK11_GetPrivateKeyNickname(NSSprivkey);
963 		privkey->keyp = (void *)NSSprivkey;
964 
965 		pubkey->kstype = KMF_KEYSTORE_NSS;
966 		pubkey->keyalg = keytype;
967 		pubkey->keyp = (void *)NSSpubkey;
968 		pubkey->keyclass = KMF_ASYM_PUB;
969 		pubkey->keylabel = PK11_GetPublicKeyNickname(NSSpubkey);
970 
971 		rv = KMF_OK;
972 	}
973 cleanup:
974 	if (rv != KMF_OK) {
975 		if (NSSpubkey)
976 			PK11_DeleteTokenPublicKey(NSSpubkey);
977 		if (NSSprivkey)
978 			PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE);
979 
980 		privkey->keyp = NULL;
981 		pubkey->keyp = NULL;
982 	}
983 
984 	if (keylabel)
985 		free(keylabel);
986 
987 	if (pqgParams != NULL)
988 		PK11_PQG_DestroyParams(pqgParams);
989 
990 	if (nss_slot != NULL)
991 		PK11_FreeSlot(nss_slot);
992 
993 	return (rv);
994 }
995 
996 KMF_RETURN
997 NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
998     KMF_OID *AlgOID, KMF_DATA *tobesigned,
999     KMF_DATA *output)
1000 {
1001 	KMF_RETURN		ret = KMF_OK;
1002 	KMF_ALGORITHM_INDEX	AlgId;
1003 	SECOidTag		signAlgTag;
1004 	SECKEYPrivateKey	*NSSprivkey = NULL;
1005 	SECStatus		rv;
1006 	SECItem			signed_data;
1007 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1008 
1009 	signed_data.data = 0;
1010 	if (key == NULL || AlgOID == NULL ||
1011 	    tobesigned == NULL || output == NULL ||
1012 	    tobesigned->Data == NULL ||
1013 	    output->Data == NULL)
1014 		return (KMF_ERR_BAD_PARAMETER);
1015 
1016 	/* Map the OID to a NSS algorithm */
1017 	AlgId = x509_algoid_to_algid(AlgOID);
1018 	if (AlgId == KMF_ALGID_NONE)
1019 		return (KMF_ERR_BAD_PARAMETER);
1020 
1021 	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1022 
1023 	if (AlgId == KMF_ALGID_MD5WithRSA)
1024 		signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1025 	else if (AlgId == KMF_ALGID_MD2WithRSA)
1026 		signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1027 	else if (AlgId == KMF_ALGID_SHA1WithRSA)
1028 		signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1029 	else if (AlgId == KMF_ALGID_SHA1WithDSA)
1030 		signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
1031 	else
1032 		return (KMF_ERR_BAD_PARAMETER);
1033 
1034 	rv = SEC_SignData(&signed_data, tobesigned->Data,
1035 	    tobesigned->Length, NSSprivkey, signAlgTag);
1036 
1037 	if (rv != 0) {
1038 		SET_ERROR(kmfh, rv);
1039 		return (KMF_ERR_INTERNAL);
1040 	}
1041 
1042 	if (signed_data.len <= output->Length) {
1043 		(void) memcpy(output->Data, signed_data.data, signed_data.len);
1044 		output->Length = signed_data.len;
1045 	} else {
1046 		output->Length = 0;
1047 		ret = KMF_ERR_BAD_PARAMETER;
1048 	}
1049 	free(signed_data.data);
1050 
1051 	return (ret);
1052 }
1053 
1054 KMF_RETURN
1055 NSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1056 	KMF_DATA *encoded)
1057 {
1058 	KMF_RETURN ret = KMF_OK;
1059 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1060 	SECItem *rvitem;
1061 	CERTSubjectPublicKeyInfo *spki = NULL;
1062 
1063 	if (keyp == NULL || encoded == NULL || keyp->keyp == NULL)
1064 		return (KMF_ERR_BAD_PARAMETER);
1065 
1066 	spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp);
1067 	if (spki == NULL) {
1068 		SET_ERROR(kmfh, PORT_GetError());
1069 		return (KMF_ERR_MEMORY);
1070 	}
1071 
1072 	rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki,
1073 	    CERT_SubjectPublicKeyInfoTemplate);
1074 	if (rvitem != NULL) {
1075 		encoded->Data = malloc(rvitem->len);
1076 		if (encoded->Data == NULL) {
1077 			ret = KMF_ERR_MEMORY;
1078 		} else {
1079 			(void) memcpy(encoded->Data, rvitem->data, rvitem->len);
1080 			encoded->Length = rvitem->len;
1081 		}
1082 		SECITEM_FreeItem(rvitem, TRUE);
1083 	} else {
1084 		SET_ERROR(kmfh, PORT_GetError());
1085 		encoded->Data = NULL;
1086 		encoded->Length = 0;
1087 		ret = KMF_ERR_ENCODING;
1088 	}
1089 	SECKEY_DestroySubjectPublicKeyInfo(spki);
1090 
1091 	return (ret);
1092 }
1093 
1094 KMF_RETURN
1095 NSS_DeleteKey(KMF_HANDLE_T handle,
1096 	int numattr, KMF_ATTRIBUTE *attrlist)
1097 {
1098 	KMF_RETURN rv = KMF_OK;
1099 	PK11SlotInfo *nss_slot = NULL;
1100 	KMF_KEY_HANDLE *key;
1101 	KMF_CREDENTIAL cred;
1102 	boolean_t delete_token = B_TRUE;
1103 
1104 	if (handle == NULL || attrlist == NULL || numattr == 0) {
1105 		return (KMF_ERR_BAD_PARAMETER);
1106 	}
1107 	/*
1108 	 * "delete_token" means to clear it from the token storage as well
1109 	 * as from memory.
1110 	 */
1111 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1112 	if (key == NULL || key->keyp == NULL)
1113 		return (KMF_ERR_BAD_PARAMETER);
1114 
1115 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1116 	    (void *)&delete_token, NULL);
1117 	if (rv != KMF_OK)
1118 		/* "delete_token" is optional. Default is TRUE */
1119 		rv = KMF_OK;
1120 
1121 	if (delete_token) {
1122 		SECStatus nssrv = SECSuccess;
1123 		if (key->keyclass != KMF_ASYM_PUB &&
1124 		    key->keyclass != KMF_ASYM_PRI &&
1125 		    key->keyclass != KMF_SYMMETRIC)
1126 			return (KMF_ERR_BAD_KEY_CLASS);
1127 
1128 		rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1129 		if (rv != KMF_OK) {
1130 			return (rv);
1131 		}
1132 
1133 		rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1134 		    (void *)&cred, NULL);
1135 		if (rv != KMF_OK)
1136 			return (KMF_ERR_BAD_PARAMETER);
1137 
1138 		rv = nss_authenticate(handle, nss_slot, &cred);
1139 		if (rv != KMF_OK) {
1140 			return (rv);
1141 		}
1142 
1143 		if (key->keyclass == KMF_ASYM_PUB) {
1144 			nssrv = PK11_DeleteTokenPublicKey(
1145 			    (SECKEYPublicKey *)key->keyp);
1146 		} else if (key->keyclass == KMF_ASYM_PRI) {
1147 			nssrv = PK11_DeleteTokenPrivateKey(
1148 			    (SECKEYPrivateKey *)key->keyp, PR_TRUE);
1149 		} else if (key->keyclass == KMF_SYMMETRIC) {
1150 			nssrv = PK11_DeleteTokenSymKey(
1151 			    (PK11SymKey *) key->keyp);
1152 			if (nssrv == SECSuccess)
1153 				PK11_FreeSymKey((PK11SymKey *) key->keyp);
1154 		}
1155 		if (nssrv != SECSuccess) {
1156 			SET_ERROR(handle, PORT_GetError());
1157 			rv = KMF_ERR_INTERNAL;
1158 		}
1159 	} else {
1160 		if (key->keyclass == KMF_ASYM_PUB) {
1161 			SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp);
1162 		} else if (key->keyclass == KMF_ASYM_PRI) {
1163 			SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp);
1164 		} else if (key->keyclass == KMF_SYMMETRIC) {
1165 			PK11_FreeSymKey((PK11SymKey *) key->keyp);
1166 		} else {
1167 			return (KMF_ERR_BAD_KEY_CLASS);
1168 		}
1169 	}
1170 	key->keyp = NULL;
1171 
1172 	return (rv);
1173 }
1174 
1175 KMF_RETURN
1176 NSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1177 {
1178 	KMF_RETURN ret = KMF_OK;
1179 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1180 	char *str;
1181 
1182 	/* Get the error string in the default language */
1183 	str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode);
1184 
1185 	if (str != NULL) {
1186 		*msgstr = (char *)strdup(str);
1187 		if ((*msgstr) == NULL)
1188 			ret = KMF_ERR_MEMORY;
1189 	} else {
1190 		*msgstr = NULL;
1191 	}
1192 
1193 	return (ret);
1194 }
1195 
1196 KMF_RETURN
1197 NSS_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1198 {
1199 	KMF_RETURN rv = KMF_OK;
1200 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1201 	PK11SlotInfo *nss_slot = NULL;
1202 	KMF_CREDENTIAL cred;
1203 	KMF_KEY_HANDLE *key = NULL;
1204 	KMF_DATA *cert = NULL;
1205 	CERTCertificate *nss_cert = NULL;
1206 	SECKEYPrivateKey* privkey = NULL;
1207 
1208 	if (handle == NULL || attrlist == NULL || numattr == 0) {
1209 		return (KMF_ERR_BAD_PARAMETER);
1210 	}
1211 
1212 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1213 	if (rv != KMF_OK)
1214 		return (rv);
1215 
1216 	/* Get the credential */
1217 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1218 	    (void *)&cred, NULL);
1219 	if (rv != KMF_OK)
1220 		return (KMF_ERR_BAD_PARAMETER);
1221 	rv = nss_authenticate(handle, nss_slot, &cred);
1222 	if (rv != KMF_OK)
1223 		return (rv);
1224 
1225 	/* Get the key handle */
1226 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1227 	if (key == NULL)
1228 		return (KMF_ERR_BAD_PARAMETER);
1229 
1230 	/* Get the cert data and decode it */
1231 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1232 	if (cert == NULL || cert->Data == NULL)
1233 		return (KMF_ERR_BAD_PARAMETER);
1234 
1235 	nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
1236 	    cert->Length);
1237 	if (nss_cert == NULL) {
1238 		SET_ERROR(kmfh, PORT_GetError());
1239 		return (KMF_ERR_BAD_CERT_FORMAT);
1240 	}
1241 
1242 	privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL);
1243 	if (privkey == NULL) {
1244 		SET_ERROR(kmfh, PORT_GetError());
1245 		return (KMF_ERR_KEY_NOT_FOUND);
1246 	}
1247 
1248 	key->kstype = KMF_KEYSTORE_NSS;
1249 	key->keyclass = KMF_ASYM_PRI;
1250 	key->keyp = (void *)privkey;
1251 	key->keylabel = PK11_GetPrivateKeyNickname(privkey);
1252 
1253 	CERT_DestroyCertificate(nss_cert);
1254 
1255 	return (KMF_OK);
1256 }
1257 
1258 
1259 KMF_RETURN
1260 NSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1261 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
1262 	KMF_DATA *output)
1263 {
1264 	KMF_RETURN		ret = KMF_OK;
1265 	SECKEYPrivateKey	*NSSprivkey = NULL;
1266 	SECStatus		rv;
1267 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1268 	unsigned int in_len = 0, out_len = 0;
1269 	unsigned int total_decrypted = 0, modulus_len = 0;
1270 	uint8_t *in_data, *out_data;
1271 	int i, blocks;
1272 
1273 	if (key == NULL || AlgOID == NULL ||
1274 	    ciphertext == NULL || output == NULL ||
1275 	    ciphertext->Data == NULL ||
1276 	    output->Data == NULL)
1277 		return (KMF_ERR_BAD_PARAMETER);
1278 
1279 	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1280 	modulus_len = PK11_GetPrivateModulusLen(NSSprivkey);
1281 
1282 	blocks = ciphertext->Length/modulus_len;
1283 	out_data = output->Data;
1284 	in_data = ciphertext->Data;
1285 	out_len = modulus_len - 11;
1286 	in_len = modulus_len;
1287 
1288 	for (i = 0; i < blocks; i++) {
1289 		rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data,
1290 		    &out_len, ciphertext->Length, in_data, in_len);
1291 
1292 		if (rv != 0) {
1293 			SET_ERROR(kmfh, rv);
1294 			return (KMF_ERR_INTERNAL);
1295 		}
1296 
1297 		out_data += out_len;
1298 		total_decrypted += out_len;
1299 		in_data += in_len;
1300 	}
1301 
1302 	output->Length = total_decrypted;
1303 
1304 	return (ret);
1305 }
1306 
1307 static KMF_KEY_ALG
1308 pk11keytype2kmf(CK_KEY_TYPE type)
1309 {
1310 	switch (type) {
1311 	case CKK_RSA:
1312 		return (KMF_RSA);
1313 	case CKK_DSA:
1314 		return (KMF_RSA);
1315 	case CKK_AES:
1316 		return (KMF_AES);
1317 	case CKK_RC4:
1318 		return (KMF_RC4);
1319 	case CKK_DES:
1320 		return (KMF_DES);
1321 	case CKK_DES3:
1322 		return (KMF_DES3);
1323 	default:
1324 		/* not supported */
1325 		return (KMF_KEYALG_NONE);
1326 	}
1327 }
1328 
1329 KMF_RETURN
1330 NSS_FindKey(KMF_HANDLE_T handle,
1331 	int numattr, KMF_ATTRIBUTE *attrlist)
1332 {
1333 	KMF_RETURN rv;
1334 	SECKEYPrivateKeyList *prilist;
1335 	SECKEYPrivateKeyListNode *prinode;
1336 	SECKEYPublicKeyList *publist;
1337 	SECKEYPublicKeyListNode *pubnode;
1338 	PK11SlotInfo *nss_slot = NULL;
1339 	PK11SymKey *symlist = NULL;
1340 	int count;
1341 	uint32_t maxkeys;
1342 	KMF_KEY_HANDLE *keys;
1343 	uint32_t *numkeys;
1344 	KMF_CREDENTIAL *cred = NULL;
1345 	KMF_KEY_CLASS keyclass;
1346 	char *findLabel;
1347 	char *nick;
1348 	int match = 0;
1349 	KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
1350 
1351 	if (handle == NULL || attrlist == NULL || numattr == 0) {
1352 		return (KMF_ERR_BAD_PARAMETER);
1353 	}
1354 
1355 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1356 	if (numkeys == NULL)
1357 		return (KMF_ERR_BAD_PARAMETER);
1358 
1359 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1360 	if (rv != KMF_OK) {
1361 		return (rv);
1362 	}
1363 
1364 	/* It is OK if this is NULL, we dont need a cred to find public keys */
1365 	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1366 
1367 	if (cred != NULL) {
1368 		rv = nss_authenticate(handle, nss_slot, cred);
1369 		if (rv != KMF_OK) {
1370 			return (rv);
1371 		}
1372 	}
1373 
1374 	maxkeys = *numkeys;
1375 	if (maxkeys == 0)
1376 		maxkeys = 0xFFFFFFFF;
1377 	*numkeys = 0;
1378 
1379 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
1380 	    (void *)&keyclass, NULL);
1381 	if (rv != KMF_OK)
1382 		return (KMF_ERR_BAD_PARAMETER);
1383 
1384 	findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1385 
1386 	if (keyclass == KMF_ASYM_PUB) {
1387 		publist = PK11_ListPublicKeysInSlot(nss_slot, findLabel);
1388 		if (publist == NULL) {
1389 			rv = KMF_ERR_KEY_NOT_FOUND;
1390 			goto cleanup;
1391 		}
1392 	} else if (keyclass == KMF_ASYM_PRI) {
1393 		prilist = PK11_ListPrivKeysInSlot(nss_slot, findLabel, NULL);
1394 		if (prilist == NULL) {
1395 			rv = KMF_ERR_KEY_NOT_FOUND;
1396 			goto cleanup;
1397 		}
1398 	} else if (keyclass == KMF_SYMMETRIC) {
1399 		symlist = PK11_ListFixedKeysInSlot(nss_slot, findLabel, NULL);
1400 		if (symlist == NULL) {
1401 			rv = KMF_ERR_KEY_NOT_FOUND;
1402 			goto cleanup;
1403 		}
1404 	} else {
1405 		rv = KMF_ERR_BAD_KEY_CLASS;
1406 		goto cleanup;
1407 	}
1408 
1409 	keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1410 	/* it is okay to have "keys" contains NULL */
1411 
1412 	if (keyclass == KMF_ASYM_PUB) {
1413 		for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist);
1414 		    !PUBKEY_LIST_END(pubnode, publist) && count < maxkeys;
1415 		    pubnode = PUBKEY_LIST_NEXT(pubnode)) {
1416 			match = 0;
1417 			/*
1418 			 * Due to bug in NSS, we have to manually match
1419 			 * the labels to be sure we have a match.
1420 			 */
1421 			nick = PK11_GetPublicKeyNickname(pubnode->key);
1422 			if (findLabel) {
1423 				match = (nick &&
1424 				    (strcmp(nick, findLabel) == 0));
1425 			} else {
1426 				/* always match if findLabel is NULL */
1427 				match = 1;
1428 			}
1429 			if (keys != NULL && match) {
1430 				keys[count].kstype = KMF_KEYSTORE_NSS;
1431 				keys[count].keyclass = KMF_ASYM_PUB;
1432 				keys[count].keyp = (void *)pubnode->key;
1433 				keys[count].keylabel = nick;
1434 
1435 				if (pubnode->key->keyType == rsaKey)
1436 					keys[count].keyalg = KMF_RSA;
1437 				else if (pubnode->key->keyType == dsaKey)
1438 					keys[count].keyalg = KMF_DSA;
1439 			}
1440 			if (match)
1441 				count++;
1442 		}
1443 		*numkeys = count;
1444 	} else if (keyclass == KMF_ASYM_PRI) {
1445 		for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist);
1446 		    !PRIVKEY_LIST_END(prinode, prilist) && count < maxkeys;
1447 		    prinode = PRIVKEY_LIST_NEXT(prinode)) {
1448 			match = 0;
1449 			/*
1450 			 * Due to bug in NSS, we have to manually match
1451 			 * the labels to be sure we have a match.
1452 			 */
1453 			nick = PK11_GetPrivateKeyNickname(prinode->key);
1454 			if (findLabel) {
1455 				match = (nick &&
1456 				    (strcmp(nick, findLabel) == 0));
1457 			} else {
1458 				/* always match if findLabel is NULL */
1459 				match = 1;
1460 			}
1461 			if (keys != NULL && match) {
1462 				keys[count].kstype = KMF_KEYSTORE_NSS;
1463 				keys[count].keyclass = KMF_ASYM_PRI;
1464 				keys[count].keyp = (void *)prinode->key;
1465 				keys[count].keylabel = nick;
1466 
1467 				if (prinode->key->keyType == rsaKey)
1468 					keys[count].keyalg = KMF_RSA;
1469 				else if (prinode->key->keyType == dsaKey)
1470 					keys[count].keyalg = KMF_DSA;
1471 			}
1472 			if (match)
1473 				count++;
1474 		}
1475 		*numkeys = count;
1476 	} else if (keyclass == KMF_SYMMETRIC) {
1477 		count = 0;
1478 		rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1479 		    (void *)&keytype, NULL);
1480 		if (rv != KMF_OK)
1481 			rv = KMF_OK;
1482 		while (symlist && count < maxkeys) {
1483 			PK11SymKey *symkey = symlist;
1484 			CK_KEY_TYPE type;
1485 			KMF_KEY_ALG keyalg;
1486 
1487 			match = 0;
1488 			type = PK11_GetSymKeyType(symkey);
1489 			keyalg = pk11keytype2kmf(type);
1490 
1491 			symlist = PK11_GetNextSymKey(symkey);
1492 
1493 			/*
1494 			 * If keytype is specified in the searching parameter,
1495 			 * check the keytype and skip the key if its keytype
1496 			 * doesn't match.
1497 			 */
1498 			if (keytype != KMF_KEYALG_NONE && keytype != keyalg) {
1499 				/* free that key since we arent using it */
1500 				PK11_FreeSymKey(symkey);
1501 				continue;
1502 			}
1503 			/*
1504 			 * Due to bug in NSS, we have to manually match
1505 			 * the labels to be sure we have a match.
1506 			 */
1507 			nick = PK11_GetSymKeyNickname(symkey);
1508 			if (findLabel) {
1509 				match = (nick &&
1510 				    (strcmp(nick, findLabel) == 0));
1511 			} else {
1512 				/* always match if findLabel is NULL */
1513 				match = 1;
1514 			}
1515 
1516 			if (keys != NULL && match) {
1517 				keys[count].kstype = KMF_KEYSTORE_NSS;
1518 				keys[count].keyclass = KMF_SYMMETRIC;
1519 				keys[count].keyp = (void *) symkey;
1520 				keys[count].keylabel = nick;
1521 				keys[count].keyalg = keyalg;
1522 			} else {
1523 				PK11_FreeSymKey(symkey);
1524 			}
1525 			if (match)
1526 				count++;
1527 		}
1528 		/*
1529 		 * Cleanup memory for unused keys.
1530 		 */
1531 		while (symlist != NULL) {
1532 			PK11SymKey *symkey = symlist;
1533 
1534 			PK11_FreeSymKey(symkey);
1535 			symlist = PK11_GetNextSymKey(symkey);
1536 		}
1537 		*numkeys = count;
1538 	}
1539 
1540 cleanup:
1541 	if (nss_slot != NULL) {
1542 		PK11_FreeSlot(nss_slot);
1543 	}
1544 
1545 	return (rv);
1546 }
1547 
1548 static SECStatus
1549 p12u_SwapUnicodeBytes(SECItem *uniItem)
1550 {
1551 	unsigned int i;
1552 	unsigned char a;
1553 	if ((uniItem == NULL) || (uniItem->len % 2)) {
1554 		return (SECFailure);
1555 		}
1556 	for (i = 0; i < uniItem->len; i += 2) {
1557 		a = uniItem->data[i];
1558 		uniItem->data[i] = uniItem->data[i+1];
1559 		uniItem->data[i+1] = a;
1560 	}
1561 	return (SECSuccess);
1562 }
1563 
1564 static PRBool
1565 p12u_ucs2_ascii_conversion_function(
1566 	PRBool		toUnicode,
1567 	unsigned char	*inBuf,
1568 	unsigned int	inBufLen,
1569 	unsigned char	*outBuf,
1570 	unsigned int	maxOutBufLen,
1571 	unsigned int	*outBufLen,
1572 	PRBool		swapBytes)
1573 {
1574 	SECItem it = { 0 };
1575 	SECItem *dup = NULL;
1576 	PRBool ret;
1577 
1578 	it.data = inBuf;
1579 	it.len = inBufLen;
1580 	dup = SECITEM_DupItem(&it);
1581 	/*
1582 	 * If converting Unicode to ASCII, swap bytes before conversion
1583 	 * as neccessary.
1584 	 */
1585 	if (!toUnicode && swapBytes) {
1586 		if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
1587 			SECITEM_ZfreeItem(dup, PR_TRUE);
1588 			return (PR_FALSE);
1589 		}
1590 	}
1591 	/* Perform the conversion. */
1592 	ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
1593 	    outBuf, maxOutBufLen, outBufLen);
1594 	if (dup)
1595 		SECITEM_ZfreeItem(dup, PR_TRUE);
1596 
1597 	return (ret);
1598 }
1599 
1600 static PRBool
1601 p12u_OpenFile(p12uContext *p12ctx, PRBool fileRead)
1602 {
1603 	if (!p12ctx || !p12ctx->filename) {
1604 		return (PR_FALSE);
1605 	}
1606 
1607 	if (fileRead) {
1608 		p12ctx->file = PR_Open(p12ctx->filename, PR_RDONLY, 0400);
1609 	} else {
1610 		p12ctx->file = PR_Open(p12ctx->filename,
1611 		    PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600);
1612 	}
1613 
1614 	if (!p12ctx->file) {
1615 		p12ctx->error = PR_TRUE;
1616 		return (PR_FALSE);
1617 	}
1618 
1619 	return (PR_TRUE);
1620 }
1621 
1622 static void
1623 p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
1624 {
1625 	if (!ppCtx || !(*ppCtx)) {
1626 		return;
1627 	}
1628 
1629 	if ((*ppCtx)->file != NULL) {
1630 		PR_Close((*ppCtx)->file);
1631 	}
1632 
1633 	if ((*ppCtx)->filename != NULL) {
1634 		if (removeFile) {
1635 			PR_Delete((*ppCtx)->filename);
1636 		}
1637 		free((*ppCtx)->filename);
1638 	}
1639 
1640 	free(*ppCtx);
1641 	*ppCtx = NULL;
1642 }
1643 
1644 static p12uContext *
1645 p12u_InitContext(PRBool fileImport, char *filename)
1646 {
1647 	p12uContext *p12ctx;
1648 
1649 	p12ctx = PORT_ZNew(p12uContext);
1650 	if (!p12ctx) {
1651 		return (NULL);
1652 	}
1653 
1654 	p12ctx->error = PR_FALSE;
1655 	p12ctx->errorValue = 0;
1656 	p12ctx->filename = strdup(filename);
1657 
1658 	if (!p12u_OpenFile(p12ctx, fileImport)) {
1659 		p12u_DestroyContext(&p12ctx, PR_FALSE);
1660 		return (NULL);
1661 	}
1662 
1663 	return (p12ctx);
1664 }
1665 
1666 static void
1667 p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
1668 {
1669 	p12uContext *p12cxt = arg;
1670 	int writeLen;
1671 
1672 	if (!p12cxt || (p12cxt->error == PR_TRUE)) {
1673 		return;
1674 	}
1675 
1676 	if (p12cxt->file == NULL) {
1677 		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1678 		p12cxt->error = PR_TRUE;
1679 		return;
1680 	}
1681 
1682 	writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
1683 
1684 	if (writeLen != (int)len) {
1685 		PR_Close(p12cxt->file);
1686 		free(p12cxt->filename);
1687 		p12cxt->filename = NULL;
1688 		p12cxt->file = NULL;
1689 		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1690 		p12cxt->error = PR_TRUE;
1691 	}
1692 }
1693 
1694 #define	HANDLE_NSS_ERROR(r) {\
1695 	SET_ERROR(kmfh, PORT_GetError()); \
1696 	rv = r; \
1697 	goto out; }
1698 
1699 static KMF_RETURN
1700 add_cert_to_bag(SEC_PKCS12ExportContext *p12ecx,
1701 	CERTCertificate *cert, SECItem *pwitem)
1702 {
1703 	KMF_RETURN rv = KMF_OK;
1704 	SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
1705 
1706 	keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
1707 	if (PK11_IsFIPS()) {
1708 		certSafe = keySafe;
1709 	} else {
1710 		certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
1711 		    SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
1712 	}
1713 
1714 	if (!certSafe || !keySafe) {
1715 		rv = KMF_ERR_INTERNAL;
1716 		goto out;
1717 	}
1718 
1719 	if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
1720 	    CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
1721 	    SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
1722 	    != SECSuccess) {
1723 		rv = KMF_ERR_INTERNAL;
1724 	}
1725 out:
1726 	return (rv);
1727 }
1728 
1729 KMF_RETURN
1730 NSS_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1731 {
1732 	KMF_RETURN rv;
1733 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
1734 	SEC_PKCS12ExportContext *p12ecx = NULL;
1735 	p12uContext *p12ctx = NULL;
1736 	CERTCertList *certlist = NULL;
1737 	CERTCertificate *nsscert = NULL;
1738 	CERTCertListNode* node = NULL;
1739 	PK11SlotInfo	*slot = NULL;
1740 	SECItem pwitem = {NULL, 0};
1741 	KMF_CREDENTIAL *cred = NULL;
1742 	KMF_CREDENTIAL *p12cred = NULL;
1743 	char *certlabel = NULL;
1744 	char *issuer = NULL;
1745 	char *subject = NULL;
1746 	KMF_BIGINT *serial = NULL;
1747 	char *filename = NULL;
1748 
1749 	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1750 		return (KMF_ERR_BAD_PARAMETER);
1751 	}
1752 
1753 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &slot);
1754 	if (rv != KMF_OK)
1755 		return (rv);
1756 
1757 	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1758 	if (cred == NULL)
1759 		return (KMF_ERR_BAD_PARAMETER);
1760 
1761 	rv = nss_authenticate(handle, slot, cred);
1762 	if (rv != KMF_OK)
1763 		return (rv);
1764 
1765 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
1766 	if (p12cred  == NULL)
1767 		return (KMF_ERR_BAD_PARAMETER);
1768 
1769 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
1770 	    numattr);
1771 	if (filename == NULL)
1772 		return (KMF_ERR_BAD_PARAMETER);
1773 
1774 	/* Get optional search criteria attributes */
1775 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
1776 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1777 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1778 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1779 
1780 	/*
1781 	 * Find the certificate(s) first.
1782 	 */
1783 	if (certlabel != NULL) {
1784 		nsscert = PK11_FindCertFromNickname(certlabel, NULL);
1785 		if (nsscert == NULL) {
1786 			HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND)
1787 		}
1788 	} else {
1789 		rv = nss_find_matching_certs(slot, issuer, subject, serial,
1790 		    &certlist, 0);
1791 
1792 		if (rv == KMF_OK && certlist == NULL) {
1793 			return (KMF_ERR_CERT_NOT_FOUND);
1794 		}
1795 		if (rv != KMF_OK)
1796 			return (rv);
1797 	}
1798 
1799 	/*
1800 	 * The KMF_CREDENTIAL holds the password to use for
1801 	 * encrypting the PKCS12 key information.
1802 	 */
1803 	pwitem.data = (uchar_t *)p12cred->cred;
1804 	pwitem.len = p12cred->credlen;
1805 
1806 	p12ctx = p12u_InitContext(PR_FALSE, filename);
1807 	if (!p12ctx) {
1808 		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1809 	}
1810 
1811 	PORT_SetUCS2_ASCIIConversionFunction(
1812 	    p12u_ucs2_ascii_conversion_function);
1813 
1814 	p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, NULL);
1815 	if (!p12ecx) {
1816 		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1817 	}
1818 
1819 	if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
1820 	    != SECSuccess) {
1821 		HANDLE_NSS_ERROR(KMF_ERR_INTERNAL)
1822 	}
1823 
1824 	/*
1825 	 * NSS actually supports storing a list of keys and certs
1826 	 * in the PKCS#12 PDU.  Nice feature.
1827 	 */
1828 	if (certlist != NULL) {
1829 		for (node = CERT_LIST_HEAD(certlist);
1830 		    !CERT_LIST_END(node, certlist) && rv == KMF_OK;
1831 		    node = CERT_LIST_NEXT(node)) {
1832 			rv = add_cert_to_bag(p12ecx, node->cert, &pwitem);
1833 		}
1834 	} else if (nsscert != NULL) {
1835 		rv = add_cert_to_bag(p12ecx, nsscert, &pwitem);
1836 	}
1837 
1838 	if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx)
1839 	    != SECSuccess) {
1840 		HANDLE_NSS_ERROR(KMF_ERR_ENCODING)
1841 	}
1842 out:
1843 	if (nsscert)
1844 		CERT_DestroyCertificate(nsscert);
1845 
1846 	if (certlist)
1847 		CERT_DestroyCertList(certlist);
1848 
1849 	if (p12ctx)
1850 		p12u_DestroyContext(&p12ctx, PR_FALSE);
1851 
1852 	if (p12ecx)
1853 		SEC_PKCS12DestroyExportContext(p12ecx);
1854 
1855 	return (rv);
1856 }
1857 
1858 #define	SETATTR(t, n, atype, value, size) \
1859 	t[n].type = atype; \
1860 	t[n].pValue = (CK_BYTE *)value; \
1861 	t[n].ulValueLen = (CK_ULONG)size;
1862 
1863 KMF_RETURN
1864 NSS_CreateSymKey(KMF_HANDLE_T handle,
1865 	int numattr, KMF_ATTRIBUTE *attrlist)
1866 {
1867 	KMF_RETURN rv = KMF_OK;
1868 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1869 	PK11SlotInfo *nss_slot = NULL;
1870 	PK11SymKey *nsskey = NULL;
1871 	CK_MECHANISM_TYPE keyType;
1872 	SECStatus nssrv;
1873 	int keySize;
1874 	KMF_KEY_HANDLE *symkey;
1875 	KMF_CREDENTIAL cred;
1876 	uint32_t keylen;
1877 	uint32_t keylen_size = sizeof (uint32_t);
1878 	KMF_KEY_ALG keytype;
1879 	char *keylabel = NULL;
1880 
1881 	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1882 		return (KMF_ERR_BAD_PARAMETER);
1883 	}
1884 
1885 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1886 	if (symkey == NULL)
1887 		return (KMF_ERR_BAD_PARAMETER);
1888 
1889 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, (void *)&keytype,
1890 	    NULL);
1891 	if (rv != KMF_OK)
1892 		return (KMF_ERR_BAD_PARAMETER);
1893 
1894 	rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, &keylen,
1895 	    &keylen_size);
1896 	if (rv == KMF_ERR_ATTR_NOT_FOUND &&
1897 	    (keytype == KMF_DES || keytype == KMF_DES3))
1898 		/* keylength is not required for DES and 3DES */
1899 		rv = KMF_OK;
1900 	if (rv != KMF_OK)
1901 		return (KMF_ERR_BAD_PARAMETER);
1902 
1903 	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1904 	if (keylabel == NULL)
1905 		return (KMF_ERR_BAD_PARAMETER);
1906 
1907 	switch (keytype) {
1908 	case KMF_AES:
1909 		keyType = CKM_AES_KEY_GEN;
1910 		keySize = keylen;
1911 		if (keySize == 0 || (keySize % 8) != 0)
1912 			return (KMF_ERR_BAD_KEY_SIZE);
1913 		break;
1914 	case KMF_RC4:
1915 		keyType = CKM_RC4_KEY_GEN;
1916 		keySize = keylen;
1917 		if (keySize == 0 || (keySize % 8) != 0)
1918 			return (KMF_ERR_BAD_KEY_SIZE);
1919 		break;
1920 	case KMF_DES:
1921 		keyType = CKM_DES_KEY_GEN;
1922 		keySize = 0; /* required by PK11_TokenKeyGen()  */
1923 		break;
1924 	case KMF_DES3:
1925 		keyType = CKM_DES3_KEY_GEN;
1926 		keySize = 0; /* required by PK11_TokenKeyGen() */
1927 		break;
1928 	case KMF_GENERIC_SECRET:
1929 		keyType = CKM_GENERIC_SECRET_KEY_GEN;
1930 		keySize = keylen;
1931 		if (keySize == 0 || (keySize % 8) != 0)
1932 			return (KMF_ERR_BAD_KEY_SIZE);
1933 		break;
1934 	default:
1935 		rv = KMF_ERR_BAD_KEY_TYPE;
1936 		goto out;
1937 	}
1938 
1939 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1940 	if (rv != KMF_OK) {
1941 		return (rv);
1942 	}
1943 
1944 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1945 	    (void *)&cred, NULL);
1946 	if (rv != KMF_OK)
1947 		return (KMF_ERR_BAD_PARAMETER);
1948 
1949 	rv = nss_authenticate(handle, nss_slot, &cred);
1950 	if (rv != KMF_OK) {
1951 		return (rv);
1952 	}
1953 
1954 	/* convert key length to bytes */
1955 	nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize / 8,  NULL,
1956 	    PR_TRUE, (void *)cred.cred);
1957 	if (nsskey == NULL) {
1958 		SET_ERROR(kmfh, PORT_GetError());
1959 		rv = KMF_ERR_KEYGEN_FAILED;
1960 		goto out;
1961 	}
1962 
1963 	nssrv = PK11_SetSymKeyNickname(nsskey, keylabel);
1964 	if (nssrv != SECSuccess) {
1965 		SET_ERROR(kmfh, PORT_GetError());
1966 		rv = KMF_ERR_KEYGEN_FAILED;
1967 		goto out;
1968 	}
1969 
1970 	symkey->kstype = KMF_KEYSTORE_NSS;
1971 	symkey->keyalg = keytype;
1972 	symkey->keyclass = KMF_SYMMETRIC;
1973 	symkey->israw = FALSE;
1974 	symkey->keyp = (void *)nsskey;
1975 
1976 out:
1977 	if (nss_slot != NULL)
1978 		PK11_FreeSlot(nss_slot);
1979 
1980 	if (rv != KMF_OK && nsskey != NULL) {
1981 		PK11_DeleteTokenSymKey(nsskey);
1982 		PK11_FreeSymKey(nsskey);
1983 	}
1984 	return (rv);
1985 }
1986 
1987 KMF_RETURN
1988 NSS_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
1989 	KMF_RAW_SYM_KEY *rkey)
1990 {
1991 	KMF_RETURN rv = KMF_OK;
1992 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1993 	SECItem *value = NULL;
1994 	PK11SymKey *nsskey;
1995 	SECStatus nss_rv;
1996 
1997 	if (kmfh == NULL)
1998 		return (KMF_ERR_UNINITIALIZED);
1999 
2000 	if (symkey == NULL || rkey == NULL)
2001 		return (KMF_ERR_BAD_PARAMETER);
2002 	else if (symkey->keyclass != KMF_SYMMETRIC)
2003 		return (KMF_ERR_BAD_KEY_CLASS);
2004 
2005 	if (symkey->israw) {
2006 		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2007 
2008 		if (rawkey == NULL ||
2009 		    rawkey->rawdata.sym.keydata.val == NULL ||
2010 		    rawkey->rawdata.sym.keydata.len == 0)
2011 			return (KMF_ERR_BAD_KEYHANDLE);
2012 
2013 		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2014 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2015 			return (KMF_ERR_MEMORY);
2016 		(void) memcpy(rkey->keydata.val,
2017 		    rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2018 	} else {
2019 		nsskey = (PK11SymKey *)(symkey->keyp);
2020 		if (nsskey == NULL)
2021 			return (KMF_ERR_BAD_KEYHANDLE);
2022 
2023 		nss_rv = PK11_ExtractKeyValue(nsskey);
2024 		if (nss_rv != SECSuccess) {
2025 			SET_ERROR(kmfh, PORT_GetError());
2026 			rv = KMF_ERR_GETKEYVALUE_FAILED;
2027 			goto out;
2028 		}
2029 
2030 		value = PK11_GetKeyData(nsskey);
2031 		if (value == NULL) {
2032 			SET_ERROR(kmfh, PORT_GetError());
2033 			rv = KMF_ERR_GETKEYVALUE_FAILED;
2034 			goto out;
2035 		}
2036 
2037 		if (value->len == 0 || value->data == NULL) {
2038 			rv = KMF_ERR_GETKEYVALUE_FAILED;
2039 			goto out;
2040 		}
2041 
2042 		rkey->keydata.val = malloc(value->len);
2043 		if (rkey->keydata.val == NULL) {
2044 			rv = KMF_ERR_MEMORY;
2045 			goto out;
2046 		}
2047 		(void) memcpy(rkey->keydata.val, value->data, value->len);
2048 		rkey->keydata.len = value->len;
2049 		(void) memset(value->data, 0, value->len);
2050 	}
2051 out:
2052 	if (value != NULL)
2053 		SECITEM_FreeItem(value, PR_TRUE);
2054 	return (rv);
2055 }
2056 
2057 KMF_RETURN
2058 NSS_SetTokenPin(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2059 {
2060 	KMF_RETURN ret = KMF_OK;
2061 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2062 	int rv;
2063 	PK11SlotInfo *nss_slot = NULL;
2064 	KMF_CREDENTIAL oldcred, newcred;
2065 
2066 	if (handle == NULL || attrlist == NULL || numattr == 0)
2067 		return (KMF_ERR_BAD_PARAMETER);
2068 
2069 	ret = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2070 	    (void *)&oldcred, NULL);
2071 	if (ret != KMF_OK)
2072 		return (KMF_ERR_BAD_PARAMETER);
2073 	ret = kmf_get_attr(KMF_NEWPIN_ATTR, attrlist, numattr,
2074 	    (void *)&newcred, NULL);
2075 	if (ret != KMF_OK)
2076 		return (KMF_ERR_BAD_PARAMETER);
2077 
2078 	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2079 	/* If it was uninitialized, set it */
2080 	if (ret == KMF_ERR_UNINITIALIZED_TOKEN) {
2081 		rv = PK11_InitPin(nss_slot, NULL, newcred.cred);
2082 		if (rv != SECSuccess) {
2083 			SET_ERROR(kmfh, PORT_GetError());
2084 			ret = KMF_ERR_AUTH_FAILED;
2085 		} else {
2086 			ret = KMF_OK;
2087 		}
2088 	} else if (ret == KMF_OK) {
2089 		ret = nss_authenticate(handle, nss_slot, &oldcred);
2090 		if (ret != KMF_OK) {
2091 			return (ret);
2092 		}
2093 		rv = PK11_ChangePW(nss_slot, oldcred.cred, newcred.cred);
2094 		if (rv != SECSuccess) {
2095 			SET_ERROR(kmfh, PORT_GetError());
2096 			ret = KMF_ERR_AUTH_FAILED;
2097 		}
2098 	}
2099 
2100 	return (ret);
2101 }
2102 
2103 KMF_RETURN
2104 NSS_StoreKey(KMF_HANDLE_T handle,
2105 	int numattr, KMF_ATTRIBUTE *attrlist)
2106 {
2107 	KMF_RETURN rv = KMF_OK;
2108 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2109 	PK11SlotInfo *nss_slot = NULL;
2110 	KMF_CREDENTIAL cred = {NULL, 0};
2111 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
2112 	KMF_RAW_KEY_DATA *rawkey = NULL;
2113 	char *keylabel = NULL;
2114 	SECStatus ckrv = SECSuccess;
2115 	SECItem nickname = {NULL, 0};
2116 	CERTCertificate *nss_cert = NULL;
2117 
2118 	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
2119 		return (KMF_ERR_BAD_PARAMETER);
2120 	}
2121 
2122 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2123 	if (rv != KMF_OK) {
2124 		return (rv);
2125 	}
2126 
2127 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2128 	    (void *)&cred, NULL);
2129 	if (rv != KMF_OK)
2130 		return (KMF_ERR_BAD_PARAMETER);
2131 
2132 	rv = nss_authenticate(handle, nss_slot, &cred);
2133 	if (rv != KMF_OK) {
2134 		return (rv);
2135 	}
2136 
2137 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
2138 	if (pubkey == NULL) {
2139 		/* look for private key */
2140 		prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist,
2141 		    numattr);
2142 		if (prikey == NULL)
2143 			/* look for raw key */
2144 			rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR,
2145 			    attrlist, numattr);
2146 	}
2147 
2148 	/* If no keys were found, return error */
2149 	if (pubkey == NULL && prikey == NULL && rawkey == NULL)
2150 		return (KMF_ERR_ATTR_NOT_FOUND);
2151 
2152 	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2153 	if (keylabel != NULL) {
2154 		nickname.data = (uchar_t *)keylabel;
2155 		nickname.len = strlen(keylabel);
2156 	}
2157 
2158 	if (rawkey != NULL) {
2159 		uchar_t ver = 0;
2160 		SECKEYPrivateKeyInfo rpk;
2161 		KMF_DATA derkey = {NULL, 0};
2162 		KMF_DATA *cert;
2163 
2164 		cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2165 		if (cert == NULL)
2166 			return (rv);
2167 		/*
2168 		 * Decode the cert into an NSS CERT object so we can access the
2169 		 * SPKI and KeyUsage data later.
2170 		 */
2171 		nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2172 		    cert->Length);
2173 
2174 		if (nss_cert == NULL) {
2175 			SET_ERROR(kmfh, PORT_GetError());
2176 			rv = KMF_ERR_BAD_CERT_FORMAT;
2177 			goto cleanup;
2178 		}
2179 
2180 		(void) memset(&rpk, 0, sizeof (rpk));
2181 		rpk.arena = NULL;
2182 		rpk.version.type = siUnsignedInteger;
2183 		rpk.version.data = &ver;
2184 		rpk.version.len = 1;
2185 		if (rawkey->keytype == KMF_RSA) {
2186 			rv = DerEncodeRSAPrivateKey(&derkey,
2187 			    &rawkey->rawdata.rsa);
2188 			if (rv != KMF_OK)
2189 				goto cleanup;
2190 
2191 		} else if (rawkey->keytype == KMF_DSA) {
2192 			rv = DerEncodeDSAPrivateKey(&derkey,
2193 			    &rawkey->rawdata.dsa);
2194 			if (rv != KMF_OK)
2195 				goto cleanup;
2196 		}
2197 		rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
2198 		rpk.privateKey.data = derkey.Data;
2199 		rpk.privateKey.len = derkey.Length;
2200 		rpk.attributes = NULL;
2201 
2202 		ckrv = PK11_ImportPrivateKeyInfo(nss_slot, &rpk, &nickname,
2203 		    &nss_cert->subjectPublicKeyInfo.subjectPublicKey, TRUE,
2204 		    TRUE, nss_cert->keyUsage, NULL);
2205 		if (ckrv != CKR_OK) {
2206 			SET_ERROR(kmfh, PORT_GetError());
2207 			rv = KMF_ERR_INTERNAL;
2208 		}
2209 		kmf_free_data(&derkey);
2210 	} else if (pubkey != NULL && pubkey->kstype == KMF_KEYSTORE_NSS) {
2211 		CK_OBJECT_HANDLE pk;
2212 		SECKEYPublicKey *publicKey = (SECKEYPublicKey *) pubkey->keyp;
2213 
2214 		pk = PK11_ImportPublicKey(nss_slot, publicKey, PR_TRUE);
2215 		if (pk == CK_INVALID_HANDLE) {
2216 			SET_ERROR(kmfh, PORT_GetError());
2217 			rv = KMF_ERR_INTERNAL;
2218 		}
2219 	} else if (prikey != NULL && prikey->kstype == KMF_KEYSTORE_NSS) {
2220 		SECKEYPrivateKey *pk;
2221 		SECKEYPrivateKey *privKey = (SECKEYPrivateKey *) prikey->keyp;
2222 
2223 		pk = PK11_LoadPrivKey(nss_slot, privKey, NULL, PR_TRUE,
2224 		    PR_TRUE);
2225 		if (pk == CK_INVALID_HANDLE) {
2226 			SET_ERROR(kmfh, PORT_GetError());
2227 			rv = KMF_ERR_INTERNAL;
2228 		}
2229 		/* We stored it, but don't need the handle anymore */
2230 		SECKEY_DestroyPrivateKey(pk);
2231 	}
2232 
2233 cleanup:
2234 	if (nss_cert != NULL)
2235 		CERT_DestroyCertificate(nss_cert);
2236 	PK11_FreeSlot(nss_slot);
2237 	return (rv);
2238 }
2239 
2240 /*
2241  * This function is called by NSS_StoreCert() and NSS_ImportCert().
2242  * The "label" and "trust_flag" arguments can be NULL.
2243  */
2244 static KMF_RETURN
2245 store_cert(KMF_HANDLE_T handle, PK11SlotInfo *nss_slot, KMF_DATA *cert,
2246     char *label, char *trust_flag)
2247 {
2248 	KMF_RETURN ret = KMF_OK;
2249 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2250 	SECStatus nss_rv;
2251 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2252 	CERTCertificate *nss_cert = NULL;
2253 	CERTCertTrust *nss_trust = NULL;
2254 
2255 	if (nss_slot == NULL || cert == NULL)
2256 		return (KMF_ERR_BAD_PARAMETER);
2257 
2258 	nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2259 	    cert->Length);
2260 	if (nss_cert == NULL) {
2261 		SET_ERROR(kmfh, PORT_GetError());
2262 		ret = KMF_ERR_BAD_CERT_FORMAT;
2263 		goto out;
2264 	}
2265 
2266 	/* Store the cert into the NSS database */
2267 	nss_rv = PK11_ImportCert(nss_slot, nss_cert, CK_INVALID_HANDLE,
2268 	    label, 0);
2269 	if (nss_rv) {
2270 		SET_ERROR(kmfh, nss_rv);
2271 		ret = KMF_ERR_BAD_CERT_FORMAT;
2272 		goto out;
2273 	}
2274 
2275 	/* If trust_flag is NULL, then we are done */
2276 	if (trust_flag == NULL)
2277 		goto out;
2278 
2279 	nss_trust = (CERTCertTrust *) malloc(sizeof (CERTCertTrust));
2280 	if (nss_trust == NULL) {
2281 		ret = KMF_ERR_MEMORY;
2282 		goto out;
2283 	}
2284 
2285 	nss_rv = CERT_DecodeTrustString(nss_trust, trust_flag);
2286 	if (nss_rv) {
2287 		SET_ERROR(kmfh, nss_rv);
2288 		ret = KMF_ERR_BAD_PARAMETER;
2289 		goto out;
2290 	}
2291 
2292 	nss_rv = CERT_ChangeCertTrust(certHandle, nss_cert, nss_trust);
2293 	if (nss_rv) {
2294 		SET_ERROR(kmfh, nss_rv);
2295 		ret = KMF_ERR_BAD_PARAMETER;
2296 	}
2297 
2298 out:
2299 	if (nss_cert != NULL) {
2300 		CERT_DestroyCertificate(nss_cert);
2301 	}
2302 
2303 	if (nss_trust != NULL) {
2304 		free(nss_trust);
2305 	}
2306 
2307 	return (ret);
2308 }
2309 
2310 
2311 KMF_RETURN
2312 NSS_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2313 {
2314 	KMF_RETURN ret = KMF_OK;
2315 	PK11SlotInfo *nss_slot = NULL;
2316 	KMF_DATA *cert = NULL;
2317 	char *label = NULL;
2318 	char *trust_flag = NULL;
2319 
2320 	if (handle == NULL || attrlist == NULL || numattr == 0) {
2321 		return (KMF_ERR_BAD_PARAMETER);
2322 	}
2323 
2324 	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2325 	if (ret != KMF_OK)
2326 		return (ret);
2327 
2328 	/* Get the cert data  */
2329 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2330 	if (cert == NULL || cert->Data == NULL)
2331 		return (KMF_ERR_BAD_PARAMETER);
2332 
2333 	/* The label attribute is optional */
2334 	label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2335 
2336 	/* The trustflag attriburte is optional */
2337 	trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2338 
2339 	ret = store_cert(handle, nss_slot, cert, label, trust_flag);
2340 
2341 out:
2342 	if (nss_slot != NULL) {
2343 		PK11_FreeSlot(nss_slot);
2344 	}
2345 
2346 	return (ret);
2347 }
2348 
2349 
2350 KMF_RETURN
2351 NSS_ImportCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2352 {
2353 	KMF_RETURN ret = KMF_OK;
2354 	PK11SlotInfo *nss_slot = NULL;
2355 	KMF_DATA cert = {NULL, 0};
2356 	KMF_DATA cert_der = {NULL, 0};
2357 	KMF_DATA *cptr = NULL;
2358 	KMF_ENCODE_FORMAT format;
2359 	char *label = NULL;
2360 	char *trust_flag = NULL;
2361 	char *certfile = NULL;
2362 
2363 	if (handle == NULL || attrlist == NULL || numattr == 0) {
2364 		return (KMF_ERR_BAD_PARAMETER);
2365 	}
2366 
2367 	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2368 	if (ret != KMF_OK)
2369 		return (ret);
2370 
2371 	/* Get the input cert filename attribute */
2372 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
2373 	if (certfile == NULL)
2374 		return (KMF_ERR_BAD_PARAMETER);
2375 
2376 	/* Check the cert file and auto-detect the file format of it. */
2377 	ret = kmf_is_cert_file(handle, certfile, &format);
2378 	if (ret != KMF_OK)
2379 		return (ret);
2380 
2381 	ret = kmf_read_input_file(handle, certfile, &cert);
2382 	if (ret != KMF_OK) {
2383 		return (ret);
2384 	}
2385 
2386 	/*
2387 	 * If the imported cert is in PEM format, convert it to
2388 	 * DER format in order to store it in NSS token.
2389 	 */
2390 	if (format == KMF_FORMAT_PEM) {
2391 		int derlen;
2392 		ret = kmf_pem_to_der(cert.Data, cert.Length,
2393 		    &cert_der.Data, &derlen);
2394 		if (ret != KMF_OK) {
2395 			goto cleanup;
2396 		}
2397 		cert_der.Length = (size_t)derlen;
2398 		cptr = &cert_der;
2399 	} else {
2400 		cptr = &cert;
2401 	}
2402 
2403 	label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2404 	trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2405 	ret = store_cert(handle, nss_slot, cptr, label, trust_flag);
2406 
2407 cleanup:
2408 	if (format == KMF_FORMAT_PEM) {
2409 		kmf_free_data(&cert_der);
2410 	}
2411 
2412 	kmf_free_data(&cert);
2413 
2414 	return (ret);
2415 }
2416 
2417 
2418 KMF_RETURN
2419 NSS_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2420 {
2421 	KMF_RETURN ret = KMF_OK;
2422 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2423 	PK11SlotInfo *nss_slot = NULL;
2424 	CERTSignedCrl *nss_crl = NULL;
2425 	KMF_ENCODE_FORMAT format;
2426 	int importOptions;
2427 	SECItem crlDER;
2428 	KMF_DATA crl1;
2429 	KMF_DATA crl2;
2430 	char *crlfilename;
2431 	boolean_t crlcheck = FALSE;
2432 
2433 	if (attrlist == NULL || numattr == 0) {
2434 		return (KMF_ERR_BAD_PARAMETER);
2435 	}
2436 
2437 	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2438 	if (ret != KMF_OK) {
2439 		return (ret);
2440 	}
2441 
2442 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist,
2443 	    numattr);
2444 	if (crlfilename == NULL)
2445 		return (KMF_ERR_BAD_CRLFILE);
2446 
2447 	/*
2448 	 * Check if the input CRL file is a valid CRL file and auto-detect
2449 	 * the encoded format of the file.
2450 	 */
2451 	ret = kmf_is_crl_file(handle, crlfilename, &format);
2452 	if (ret != KMF_OK)
2453 		return (ret);
2454 
2455 	ret = kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
2456 	    &crlcheck, NULL);
2457 	if (ret != KMF_OK)
2458 		ret = KMF_OK; /* CRL_CHECK is optional */
2459 
2460 	/* set importOptions */
2461 	if (crlcheck == B_FALSE) {
2462 		importOptions = CRL_IMPORT_DEFAULT_OPTIONS |
2463 		    CRL_IMPORT_BYPASS_CHECKS;
2464 	} else {
2465 		importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
2466 	}
2467 
2468 
2469 	/* Read in the CRL file */
2470 	crl1.Data = NULL;
2471 	crl2.Data = NULL;
2472 	ret = kmf_read_input_file(handle, crlfilename, &crl1);
2473 	if (ret != KMF_OK) {
2474 		return (ret);
2475 	}
2476 
2477 	/* If the input CRL is in PEM format, convert it to DER first. */
2478 	if (format == KMF_FORMAT_PEM) {
2479 		int len;
2480 		ret = kmf_pem_to_der(crl1.Data, crl1.Length,
2481 		    &crl2.Data, &len);
2482 		if (ret != KMF_OK) {
2483 			goto out;
2484 		}
2485 		crl2.Length = (size_t)len;
2486 	}
2487 
2488 	crlDER.data = format == KMF_FORMAT_ASN1 ? crl1.Data : crl2.Data;
2489 	crlDER.len = format == KMF_FORMAT_ASN1 ? crl1.Length : crl2.Length;
2490 
2491 	nss_crl = PK11_ImportCRL(nss_slot, &crlDER, NULL, SEC_CRL_TYPE,
2492 	    NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
2493 
2494 	if (nss_crl == NULL) {
2495 		SET_ERROR(kmfh, PORT_GetError());
2496 		ret = KMF_ERR_BAD_CRLFILE;
2497 		goto out;
2498 	}
2499 
2500 out:
2501 	if (nss_slot != NULL) {
2502 		PK11_FreeSlot(nss_slot);
2503 	}
2504 
2505 	if (crl1.Data != NULL) {
2506 		free(crl1.Data);
2507 	}
2508 
2509 	if (crl2.Data != NULL) {
2510 		free(crl2.Data);
2511 	}
2512 
2513 	if (nss_crl != NULL) {
2514 		SEC_DestroyCrl(nss_crl);
2515 	}
2516 
2517 	return (ret);
2518 }
2519 
2520 KMF_RETURN
2521 NSS_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2522 {
2523 	KMF_RETURN rv = KMF_OK;
2524 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2525 	CERTSignedCrl *crl = NULL;
2526 	CERTCertificate *cert = NULL;
2527 	PK11SlotInfo *nss_slot = NULL;
2528 	CERTCrlHeadNode *crlList = NULL;
2529 	CERTCrlNode *crlNode = NULL;
2530 	PRArenaPool *arena = NULL;
2531 	CERTName *name = NULL;
2532 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2533 	char *issuername, *subjectname;
2534 
2535 	/* check params */
2536 	if (numattr == 0 || attrlist == NULL) {
2537 		return (KMF_ERR_BAD_PARAMETER);
2538 	}
2539 
2540 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2541 	if (rv != KMF_OK) {
2542 		return (rv);
2543 	}
2544 
2545 	issuername = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist,
2546 	    numattr);
2547 	subjectname = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist,
2548 	    numattr);
2549 
2550 	/* Caller must specify issuer or subject but not both */
2551 	if ((issuername == NULL && subjectname == NULL) ||
2552 	    (issuername != NULL && subjectname != NULL))
2553 		return (KMF_ERR_BAD_PARAMETER);
2554 
2555 	/* Find the CRL based on the deletion criteria. */
2556 	if (issuername != NULL) {
2557 		/*
2558 		 * If the deletion is based on the issuer's certificate
2559 		 * nickname, we will get the issuer's cert first, then
2560 		 * get the CRL from the cert.
2561 		 */
2562 		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2563 		    issuername);
2564 		if (!cert) {
2565 			SET_ERROR(kmfh, PORT_GetError());
2566 			rv = KMF_ERR_CERT_NOT_FOUND;
2567 			goto out;
2568 		}
2569 
2570 		crl = SEC_FindCrlByName(certHandle, &cert->derSubject,
2571 		    SEC_CRL_TYPE);
2572 		if (crl == NULL) {
2573 			SET_ERROR(kmfh, PORT_GetError());
2574 			rv = KMF_ERR_CRL_NOT_FOUND;
2575 			goto out;
2576 		}
2577 	} else {
2578 		/*
2579 		 * If the deletion is based on the CRL's subject name, we will
2580 		 * get all the CRLs from the internal database and search
2581 		 * for the CRL with the same subject name.
2582 		 */
2583 		boolean_t found = B_FALSE;
2584 		int nssrv;
2585 
2586 		nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2587 		if (nssrv) {
2588 			SET_ERROR(kmfh, nssrv);
2589 			rv = KMF_ERR_CRL_NOT_FOUND;
2590 			goto out;
2591 		}
2592 
2593 		if (crlList == NULL) {
2594 			SET_ERROR(kmfh, PORT_GetError());
2595 			rv = KMF_ERR_CRL_NOT_FOUND;
2596 			goto out;
2597 		}
2598 
2599 		/* Allocate space for name */
2600 		arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2601 		if (arena == NULL) {
2602 			rv = KMF_ERR_MEMORY;
2603 			goto out;
2604 		}
2605 
2606 		name = PORT_ArenaZAlloc(arena, sizeof (*name));
2607 		if (name == NULL) {
2608 			rv = KMF_ERR_MEMORY;
2609 			goto out;
2610 		}
2611 		name->arena = arena;
2612 
2613 		crlNode  = crlList->first;
2614 		while (crlNode && !found) {
2615 			char *asciiname = NULL;
2616 			SECItem* issuer;
2617 
2618 			name = &crlNode->crl->crl.name;
2619 			if (!name) {
2620 				SET_ERROR(kmfh, PORT_GetError());
2621 				rv = KMF_ERR_CRL_NOT_FOUND;
2622 				break;
2623 			}
2624 
2625 			asciiname = CERT_NameToAscii(name);
2626 			if (asciiname == NULL) {
2627 				SET_ERROR(kmfh, PORT_GetError());
2628 				rv = KMF_ERR_CRL_NOT_FOUND;
2629 				break;
2630 			}
2631 
2632 			if (strcmp(subjectname, asciiname) == 0) {
2633 				found = B_TRUE;
2634 				issuer = &crlNode->crl->crl.derName;
2635 				crl = SEC_FindCrlByName(certHandle, issuer,
2636 				    SEC_CRL_TYPE);
2637 				if (crl == NULL) {
2638 					/* We found a cert but no CRL */
2639 					SET_ERROR(kmfh,  PORT_GetError());
2640 					rv = KMF_ERR_CRL_NOT_FOUND;
2641 				}
2642 			}
2643 			PORT_Free(asciiname);
2644 			crlNode = crlNode->next;
2645 		}
2646 
2647 		if (rv) {
2648 			goto out;
2649 		}
2650 	}
2651 
2652 	if (crl) {
2653 		(void) SEC_DeletePermCRL(crl);
2654 	}
2655 
2656 out:
2657 	if (nss_slot != NULL) {
2658 		PK11_FreeSlot(nss_slot);
2659 	}
2660 
2661 	if (crlList != NULL) {
2662 		PORT_FreeArena(crlList->arena, PR_FALSE);
2663 	}
2664 
2665 	if (arena != NULL) {
2666 		PORT_FreeArena(arena, PR_FALSE);
2667 	}
2668 
2669 	if (cert != NULL) {
2670 		CERT_DestroyCertificate(cert);
2671 	}
2672 
2673 	if (crl != NULL) {
2674 		SEC_DestroyCrl(crl);
2675 	}
2676 
2677 	return (rv);
2678 }
2679 
2680 KMF_RETURN
2681 NSS_FindCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2682 {
2683 	KMF_RETURN rv = KMF_OK;
2684 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2685 	PK11SlotInfo *nss_slot = NULL;
2686 	CERTCrlHeadNode *crlList = NULL;
2687 	CERTCrlNode *crlNode = NULL;
2688 	PRArenaPool *arena = NULL;
2689 	CERTName *name = NULL;
2690 	SECStatus nssrv;
2691 	char *asciiname = NULL;
2692 	int crl_num;
2693 	int i, *CRLCount;
2694 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2695 	char **CRLNameList;
2696 
2697 	if (numattr == 0 || attrlist == NULL) {
2698 		return (KMF_ERR_BAD_PARAMETER);
2699 	}
2700 
2701 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2702 	if (rv != KMF_OK) {
2703 		return (rv);
2704 	}
2705 
2706 	CRLCount = kmf_get_attr_ptr(KMF_CRL_COUNT_ATTR,	attrlist, numattr);
2707 	if (CRLCount == NULL)
2708 		return (KMF_ERR_BAD_PARAMETER);
2709 
2710 	CRLNameList = (char **)kmf_get_attr_ptr(KMF_CRL_NAMELIST_ATTR,
2711 	    attrlist, numattr);
2712 
2713 	/* Look up Crls */
2714 	nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2715 	if (nssrv) {
2716 		SET_ERROR(kmfh, rv);
2717 		rv = KMF_ERR_CRL_NOT_FOUND;
2718 		goto out;
2719 	}
2720 
2721 	/* Allocate space for name first */
2722 	arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2723 	if (arena == NULL) {
2724 		rv = KMF_ERR_MEMORY;
2725 		goto out;
2726 	}
2727 
2728 	name = PORT_ArenaZAlloc(arena, sizeof (*name));
2729 	if (name == NULL) {
2730 		rv = KMF_ERR_MEMORY;
2731 		goto out;
2732 	}
2733 	name->arena = arena;
2734 
2735 	/*
2736 	 * Loop thru the crlList and create a crl list with CRL's subject name.
2737 	 */
2738 	crlNode  = crlList->first;
2739 	crl_num = 0;
2740 	while (crlNode) {
2741 		char *subj_name;
2742 
2743 		/* Get the CRL subject name */
2744 		name = &crlNode->crl->crl.name;
2745 		if (!name) {
2746 			SET_ERROR(kmfh, PORT_GetError());
2747 			rv = KMF_ERR_CRL_NOT_FOUND;
2748 			break;
2749 		}
2750 
2751 
2752 		if (CRLNameList != NULL) {
2753 			asciiname = CERT_NameToAscii(name);
2754 			if (asciiname == NULL) {
2755 				SET_ERROR(kmfh, PORT_GetError());
2756 				rv = KMF_ERR_CRL_NOT_FOUND;
2757 				break;
2758 			}
2759 			subj_name = strdup(asciiname);
2760 			PORT_Free(asciiname);
2761 			if (subj_name == NULL) {
2762 				rv = KMF_ERR_MEMORY;
2763 				break;
2764 			}
2765 			CRLNameList[crl_num] = subj_name;
2766 		}
2767 
2768 		crl_num++;
2769 		crlNode = crlNode->next;
2770 	}
2771 
2772 	if (rv == KMF_OK) {
2773 		/* success */
2774 		*CRLCount = crl_num;
2775 	}
2776 
2777 out:
2778 	if (nss_slot != NULL) {
2779 		PK11_FreeSlot(nss_slot);
2780 	}
2781 
2782 	if (crlList != NULL) {
2783 		PORT_FreeArena(crlList->arena, PR_FALSE);
2784 	}
2785 
2786 	if (arena != NULL) {
2787 		PORT_FreeArena(arena, PR_FALSE);
2788 	}
2789 
2790 	/* If failed, free memory allocated for the returning rlist */
2791 	if (rv && (CRLNameList != NULL)) {
2792 		for (i = 0; i < crl_num; i++) {
2793 			free(CRLNameList[i]);
2794 		}
2795 	}
2796 
2797 	return (rv);
2798 }
2799 
2800 KMF_RETURN
2801 NSS_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2802 {
2803 	KMF_RETURN rv = KMF_OK;
2804 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2805 	PK11SlotInfo *nss_slot = NULL;
2806 	CERTCertificate *cert = NULL;
2807 	CERTSignedCrl *crl = NULL;
2808 	CERTCrlEntry *entry;
2809 	boolean_t match = B_FALSE;
2810 	int i;
2811 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2812 	char *certlabel;
2813 	KMF_DATA *certdata;
2814 
2815 	/* check params */
2816 	if (numattr == 0 || attrlist == NULL) {
2817 		return (KMF_ERR_BAD_PARAMETER);
2818 	}
2819 
2820 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2821 	if (rv != KMF_OK) {
2822 		return (rv);
2823 	}
2824 
2825 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2826 
2827 	/* Find the certificate first */
2828 	if (certlabel != NULL) {
2829 		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2830 		    certlabel);
2831 	} else {
2832 		SECItem derCert = { NULL, 0};
2833 
2834 		certdata = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR,
2835 		    attrlist, numattr);
2836 
2837 		if (certdata == NULL)
2838 			return (KMF_ERR_BAD_PARAMETER);
2839 
2840 		derCert.data = certdata->Data;
2841 		derCert.len = certdata->Length;
2842 
2843 		cert = CERT_FindCertByDERCert(certHandle, &derCert);
2844 	}
2845 
2846 	if (cert == NULL) {
2847 		SET_ERROR(kmfh, PORT_GetError());
2848 		rv = KMF_ERR_CERT_NOT_FOUND;
2849 		goto out;
2850 	}
2851 
2852 	/* Find the CRL with the same issuer as the given certificate. */
2853 	crl = SEC_FindCrlByName(certHandle, &cert->derIssuer, SEC_CRL_TYPE);
2854 	if (crl == NULL) {
2855 		/*
2856 		 * Could not find the CRL issued by the same issuer. This
2857 		 * usually means that the CRL is not installed in the DB.
2858 		 */
2859 		SET_ERROR(kmfh, PORT_GetError());
2860 		rv = KMF_ERR_CRL_NOT_FOUND;
2861 		goto out;
2862 
2863 	}
2864 
2865 	/* Check if the certificate's serialNumber is revoked in the CRL */
2866 	i = 0;
2867 	while ((entry = (crl->crl).entries[i++]) != NULL) {
2868 		if (SECITEM_CompareItem(&(cert->serialNumber),
2869 		    &(entry->serialNumber)) == SECEqual) {
2870 			match = B_TRUE;
2871 			break;
2872 		}
2873 	}
2874 
2875 	if (!match) {
2876 		rv = KMF_ERR_NOT_REVOKED;
2877 	}
2878 
2879 out:
2880 	if (nss_slot != NULL) {
2881 		PK11_FreeSlot(nss_slot);
2882 	}
2883 
2884 	if (cert != NULL) {
2885 		CERT_DestroyCertificate(cert);
2886 	}
2887 
2888 	if (crl != NULL) {
2889 		SEC_DestroyCrl(crl);
2890 	}
2891 
2892 	return (rv);
2893 }
2894