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