xref: /illumos-gate/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c (revision 24472db64c485d6744c0321b7581cf066556cf2d)
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 	uint32_t maxcerts = *numcerts;
561 
562 	*numcerts = 0;
563 
564 	for (node = CERT_LIST_HEAD(nsscerts);
565 		!CERT_LIST_END(node, nsscerts) && rv == KMF_OK &&
566 		(*numcerts) < maxcerts;
567 		node = CERT_LIST_NEXT(node), (*numcerts)++) {
568 		if (kmfcerts != NULL)
569 			rv = nss2kmf_cert(node->cert, &kmfcerts[*numcerts]);
570 	}
571 
572 	/*
573 	 * If we failed, delete any certs allocated so far.
574 	 */
575 	if (rv != KMF_OK) {
576 		int i;
577 		for (i = 0; i < *numcerts; i++)
578 			KMF_FreeKMFCert(kmfhandle, &kmfcerts[i]);
579 		*numcerts = 0;
580 	}
581 	return (rv);
582 }
583 
584 KMF_RETURN
585 NSS_FindCert(KMF_HANDLE_T handle, KMF_FINDCERT_PARAMS *params,
586 	KMF_X509_DER_CERT *kmfcerts,
587 	uint32_t *num_certs)
588 {
589 	KMF_RETURN rv = KMF_OK;
590 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
591 	PK11SlotInfo *nss_slot = NULL;
592 	CERTCertList *certlist = NULL;
593 	uint32_t maxcerts;
594 
595 	rv = Do_NSS_Init(handle,
596 		params->ks_opt_u.nss_opts, FALSE, &nss_slot);
597 	if (rv != KMF_OK) {
598 		return (rv);
599 	}
600 
601 	if (*num_certs == 0)
602 		maxcerts = 0xFFFFFFFF;
603 	else
604 		maxcerts = *num_certs;
605 
606 	*num_certs = 0;
607 	if (params->certLabel) {
608 		/* This will only find 1 certificate */
609 		rv = nss_getcert_by_label(kmfh,
610 			params->certLabel,
611 			kmfcerts, num_certs, params->find_cert_validity);
612 	} else {
613 		/*
614 		 * Build a list of matching certs.
615 		 */
616 		rv = nss_find_matching_certs(nss_slot,
617 			params->issuer, params->subject, params->serial,
618 			&certlist, params->find_cert_validity);
619 
620 		/*
621 		 * If the caller supplied a pointer to storage for
622 		 * a list of certs, convert up to 'maxcerts' of the
623 		 * matching certs.
624 		 */
625 		if (rv == KMF_OK && certlist != NULL) {
626 			rv = convertCertList(handle,
627 				certlist, kmfcerts, &maxcerts);
628 			CERT_DestroyCertList(certlist);
629 			if (rv == KMF_OK)
630 				*num_certs = maxcerts;
631 		}
632 	}
633 
634 	if (nss_slot != NULL) {
635 		PK11_FreeSlot(nss_slot);
636 	}
637 
638 	if (rv == KMF_OK && *num_certs == 0)
639 		rv = KMF_ERR_CERT_NOT_FOUND;
640 
641 	return (rv);
642 }
643 
644 void
645 /*ARGSUSED*/
646 NSS_FreeKMFCert(KMF_HANDLE_T handle,
647 	KMF_X509_DER_CERT *kmf_cert)
648 {
649 	if (kmf_cert != NULL) {
650 		if (kmf_cert->certificate.Data != NULL) {
651 			free(kmf_cert->certificate.Data);
652 			kmf_cert->certificate.Data = NULL;
653 			kmf_cert->certificate.Length = 0;
654 		}
655 		if (kmf_cert->kmf_private.label != NULL) {
656 			free(kmf_cert->kmf_private.label);
657 			kmf_cert->kmf_private.label = NULL;
658 		}
659 	}
660 }
661 
662 KMF_RETURN
663 NSS_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *params,
664 	KMF_DATA *pcert)
665 {
666 	KMF_RETURN ret = KMF_OK;
667 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
668 	SECStatus nss_rv;
669 	CERTCertificate *nss_cert = NULL;
670 	CERTCertTrust *nss_trust = NULL;
671 	PK11SlotInfo *nss_slot = NULL;
672 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
673 
674 	if (pcert == NULL) {
675 		return (KMF_ERR_BAD_PARAMETER);
676 	}
677 
678 	/* NSS only support DER format */
679 	if (params == NULL) {
680 		return (KMF_ERR_BAD_PARAMETER);
681 	}
682 
683 	ret = Do_NSS_Init(handle,
684 		params->ks_opt_u.nss_opts, FALSE, &nss_slot);
685 	if (ret != KMF_OK) {
686 		return (ret);
687 	}
688 
689 	nss_cert = CERT_DecodeCertFromPackage((char *)pcert->Data,
690 	    pcert->Length);
691 	if (nss_cert == NULL) {
692 		SET_ERROR(kmfh, PORT_GetError());
693 		ret = KMF_ERR_BAD_CERT_FORMAT;
694 		goto out;
695 	}
696 
697 	nss_rv = PK11_ImportCert(nss_slot, nss_cert, CK_INVALID_HANDLE,
698 	    params->certLabel, 0);
699 	if (nss_rv) {
700 		SET_ERROR(kmfh, nss_rv);
701 		ret = KMF_ERR_BAD_CERT_FORMAT;
702 		goto out;
703 	}
704 
705 	if (params->ks_opt_u.nss_opts.trustflag != NULL &&
706 		strlen(params->ks_opt_u.nss_opts.trustflag)) {
707 		nss_trust = (CERTCertTrust *) malloc(sizeof (CERTCertTrust));
708 		if (nss_trust == NULL) {
709 			ret = KMF_ERR_MEMORY;
710 				goto out;
711 		}
712 		nss_rv = CERT_DecodeTrustString(nss_trust,
713 			params->ks_opt_u.nss_opts.trustflag);
714 		if (nss_rv) {
715 			SET_ERROR(kmfh, nss_rv);
716 			ret = KMF_ERR_BAD_PARAMETER;
717 			goto out;
718 		}
719 
720 		nss_rv = CERT_ChangeCertTrust(certHandle, nss_cert, nss_trust);
721 		if (nss_rv) {
722 			SET_ERROR(kmfh, nss_rv);
723 			ret = KMF_ERR_BAD_PARAMETER;
724 		}
725 	}
726 
727 out:
728 	if (nss_trust != NULL) {
729 		free(nss_trust);
730 	}
731 
732 	if (nss_cert != NULL) {
733 		CERT_DestroyCertificate(nss_cert);
734 	}
735 
736 	if (nss_slot != NULL) {
737 		PK11_FreeSlot(nss_slot);
738 	}
739 
740 	return (ret);
741 }
742 
743 
744 KMF_RETURN
745 NSS_ImportCert(KMF_HANDLE_T handle, KMF_IMPORTCERT_PARAMS *params)
746 {
747 	KMF_RETURN ret = KMF_OK;
748 	KMF_STORECERT_PARAMS scparams;
749 	KMF_DATA cert = {NULL, 0};
750 	KMF_DATA cert_der = {NULL, 0};
751 	KMF_DATA *cptr = NULL;
752 	KMF_ENCODE_FORMAT format;
753 
754 	if (params == NULL || params->certfile == NULL) {
755 		return (KMF_ERR_BAD_PARAMETER);
756 	}
757 
758 	/*
759 	 * Check if the input cert file is a valid certificate and
760 	 * auto-detect the file format of it.
761 	 */
762 	ret = KMF_IsCertFile(handle, params->certfile, &format);
763 	if (ret != KMF_OK)
764 		return (ret);
765 
766 	ret = KMF_ReadInputFile(handle, params->certfile, &cert);
767 	if (ret != KMF_OK) {
768 		return (ret);
769 	}
770 
771 	/*
772 	 * If the imported cert is in PEM format, convert it to
773 	 * DER format in order to store it in NSS token.
774 	 */
775 	if (format == KMF_FORMAT_PEM) {
776 		int derlen;
777 		ret = KMF_Pem2Der(cert.Data, cert.Length,
778 		    &cert_der.Data, &derlen);
779 		if (ret != KMF_OK) {
780 			goto cleanup;
781 		}
782 		cert_der.Length = (size_t)derlen;
783 		cptr = &cert_der;
784 	} else {
785 		cptr = &cert;
786 	}
787 
788 	(void) memset(&scparams, 0, sizeof (scparams));
789 	scparams.kstype = params->kstype;
790 	scparams.certLabel = params->certLabel;
791 	scparams.nssparms = params->nssparms;
792 
793 	ret = NSS_StoreCert(handle, &scparams, cptr);
794 
795 	if (format == KMF_FORMAT_PEM) {
796 		KMF_FreeData(&cert_der);
797 	}
798 
799 cleanup:
800 	KMF_FreeData(&cert);
801 
802 	return (ret);
803 }
804 
805 KMF_RETURN
806 NSS_DeleteCert(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *params)
807 {
808 	KMF_RETURN rv = KMF_OK;
809 	int nssrv;
810 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
811 	CERTCertificate *cert = NULL;
812 	PK11SlotInfo *nss_slot = NULL;
813 
814 	/* check params */
815 	if (params == NULL) {
816 		return (KMF_ERR_BAD_PARAMETER);
817 	}
818 
819 	rv = Do_NSS_Init(handle,
820 		params->ks_opt_u.nss_opts,
821 		FALSE, &nss_slot);
822 	if (rv != KMF_OK) {
823 		return (rv);
824 	}
825 
826 	if (params->certLabel) {
827 		cert = PK11_FindCertFromNickname(params->certLabel, NULL);
828 		if (cert == NULL) {
829 			return (KMF_ERR_CERT_NOT_FOUND);
830 		}
831 
832 		switch (params->find_cert_validity) {
833 		case KMF_ALL_CERTS:
834 			break;
835 		case KMF_NONEXPIRED_CERTS:
836 			nssrv = CERT_CertTimesValid(cert);
837 			if (nssrv == SECFailure) {
838 				/* this is an invalid cert - skip it */
839 				goto out;
840 			}
841 			break;
842 		case KMF_EXPIRED_CERTS:
843 			nssrv = CERT_CertTimesValid(cert);
844 			if (nssrv != SECFailure) {
845 				/* this is a valid cert - skip it */
846 				goto out;
847 			}
848 			break;
849 		}
850 		/* delete it from database */
851 		nssrv = SEC_DeletePermCertificate(cert);
852 		if (nssrv) {
853 			SET_ERROR(kmfh, nssrv);
854 			rv = KMF_ERR_INTERNAL;
855 		}
856 	} else {
857 		CERTCertListNode *node;
858 		CERTCertList *certlist = NULL;
859 
860 		rv = nss_find_matching_certs(nss_slot,
861 			params->issuer, params->subject, params->serial,
862 			&certlist, params->find_cert_validity);
863 
864 		for (node = CERT_LIST_HEAD(certlist);
865 			!CERT_LIST_END(node, certlist) && rv == KMF_OK;
866 			node = CERT_LIST_NEXT(node)) {
867 
868 			nssrv = SEC_DeletePermCertificate(node->cert);
869 			if (nssrv) {
870 				SET_ERROR(kmfh, nssrv);
871 				rv = KMF_ERR_INTERNAL;
872 			}
873 		}
874 
875 		if (rv == KMF_OK && certlist != NULL) {
876 			CERT_DestroyCertList(certlist);
877 		} else if (rv == KMF_OK && certlist == NULL) {
878 			rv = KMF_ERR_CERT_NOT_FOUND;
879 		}
880 	}
881 out:
882 	if (nss_slot != NULL) {
883 		PK11_FreeSlot(nss_slot);
884 	}
885 
886 	if (cert != NULL) {
887 		CERT_DestroyCertificate(cert);
888 	}
889 
890 	return (rv);
891 }
892 
893 static void
894 InitRandom(char *filename)
895 {
896 	char buf[2048];
897 	int fd;
898 	PRInt32 count;
899 
900 	fd = open(filename, O_RDONLY);
901 	if (!fd)
902 		return;
903 
904 	count = read(fd, buf, sizeof (buf));
905 	if (count > 0) {
906 		PK11_RandomUpdate(buf, count);
907 	}
908 
909 	(void) close(fd);
910 }
911 
912 KMF_RETURN
913 NSS_CreateKeypair(KMF_HANDLE_T handle,
914 	KMF_CREATEKEYPAIR_PARAMS *params,
915 	KMF_KEY_HANDLE *privkey,
916 	KMF_KEY_HANDLE *pubkey)
917 {
918 	KMF_RETURN rv = KMF_OK;
919 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
920 	PK11RSAGenParams	rsaparams;
921 	void	*nssparams;
922 	CK_MECHANISM_TYPE mechanism;
923 	ulong_t publicExponent = 0x010001;
924 	PK11SlotInfo *nss_slot = NULL;
925 	SECKEYPrivateKey *NSSprivkey = NULL;
926 	SECKEYPublicKey *NSSpubkey = NULL;
927 	PQGParams *pqgParams = NULL;
928 
929 
930 	if (params == NULL) {
931 		return (KMF_ERR_BAD_PARAMETER);
932 	}
933 
934 	rv = Do_NSS_Init(handle,
935 		params->ks_opt_u.nss_opts, FALSE, &nss_slot);
936 	if (rv != KMF_OK) {
937 		return (rv);
938 	}
939 
940 	rv = nss_authenticate(handle, nss_slot, &params->cred);
941 	if (rv != KMF_OK) {
942 		return (rv);
943 	}
944 
945 	/* Get some random bits */
946 	InitRandom("/dev/urandom");
947 	if (params->keytype == KMF_RSA) {
948 		rsaparams.keySizeInBits = params->keylength;
949 		/*
950 		 * NSS only allows for a 4 byte exponent.
951 		 * Ignore the exponent parameter if it is too big.
952 		 */
953 		if (params->rsa_exponent.len > 0 &&
954 		    params->rsa_exponent.len <= sizeof (publicExponent) &&
955 		    params->rsa_exponent.val != NULL) {
956 			(void) memcpy(&publicExponent,
957 				params->rsa_exponent.val,
958 				params->rsa_exponent.len);
959 		}
960 		rsaparams.pe = publicExponent;
961 		mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
962 		nssparams = &rsaparams;
963 	} else if (params->keytype == KMF_DSA) {
964 		PQGVerify *pqgVerify = NULL;
965 		int ks;
966 		SECStatus	nssrv, passed;
967 
968 		mechanism = CKM_DSA_KEY_PAIR_GEN;
969 
970 		ks = PQG_PBITS_TO_INDEX(params->keylength);
971 		nssrv = PK11_PQG_ParamGen(ks, &pqgParams, &pqgVerify);
972 		if (nssrv != SECSuccess) {
973 			SET_ERROR(kmfh, rv);
974 			PK11_PQG_DestroyVerify(pqgVerify);
975 			rv = KMF_ERR_KEYGEN_FAILED;
976 			goto cleanup;
977 		}
978 
979 		nssrv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
980 		if (nssrv != SECSuccess || passed != SECSuccess) {
981 			SET_ERROR(kmfh, rv);
982 			rv = KMF_ERR_KEYGEN_FAILED;
983 		}
984 
985 		PK11_PQG_DestroyVerify(pqgVerify);
986 
987 		if (rv != KMF_OK) {
988 			SET_ERROR(kmfh, PORT_GetError());
989 			goto cleanup;
990 		}
991 
992 		nssparams = pqgParams;
993 	} else {
994 		rv = KMF_ERR_BAD_PARAMETER;
995 		goto cleanup;
996 	}
997 
998 	NSSprivkey = PK11_GenerateKeyPair(nss_slot,
999 		mechanism, nssparams, &NSSpubkey,
1000 		PR_TRUE, /* isPermanent */
1001 		PR_TRUE, /* isSensitive */
1002 		(void *)params->cred.cred);
1003 
1004 	if (NSSprivkey == NULL || NSSpubkey == NULL) {
1005 		SET_ERROR(kmfh, PORT_GetError());
1006 		rv = KMF_ERR_KEYGEN_FAILED;
1007 	} else {
1008 		if (params->keylabel != NULL &&
1009 			strlen(params->keylabel)) {
1010 			(void) PK11_SetPrivateKeyNickname(NSSprivkey,
1011 				params->keylabel);
1012 			(void) PK11_SetPublicKeyNickname(NSSpubkey,
1013 				params->keylabel);
1014 		}
1015 		/* Now, convert it to a KMF_KEY object for the framework */
1016 		if (privkey != NULL) {
1017 			privkey->kstype = KMF_KEYSTORE_NSS;
1018 			privkey->keyalg = params->keytype;
1019 			privkey->keyclass = KMF_ASYM_PRI;
1020 			privkey->keylabel =
1021 				PK11_GetPrivateKeyNickname(NSSprivkey);
1022 			privkey->keyp = (void *)NSSprivkey;
1023 		}
1024 		if (pubkey != NULL) {
1025 			pubkey->kstype = KMF_KEYSTORE_NSS;
1026 			pubkey->keyalg = params->keytype;
1027 			pubkey->keyp = (void *)NSSpubkey;
1028 			pubkey->keyclass = KMF_ASYM_PUB;
1029 			pubkey->keylabel =
1030 				PK11_GetPublicKeyNickname(NSSpubkey);
1031 		}
1032 		rv = KMF_OK;
1033 	}
1034 cleanup:
1035 	if (rv != KMF_OK) {
1036 		if (NSSpubkey)
1037 			PK11_DeleteTokenPublicKey(NSSpubkey);
1038 		if (NSSprivkey)
1039 			PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE);
1040 
1041 		privkey->keyp = NULL;
1042 		pubkey->keyp = NULL;
1043 	}
1044 
1045 	if (pqgParams != NULL)
1046 		PK11_PQG_DestroyParams(pqgParams);
1047 
1048 
1049 	if (nss_slot != NULL)
1050 		PK11_FreeSlot(nss_slot);
1051 
1052 	return (rv);
1053 }
1054 
1055 KMF_RETURN
1056 NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1057 	KMF_OID *AlgOID, KMF_DATA *tobesigned,
1058 	KMF_DATA *output)
1059 {
1060 	KMF_RETURN		ret = KMF_OK;
1061 	KMF_ALGORITHM_INDEX		AlgId;
1062 	SECOidTag		signAlgTag;
1063 	SECKEYPrivateKey	*NSSprivkey = NULL;
1064 	SECStatus		rv;
1065 	SECItem			signed_data;
1066 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1067 
1068 	signed_data.data = 0;
1069 	if (key == NULL || AlgOID == NULL ||
1070 	    tobesigned == NULL || output == NULL ||
1071 	    tobesigned->Data == NULL ||
1072 	    output->Data == NULL)
1073 		return (KMF_ERR_BAD_PARAMETER);
1074 
1075 	/* Map the OID to a NSS algorithm */
1076 	AlgId = X509_AlgorithmOidToAlgId(AlgOID);
1077 	if (AlgId == KMF_ALGID_NONE)
1078 		return (KMF_ERR_BAD_PARAMETER);
1079 
1080 	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1081 
1082 	if (AlgId == KMF_ALGID_MD5WithRSA)
1083 		signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1084 	else if (AlgId == KMF_ALGID_MD2WithRSA)
1085 		signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1086 	else if (AlgId == KMF_ALGID_SHA1WithRSA)
1087 		signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1088 	else if (AlgId == KMF_ALGID_SHA1WithDSA)
1089 		signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
1090 	else
1091 		return (KMF_ERR_BAD_PARAMETER);
1092 
1093 	rv = SEC_SignData(&signed_data, tobesigned->Data,
1094 	    tobesigned->Length, NSSprivkey, signAlgTag);
1095 
1096 	if (rv != 0) {
1097 		SET_ERROR(kmfh, rv);
1098 		return (KMF_ERR_INTERNAL);
1099 	}
1100 
1101 	if (signed_data.len <= output->Length) {
1102 		(void) memcpy(output->Data, signed_data.data, signed_data.len);
1103 		output->Length = signed_data.len;
1104 	} else {
1105 		output->Length = 0;
1106 		ret = KMF_ERR_BAD_PARAMETER;
1107 	}
1108 	free(signed_data.data);
1109 
1110 	return (ret);
1111 }
1112 
1113 KMF_RETURN
1114 NSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1115 	KMF_DATA *encoded)
1116 {
1117 	KMF_RETURN ret = KMF_OK;
1118 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1119 	SECItem *rvitem;
1120 	CERTSubjectPublicKeyInfo *spki = NULL;
1121 
1122 	if (keyp == NULL || encoded == NULL || keyp->keyp == NULL)
1123 		return (KMF_ERR_BAD_PARAMETER);
1124 
1125 	spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp);
1126 	if (spki == NULL) {
1127 		SET_ERROR(kmfh, PORT_GetError());
1128 		return (KMF_ERR_MEMORY);
1129 	}
1130 
1131 	rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki,
1132 		CERT_SubjectPublicKeyInfoTemplate);
1133 
1134 	if (rvitem != NULL) {
1135 		encoded->Data = malloc(rvitem->len);
1136 		if (encoded->Data == NULL) {
1137 			ret = KMF_ERR_MEMORY;
1138 		} else {
1139 			(void) memcpy(encoded->Data, rvitem->data, rvitem->len);
1140 			encoded->Length = rvitem->len;
1141 		}
1142 		SECITEM_FreeItem(rvitem, TRUE);
1143 	} else {
1144 		SET_ERROR(kmfh, PORT_GetError());
1145 		encoded->Data = NULL;
1146 		encoded->Length = 0;
1147 		ret = KMF_ERR_ENCODING;
1148 	}
1149 	SECKEY_DestroySubjectPublicKeyInfo(spki);
1150 
1151 	return (ret);
1152 }
1153 
1154 KMF_RETURN
1155 NSS_DeleteKey(KMF_HANDLE_T handle, KMF_DELETEKEY_PARAMS *params,
1156 	KMF_KEY_HANDLE *key, boolean_t delete_token)
1157 {
1158 	KMF_RETURN rv = KMF_OK;
1159 	PK11SlotInfo *nss_slot = NULL;
1160 
1161 	/*
1162 	 * "delete_token" means to clear it from the token storage as well
1163 	 * as from memory.
1164 	 */
1165 	if (key == NULL || key->keyp == NULL)
1166 		return (KMF_ERR_BAD_PARAMETER);
1167 
1168 	if (delete_token) {
1169 		SECStatus nssrv = SECSuccess;
1170 		if (key->keyclass != KMF_ASYM_PUB &&
1171 			key->keyclass != KMF_ASYM_PRI &&
1172 			key->keyclass != KMF_SYMMETRIC)
1173 			return (KMF_ERR_BAD_KEY_CLASS);
1174 
1175 		if (params == NULL)
1176 			return (KMF_ERR_BAD_PARAMETER);
1177 		rv = Do_NSS_Init(handle,
1178 			params->ks_opt_u.nss_opts, FALSE, &nss_slot);
1179 		if (rv != KMF_OK) {
1180 			return (rv);
1181 		}
1182 		rv = nss_authenticate(handle, nss_slot, &params->cred);
1183 		if (rv != KMF_OK) {
1184 			return (rv);
1185 		}
1186 
1187 		if (key->keyclass == KMF_ASYM_PUB) {
1188 			nssrv = PK11_DeleteTokenPublicKey(
1189 				(SECKEYPublicKey *)key->keyp);
1190 		} else if (key->keyclass == KMF_ASYM_PRI) {
1191 			nssrv = PK11_DeleteTokenPrivateKey(
1192 				(SECKEYPrivateKey *)key->keyp, PR_TRUE);
1193 		} else if (key->keyclass == KMF_SYMMETRIC) {
1194 			nssrv = PK11_DeleteTokenSymKey(
1195 					(PK11SymKey *) key->keyp);
1196 			if (nssrv == SECSuccess)
1197 				PK11_FreeSymKey(
1198 					(PK11SymKey *) key->keyp);
1199 		}
1200 		if (nssrv != SECSuccess) {
1201 			SET_ERROR(handle, PORT_GetError());
1202 			rv = KMF_ERR_INTERNAL;
1203 		}
1204 	} else {
1205 		if (key->keyclass == KMF_ASYM_PUB) {
1206 			SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp);
1207 		} else if (key->keyclass == KMF_ASYM_PRI) {
1208 			SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp);
1209 		} else if (key->keyclass == KMF_SYMMETRIC) {
1210 			PK11_FreeSymKey((PK11SymKey *) key->keyp);
1211 		} else {
1212 			return (KMF_ERR_BAD_KEY_CLASS);
1213 		}
1214 	}
1215 	key->keyp = NULL;
1216 
1217 	return (rv);
1218 }
1219 
1220 KMF_RETURN
1221 NSS_ImportCRL(KMF_HANDLE_T handle, KMF_IMPORTCRL_PARAMS *params)
1222 {
1223 	KMF_RETURN ret = KMF_OK;
1224 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1225 	PK11SlotInfo *nss_slot = NULL;
1226 	CERTSignedCrl *nss_crl = NULL;
1227 	KMF_ENCODE_FORMAT format;
1228 	int importOptions;
1229 	SECItem crlDER;
1230 	KMF_DATA crl1;
1231 	KMF_DATA crl2;
1232 
1233 	if (params == NULL || params->ks_opt_u.nss_opts.crlfile == NULL) {
1234 		return (KMF_ERR_BAD_PARAMETER);
1235 	}
1236 
1237 	/*
1238 	 * Check if the input CRL file is a valid CRL file and auto-detect
1239 	 * the encoded format of the file.
1240 	 */
1241 	ret = KMF_IsCRLFile(handle, params->ks_opt_u.nss_opts.crlfile,
1242 	    &format);
1243 	if (ret != KMF_OK)
1244 		return (ret);
1245 
1246 	ret = Do_NSS_Init(handle,
1247 		params->ks_opt_u.nss_opts, TRUE, &nss_slot);
1248 	if (ret != KMF_OK) {
1249 		return (ret);
1250 	}
1251 
1252 	/* set importOptions */
1253 	if (params->ks_opt_u.nss_opts.crl_check == B_FALSE) {
1254 		importOptions = CRL_IMPORT_DEFAULT_OPTIONS |
1255 		    CRL_IMPORT_BYPASS_CHECKS;
1256 	} else {
1257 		importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
1258 	}
1259 
1260 
1261 	/* Read in the CRL file */
1262 	crl1.Data = NULL;
1263 	crl2.Data = NULL;
1264 	ret = KMF_ReadInputFile(handle, params->ks_opt_u.nss_opts.crlfile,
1265 	    &crl1);
1266 	if (ret != KMF_OK) {
1267 		return (ret);
1268 	}
1269 
1270 	/* If the input CRL is in PEM format, convert it to DER first. */
1271 	if (format == KMF_FORMAT_PEM) {
1272 		int len;
1273 		ret = KMF_Pem2Der(crl1.Data, crl1.Length,
1274 		    &crl2.Data, &len);
1275 		if (ret != KMF_OK) {
1276 			goto out;
1277 		}
1278 		crl2.Length = (size_t)len;
1279 	}
1280 
1281 	crlDER.data = format == KMF_FORMAT_ASN1 ? crl1.Data : crl2.Data;
1282 	crlDER.len = format == KMF_FORMAT_ASN1 ? crl1.Length : crl2.Length;
1283 
1284 	nss_crl = PK11_ImportCRL(nss_slot, &crlDER, NULL, SEC_CRL_TYPE,
1285 	    NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
1286 
1287 	if (nss_crl == NULL) {
1288 		SET_ERROR(kmfh, PORT_GetError());
1289 		ret = KMF_ERR_BAD_CRLFILE;
1290 		goto out;
1291 	}
1292 
1293 out:
1294 	if (nss_slot != NULL) {
1295 		PK11_FreeSlot(nss_slot);
1296 	}
1297 
1298 	if (crl1.Data != NULL) {
1299 		free(crl1.Data);
1300 	}
1301 
1302 	if (crl2.Data != NULL) {
1303 		free(crl2.Data);
1304 	}
1305 
1306 	if (nss_crl != NULL) {
1307 		SEC_DestroyCrl(nss_crl);
1308 	}
1309 
1310 	return (ret);
1311 }
1312 
1313 KMF_RETURN
1314 NSS_DeleteCRL(KMF_HANDLE_T handle, KMF_DELETECRL_PARAMS *params)
1315 {
1316 	KMF_RETURN rv = KMF_OK;
1317 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1318 	CERTSignedCrl *crl = NULL;
1319 	CERTCertificate *cert = NULL;
1320 	PK11SlotInfo *nss_slot = NULL;
1321 	CERTCrlHeadNode *crlList = NULL;
1322 	CERTCrlNode *crlNode = NULL;
1323 	PRArenaPool *arena = NULL;
1324 	CERTName *name = NULL;
1325 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
1326 
1327 	/* check params */
1328 	if (params == NULL ||
1329 	    (params->ks_opt_u.nss_opts.crl_issuerName == NULL &&
1330 	    params->ks_opt_u.nss_opts.crl_subjName == NULL) ||
1331 	    (params->ks_opt_u.nss_opts.crl_issuerName != NULL &&
1332 	    params->ks_opt_u.nss_opts.crl_subjName != NULL)) {
1333 		return (KMF_ERR_BAD_PARAMETER);
1334 	}
1335 
1336 	rv = Do_NSS_Init(handle,
1337 		params->ks_opt_u.nss_opts, TRUE,
1338 		&nss_slot);
1339 	if (rv != KMF_OK) {
1340 		return (rv);
1341 	}
1342 
1343 	/* Find the CRL based on the deletion criteria. */
1344 	if (params->ks_opt_u.nss_opts.crl_issuerName != NULL) {
1345 		/*
1346 		 * If the deletion is based on the issuer's certificate
1347 		 * nickname, we will get the issuer's cert first, then
1348 		 * get the CRL from the cert.
1349 		 */
1350 		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
1351 		    params->ks_opt_u.nss_opts.crl_issuerName);
1352 		if (!cert) {
1353 			SET_ERROR(kmfh, PORT_GetError());
1354 			rv = KMF_ERR_CERT_NOT_FOUND;
1355 			goto out;
1356 		}
1357 
1358 		crl = SEC_FindCrlByName(certHandle, &cert->derSubject,
1359 		    SEC_CRL_TYPE);
1360 		if (crl == NULL) {
1361 			SET_ERROR(kmfh, PORT_GetError());
1362 			rv = KMF_ERR_CRL_NOT_FOUND;
1363 			goto out;
1364 		}
1365 	} else {
1366 		/*
1367 		 * If the deletion is based on the CRL's subject name, we will
1368 		 * get all the CRLs from the internal database and search
1369 		 * for the CRL with the same subject name.
1370 		 */
1371 		boolean_t found = B_FALSE;
1372 		int nssrv;
1373 
1374 		nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
1375 		if (nssrv) {
1376 			SET_ERROR(kmfh, nssrv);
1377 			rv = KMF_ERR_CRL_NOT_FOUND;
1378 			goto out;
1379 		}
1380 
1381 		if (crlList == NULL) {
1382 			SET_ERROR(kmfh, PORT_GetError());
1383 			rv = KMF_ERR_CRL_NOT_FOUND;
1384 			goto out;
1385 		}
1386 
1387 		/* Allocate space for name */
1388 		arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
1389 		if (arena == NULL) {
1390 			rv = KMF_ERR_MEMORY;
1391 			goto out;
1392 		}
1393 
1394 		name = PORT_ArenaZAlloc(arena, sizeof (*name));
1395 		if (name == NULL) {
1396 			rv = KMF_ERR_MEMORY;
1397 			goto out;
1398 		}
1399 		name->arena = arena;
1400 
1401 		crlNode  = crlList->first;
1402 		while (crlNode && !found) {
1403 			char *asciiname = NULL;
1404 			SECItem* issuer;
1405 
1406 			name = &crlNode->crl->crl.name;
1407 			if (!name) {
1408 				SET_ERROR(kmfh, PORT_GetError());
1409 				rv = KMF_ERR_CRL_NOT_FOUND;
1410 				break;
1411 			}
1412 
1413 			asciiname = CERT_NameToAscii(name);
1414 			if (asciiname == NULL) {
1415 				SET_ERROR(kmfh, PORT_GetError());
1416 				rv = KMF_ERR_CRL_NOT_FOUND;
1417 				break;
1418 			}
1419 
1420 			if (strcmp(params->ks_opt_u.nss_opts.crl_subjName,
1421 			    asciiname) == 0) {
1422 				found = B_TRUE;
1423 				issuer = &crlNode->crl->crl.derName;
1424 				crl = SEC_FindCrlByName(certHandle, issuer,
1425 				    SEC_CRL_TYPE);
1426 				if (crl == NULL) {
1427 					/* We found a cert but no CRL */
1428 					SET_ERROR(kmfh,  PORT_GetError());
1429 					rv = KMF_ERR_CRL_NOT_FOUND;
1430 				}
1431 			}
1432 			PORT_Free(asciiname);
1433 			crlNode = crlNode->next;
1434 		}
1435 
1436 		if (rv) {
1437 			goto out;
1438 		}
1439 	}
1440 
1441 	if (crl) {
1442 		(void) SEC_DeletePermCRL(crl);
1443 	}
1444 
1445 out:
1446 	if (nss_slot != NULL) {
1447 		PK11_FreeSlot(nss_slot);
1448 	}
1449 
1450 	if (crlList != NULL) {
1451 		PORT_FreeArena(crlList->arena, PR_FALSE);
1452 	}
1453 
1454 	if (arena != NULL) {
1455 		PORT_FreeArena(arena, PR_FALSE);
1456 	}
1457 
1458 	if (cert != NULL) {
1459 		CERT_DestroyCertificate(cert);
1460 	}
1461 
1462 	if (crl != NULL) {
1463 		SEC_DestroyCrl(crl);
1464 	}
1465 
1466 	return (rv);
1467 }
1468 
1469 
1470 KMF_RETURN
1471 NSS_FindCRL(KMF_HANDLE_T handle, KMF_FINDCRL_PARAMS *params,
1472 	char **CRLNameList, int *CRLCount)
1473 {
1474 	KMF_RETURN rv = KMF_OK;
1475 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1476 	PK11SlotInfo *nss_slot = NULL;
1477 	CERTCrlHeadNode *crlList = NULL;
1478 	CERTCrlNode *crlNode = NULL;
1479 	PRArenaPool *arena = NULL;
1480 	CERTName *name = NULL;
1481 	SECStatus nssrv;
1482 	char *asciiname = NULL;
1483 	int crl_num;
1484 	int i;
1485 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
1486 
1487 	if (CRLCount == NULL || params == NULL) {
1488 		return (KMF_ERR_BAD_PARAMETER);
1489 	}
1490 
1491 	*CRLCount = 0;
1492 
1493 	rv = Do_NSS_Init(handle,
1494 		params->ks_opt_u.nss_opts, TRUE, &nss_slot);
1495 	if (rv != KMF_OK) {
1496 		return (rv);
1497 	}
1498 
1499 	/* Look up Crls */
1500 	nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
1501 	if (nssrv) {
1502 		SET_ERROR(kmfh, rv);
1503 		rv = KMF_ERR_CRL_NOT_FOUND;
1504 		goto out;
1505 	}
1506 
1507 	/* Allocate space for name first */
1508 	arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
1509 	if (arena == NULL) {
1510 	    rv = KMF_ERR_MEMORY;
1511 	    goto out;
1512 	}
1513 
1514 	name = PORT_ArenaZAlloc(arena, sizeof (*name));
1515 	if (name == NULL) {
1516 		rv = KMF_ERR_MEMORY;
1517 		goto out;
1518 	}
1519 	name->arena = arena;
1520 
1521 	/*
1522 	 * Loop thru the crlList and create a crl list with CRL's subject name.
1523 	 */
1524 	crlNode  = crlList->first;
1525 	crl_num = 0;
1526 	while (crlNode) {
1527 		char *subj_name;
1528 
1529 		/* Get the CRL subject name */
1530 		name = &crlNode->crl->crl.name;
1531 		if (!name) {
1532 			SET_ERROR(kmfh, PORT_GetError());
1533 			rv = KMF_ERR_CRL_NOT_FOUND;
1534 			break;
1535 		}
1536 
1537 
1538 		if (CRLNameList != NULL) {
1539 			asciiname = CERT_NameToAscii(name);
1540 			if (asciiname == NULL) {
1541 				SET_ERROR(kmfh, PORT_GetError());
1542 				rv = KMF_ERR_CRL_NOT_FOUND;
1543 				break;
1544 			}
1545 			subj_name = strdup(asciiname);
1546 			PORT_Free(asciiname);
1547 			if (subj_name == NULL) {
1548 				rv = KMF_ERR_MEMORY;
1549 				break;
1550 			}
1551 			CRLNameList[crl_num] = subj_name;
1552 		}
1553 
1554 		crl_num++;
1555 		crlNode = crlNode->next;
1556 	}
1557 
1558 	if (rv == KMF_OK) {
1559 		/* success */
1560 		*CRLCount = crl_num;
1561 	}
1562 
1563 out:
1564 	if (nss_slot != NULL) {
1565 		PK11_FreeSlot(nss_slot);
1566 	}
1567 
1568 	if (crlList != NULL) {
1569 		PORT_FreeArena(crlList->arena, PR_FALSE);
1570 	}
1571 
1572 	if (arena != NULL) {
1573 		PORT_FreeArena(arena, PR_FALSE);
1574 	}
1575 
1576 	/* If failed, free memory allocated for the returning rlist */
1577 	if (rv && (CRLNameList != NULL)) {
1578 		for (i = 0; i < crl_num; i++) {
1579 			free(CRLNameList[i]);
1580 		}
1581 	}
1582 
1583 	return (rv);
1584 }
1585 
1586 
1587 KMF_RETURN
1588 NSS_FindCertInCRL(KMF_HANDLE_T handle, KMF_FINDCERTINCRL_PARAMS *params)
1589 {
1590 	KMF_RETURN rv = KMF_OK;
1591 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1592 	PK11SlotInfo *nss_slot = NULL;
1593 	CERTCertificate *cert = NULL;
1594 	CERTSignedCrl *crl = NULL;
1595 	CERTCrlEntry *entry;
1596 	boolean_t match = B_FALSE;
1597 	int i;
1598 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
1599 
1600 	/* check params */
1601 	if (params == NULL ||
1602 	    (params->ks_opt_u.nss_opts.certLabel == NULL &&
1603 	    params->ks_opt_u.nss_opts.certificate == NULL)) {
1604 		return (KMF_ERR_BAD_PARAMETER);
1605 	}
1606 
1607 	rv = Do_NSS_Init(handle,
1608 		params->ks_opt_u.nss_opts, TRUE, &nss_slot);
1609 	if (rv != KMF_OK) {
1610 		return (rv);
1611 	}
1612 
1613 	/* Find the certificate first */
1614 	if (params->ks_opt_u.nss_opts.certLabel != NULL) {
1615 		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
1616 		    params->ks_opt_u.nss_opts.certLabel);
1617 	} else {
1618 		SECItem derCert = { NULL, 0};
1619 
1620 		derCert.data = params->ks_opt_u.nss_opts.certificate->Data;
1621 		derCert.len =  params->ks_opt_u.nss_opts.certificate->Length;
1622 		cert = CERT_FindCertByDERCert(certHandle, &derCert);
1623 	}
1624 
1625 	if (!cert) {
1626 		SET_ERROR(kmfh, PORT_GetError());
1627 		rv = KMF_ERR_CERT_NOT_FOUND;
1628 		goto out;
1629 	}
1630 
1631 	/* Find the CRL with the same issuer as the given certificate. */
1632 	crl = SEC_FindCrlByName(certHandle, &cert->derIssuer, SEC_CRL_TYPE);
1633 	if (crl == NULL) {
1634 		/*
1635 		 * Could not find the CRL issued by the same issuer. This
1636 		 * usually means that the CRL is not installed in the DB.
1637 		 */
1638 		SET_ERROR(kmfh, PORT_GetError());
1639 		rv = KMF_ERR_CRL_NOT_FOUND;
1640 		goto out;
1641 
1642 	}
1643 
1644 	/* Check if the certificate's serialNumber is revoked in the CRL */
1645 	i = 0;
1646 	while ((entry = (crl->crl).entries[i++]) != NULL) {
1647 		if (SECITEM_CompareItem(&(cert->serialNumber),
1648 		    &(entry->serialNumber)) == SECEqual) {
1649 			match = B_TRUE;
1650 			break;
1651 		}
1652 	}
1653 
1654 	if (!match) {
1655 		rv = KMF_ERR_NOT_REVOKED;
1656 	}
1657 
1658 out:
1659 	if (nss_slot != NULL) {
1660 		PK11_FreeSlot(nss_slot);
1661 	}
1662 
1663 	if (cert != NULL) {
1664 		CERT_DestroyCertificate(cert);
1665 	}
1666 
1667 	if (crl != NULL) {
1668 		SEC_DestroyCrl(crl);
1669 	}
1670 
1671 	return (rv);
1672 }
1673 
1674 KMF_RETURN
1675 NSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1676 {
1677 	KMF_RETURN ret = KMF_OK;
1678 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1679 	char *str;
1680 
1681 	/* Get the error string in the default language */
1682 	str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode);
1683 
1684 	if (str != NULL) {
1685 		*msgstr = (char *)strdup(str);
1686 		if ((*msgstr) == NULL)
1687 			ret = KMF_ERR_MEMORY;
1688 	} else {
1689 		*msgstr = NULL;
1690 	}
1691 
1692 	return (ret);
1693 }
1694 
1695 KMF_RETURN
1696 NSS_GetPrikeyByCert(KMF_HANDLE_T handle, KMF_CRYPTOWITHCERT_PARAMS *params,
1697 	KMF_DATA *SignerCertData, KMF_KEY_HANDLE *key,
1698 	KMF_KEY_ALG keytype)
1699 {
1700 	CERTCertificate *nss_cert = NULL;
1701 	SECKEYPrivateKey* privkey = NULL;
1702 	PK11SlotInfo *nss_slot = NULL;
1703 	KMF_RETURN rv = KMF_OK;
1704 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1705 
1706 	rv = Do_NSS_Init(handle,
1707 		params->nssparms, FALSE, &nss_slot);
1708 	if (rv != KMF_OK) {
1709 		return (rv);
1710 	}
1711 
1712 	rv = nss_authenticate(handle, nss_slot, &params->cred);
1713 	if (rv != KMF_OK) {
1714 		return (rv);
1715 	}
1716 
1717 	nss_cert = CERT_DecodeCertFromPackage((char *)SignerCertData->Data,
1718 	    SignerCertData->Length);
1719 
1720 	if (nss_cert == NULL) {
1721 		SET_ERROR(kmfh, PORT_GetError());
1722 		return (KMF_ERR_BAD_CERT_FORMAT);
1723 	}
1724 
1725 	privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL);
1726 	if (privkey == NULL) {
1727 		SET_ERROR(kmfh, PORT_GetError());
1728 		return (KMF_ERR_KEY_NOT_FOUND);
1729 	}
1730 
1731 	key->kstype = KMF_KEYSTORE_NSS;
1732 	key->keyclass = KMF_ASYM_PRI;
1733 	key->keyalg = keytype;
1734 	key->keyp = (void *)privkey;
1735 	key->keylabel = PK11_GetPrivateKeyNickname(privkey);
1736 
1737 	CERT_DestroyCertificate(nss_cert);
1738 
1739 	return (KMF_OK);
1740 
1741 }
1742 
1743 KMF_RETURN
1744 NSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1745 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
1746 	KMF_DATA *output)
1747 {
1748 	KMF_RETURN		ret = KMF_OK;
1749 	SECKEYPrivateKey	*NSSprivkey = NULL;
1750 	SECStatus		rv;
1751 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
1752 	unsigned int in_len = 0, out_len = 0;
1753 	unsigned int total_decrypted = 0, modulus_len = 0;
1754 	uint8_t *in_data, *out_data;
1755 	int i, blocks;
1756 
1757 
1758 	if (key == NULL || AlgOID == NULL ||
1759 	    ciphertext == NULL || output == NULL ||
1760 	    ciphertext->Data == NULL ||
1761 	    output->Data == NULL)
1762 		return (KMF_ERR_BAD_PARAMETER);
1763 
1764 	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1765 	modulus_len = PK11_GetPrivateModulusLen(NSSprivkey);
1766 
1767 	blocks = ciphertext->Length/modulus_len;
1768 	out_data = output->Data;
1769 	in_data = ciphertext->Data;
1770 	out_len = modulus_len - 11;
1771 	in_len = modulus_len;
1772 
1773 	for (i = 0; i < blocks; i++) {
1774 		rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data,
1775 		    &out_len, ciphertext->Length, in_data, in_len);
1776 
1777 		if (rv != 0) {
1778 			SET_ERROR(kmfh, rv);
1779 			return (KMF_ERR_INTERNAL);
1780 		}
1781 
1782 		out_data += out_len;
1783 		total_decrypted += out_len;
1784 		in_data += in_len;
1785 	}
1786 
1787 	output->Length = total_decrypted;
1788 
1789 	return (ret);
1790 }
1791 
1792 static KMF_KEY_ALG
1793 pk11keytype2kmf(CK_KEY_TYPE type)
1794 {
1795 	switch (type) {
1796 	case CKK_RSA:
1797 		return (KMF_RSA);
1798 	case CKK_DSA:
1799 		return (KMF_RSA);
1800 	case CKK_AES:
1801 		return (KMF_AES);
1802 	case CKK_RC4:
1803 		return (KMF_RC4);
1804 	case CKK_DES:
1805 		return (KMF_DES);
1806 	case CKK_DES3:
1807 		return (KMF_DES3);
1808 	default:
1809 		/* not supported */
1810 		return (KMF_KEYALG_NONE);
1811 	}
1812 }
1813 
1814 KMF_RETURN
1815 NSS_FindKey(KMF_HANDLE_T handle, KMF_FINDKEY_PARAMS *parms,
1816 	KMF_KEY_HANDLE *keys, uint32_t *numkeys)
1817 {
1818 	KMF_RETURN rv;
1819 	SECKEYPrivateKeyList *prilist;
1820 	SECKEYPrivateKeyListNode *prinode;
1821 	SECKEYPublicKeyList *publist;
1822 	SECKEYPublicKeyListNode *pubnode;
1823 	PK11SlotInfo *nss_slot = NULL;
1824 	PK11SymKey *symlist = NULL;
1825 	int count;
1826 	uint32_t maxkeys;
1827 
1828 	rv = Do_NSS_Init(handle,
1829 		parms->ks_opt_u.nss_opts, FALSE, &nss_slot);
1830 	if (rv != KMF_OK) {
1831 		return (rv);
1832 	}
1833 
1834 	rv = nss_authenticate(handle, nss_slot, &parms->cred);
1835 	if (rv != KMF_OK) {
1836 		return (rv);
1837 	}
1838 
1839 	maxkeys = *numkeys;
1840 	if (maxkeys == 0)
1841 		maxkeys = 0xFFFFFFFF;
1842 
1843 	*numkeys = 0;
1844 	if (parms->keyclass == KMF_ASYM_PUB) {
1845 		publist = PK11_ListPublicKeysInSlot(nss_slot, parms->findLabel);
1846 		if (publist == NULL) {
1847 			rv = KMF_ERR_KEY_NOT_FOUND;
1848 			goto cleanup;
1849 		}
1850 	} else if (parms->keyclass == KMF_ASYM_PRI) {
1851 		prilist = PK11_ListPrivKeysInSlot(nss_slot,
1852 			parms->findLabel, NULL);
1853 		if (prilist == NULL) {
1854 			rv = KMF_ERR_KEY_NOT_FOUND;
1855 			goto cleanup;
1856 		}
1857 	} else if (parms->keyclass == KMF_SYMMETRIC) {
1858 		symlist = PK11_ListFixedKeysInSlot(nss_slot, parms->findLabel,
1859 		    NULL);
1860 		if (symlist == NULL) {
1861 			rv = KMF_ERR_KEY_NOT_FOUND;
1862 			goto cleanup;
1863 		}
1864 	} else {
1865 		rv = KMF_ERR_BAD_KEY_CLASS;
1866 		goto cleanup;
1867 	}
1868 
1869 	if (parms->keyclass == KMF_ASYM_PUB) {
1870 		for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist);
1871 			!PUBKEY_LIST_END(pubnode, publist) &&
1872 			count < maxkeys;
1873 			pubnode = PUBKEY_LIST_NEXT(pubnode), count++) {
1874 			if (keys != NULL) {
1875 				keys[count].kstype = KMF_KEYSTORE_NSS;
1876 				keys[count].keyclass = KMF_ASYM_PUB;
1877 				keys[count].keyp = (void *)pubnode->key;
1878 				keys[count].keylabel =
1879 					PK11_GetPublicKeyNickname(
1880 						pubnode->key);
1881 
1882 				if (pubnode->key->keyType == rsaKey)
1883 					keys[count].keyalg = KMF_RSA;
1884 				else if (pubnode->key->keyType == dsaKey)
1885 					keys[count].keyalg = KMF_DSA;
1886 			}
1887 		}
1888 		*numkeys = count;
1889 	} else if (parms->keyclass == KMF_ASYM_PRI) {
1890 		for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist);
1891 			!PRIVKEY_LIST_END(prinode, prilist) &&
1892 			count < maxkeys;
1893 			prinode = PRIVKEY_LIST_NEXT(prinode), count++) {
1894 			if (keys != NULL) {
1895 				keys[count].kstype = KMF_KEYSTORE_NSS;
1896 				keys[count].keyclass = KMF_ASYM_PRI;
1897 				keys[count].keyp = (void *)prinode->key;
1898 				keys[count].keylabel =
1899 					PK11_GetPrivateKeyNickname(
1900 						prinode->key);
1901 
1902 				if (prinode->key->keyType == rsaKey)
1903 					keys[count].keyalg = KMF_RSA;
1904 				else if (prinode->key->keyType == dsaKey)
1905 					keys[count].keyalg = KMF_DSA;
1906 			}
1907 		}
1908 		*numkeys = count;
1909 	} else if (parms->keyclass == KMF_SYMMETRIC) {
1910 		count = 0;
1911 		while (symlist && count < maxkeys) {
1912 			PK11SymKey *symkey = symlist;
1913 			CK_KEY_TYPE type;
1914 			KMF_KEY_ALG keyalg;
1915 
1916 			type = PK11_GetSymKeyType(symkey);
1917 			keyalg = pk11keytype2kmf(type);
1918 
1919 			/*
1920 			 * If keytype is specified in the searching parameter,
1921 			 * check the keytype and skip the key if its keytype
1922 			 * doesn't match.
1923 			 */
1924 			symlist = PK11_GetNextSymKey(symkey);
1925 			if (parms->keytype != KMF_KEYALG_NONE &&
1926 			    parms->keytype != keyalg) {
1927 				/* free that key since we aren't using it */
1928 				PK11_FreeSymKey(symkey);
1929 				continue;
1930 			}
1931 
1932 			if (keys != NULL) {
1933 				keys[count].kstype = KMF_KEYSTORE_NSS;
1934 				keys[count].keyclass = KMF_SYMMETRIC;
1935 				keys[count].keyp = (void *) symkey;
1936 				keys[count].keylabel =
1937 				    PK11_GetSymKeyNickname(symkey);
1938 				keys[count].keyalg = keyalg;
1939 			} else {
1940 				PK11_FreeSymKey(symkey);
1941 			}
1942 			count++;
1943 		}
1944 		/*
1945 		 * Cleanup memory for unused keys.
1946 		 */
1947 		while (symlist != NULL) {
1948 			PK11SymKey *symkey = symlist;
1949 			PK11_FreeSymKey(symkey);
1950 			symlist = PK11_GetNextSymKey(symkey);
1951 		}
1952 	}
1953 
1954 	*numkeys = count;
1955 cleanup:
1956 	if (nss_slot != NULL) {
1957 		PK11_FreeSlot(nss_slot);
1958 	}
1959 
1960 	return (rv);
1961 }
1962 
1963 static SECStatus
1964 p12u_SwapUnicodeBytes(SECItem *uniItem)
1965 {
1966 	unsigned int i;
1967 	unsigned char a;
1968 	if ((uniItem == NULL) || (uniItem->len % 2)) {
1969 		return (SECFailure);
1970 		}
1971 	for (i = 0; i < uniItem->len; i += 2) {
1972 		a = uniItem->data[i];
1973 		uniItem->data[i] = uniItem->data[i+1];
1974 		uniItem->data[i+1] = a;
1975 	}
1976 	return (SECSuccess);
1977 }
1978 
1979 static PRBool
1980 p12u_ucs2_ascii_conversion_function(
1981 	PRBool		toUnicode,
1982 	unsigned char	*inBuf,
1983 	unsigned int	inBufLen,
1984 	unsigned char	*outBuf,
1985 	unsigned int	maxOutBufLen,
1986 	unsigned int	*outBufLen,
1987 	PRBool		swapBytes)
1988 {
1989 	SECItem it = { 0 };
1990 	SECItem *dup = NULL;
1991 	PRBool ret;
1992 
1993 	it.data = inBuf;
1994 	it.len = inBufLen;
1995 	dup = SECITEM_DupItem(&it);
1996 	/*
1997 	 * If converting Unicode to ASCII, swap bytes before conversion
1998 	 * as neccessary.
1999 	 */
2000 	if (!toUnicode && swapBytes) {
2001 		if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
2002 			SECITEM_ZfreeItem(dup, PR_TRUE);
2003 			return (PR_FALSE);
2004 		}
2005 	}
2006 	/* Perform the conversion. */
2007 	ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
2008 		outBuf, maxOutBufLen, outBufLen);
2009 	if (dup)
2010 		SECITEM_ZfreeItem(dup, PR_TRUE);
2011 
2012 	return (ret);
2013 }
2014 
2015 static PRBool
2016 p12u_OpenFile(p12uContext *p12ctx, PRBool fileRead)
2017 {
2018 	if (!p12ctx || !p12ctx->filename) {
2019 		return (PR_FALSE);
2020 	}
2021 
2022 	if (fileRead) {
2023 		p12ctx->file = PR_Open(p12ctx->filename,
2024 			PR_RDONLY, 0400);
2025 	} else {
2026 		p12ctx->file = PR_Open(p12ctx->filename,
2027 			PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600);
2028 	}
2029 
2030 	if (!p12ctx->file) {
2031 		p12ctx->error = PR_TRUE;
2032 		return (PR_FALSE);
2033 	}
2034 
2035 	return (PR_TRUE);
2036 }
2037 
2038 static void
2039 p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
2040 {
2041 	if (!ppCtx || !(*ppCtx)) {
2042 		return;
2043 	}
2044 
2045 	if ((*ppCtx)->file != NULL) {
2046 		PR_Close((*ppCtx)->file);
2047 	}
2048 
2049 	if ((*ppCtx)->filename != NULL) {
2050 		if (removeFile) {
2051 			PR_Delete((*ppCtx)->filename);
2052 		}
2053 		free((*ppCtx)->filename);
2054 	}
2055 
2056 	free(*ppCtx);
2057 	*ppCtx = NULL;
2058 }
2059 
2060 static p12uContext *
2061 p12u_InitContext(PRBool fileImport, char *filename)
2062 {
2063 	p12uContext *p12ctx;
2064 
2065 	p12ctx = PORT_ZNew(p12uContext);
2066 	if (!p12ctx) {
2067 		return (NULL);
2068 	}
2069 
2070 	p12ctx->error = PR_FALSE;
2071 	p12ctx->errorValue = 0;
2072 	p12ctx->filename = strdup(filename);
2073 
2074 	if (!p12u_OpenFile(p12ctx, fileImport)) {
2075 		p12u_DestroyContext(&p12ctx, PR_FALSE);
2076 		return (NULL);
2077 	}
2078 
2079 	return (p12ctx);
2080 }
2081 
2082 static void
2083 p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
2084 {
2085 	p12uContext *p12cxt = arg;
2086 	int writeLen;
2087 
2088 	if (!p12cxt || (p12cxt->error == PR_TRUE)) {
2089 		return;
2090 	}
2091 
2092 	if (p12cxt->file == NULL) {
2093 		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
2094 		p12cxt->error = PR_TRUE;
2095 		return;
2096 	}
2097 
2098 	writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
2099 
2100 	if (writeLen != (int)len) {
2101 		PR_Close(p12cxt->file);
2102 		free(p12cxt->filename);
2103 		p12cxt->filename = NULL;
2104 		p12cxt->file = NULL;
2105 		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
2106 		p12cxt->error = PR_TRUE;
2107 	}
2108 }
2109 
2110 #define	HANDLE_NSS_ERROR(r) {\
2111 	SET_ERROR(kmfh, PORT_GetError()); \
2112 	rv = r; \
2113 	goto out; }
2114 
2115 static KMF_RETURN
2116 add_cert_to_bag(SEC_PKCS12ExportContext *p12ecx,
2117 	CERTCertificate *cert, SECItem *pwitem)
2118 {
2119 	KMF_RETURN rv = KMF_OK;
2120 	SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
2121 
2122 	keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
2123 	if (PK11_IsFIPS()) {
2124 		certSafe = keySafe;
2125 	} else {
2126 		certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
2127 			SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
2128 	}
2129 
2130 	if (!certSafe || !keySafe) {
2131 		rv = KMF_ERR_INTERNAL;
2132 		goto out;
2133 	}
2134 
2135 	if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
2136 		CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
2137 		SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
2138 		!= SECSuccess) {
2139 		rv = KMF_ERR_INTERNAL;
2140 	}
2141 out:
2142 	return (rv);
2143 }
2144 
2145 /*ARGSUSED*/
2146 KMF_RETURN
2147 NSS_ExportP12(KMF_HANDLE_T handle,
2148 	KMF_EXPORTP12_PARAMS *params,
2149 	int numcerts, KMF_X509_DER_CERT *certs,
2150 	int numkeys, KMF_KEY_HANDLE *keylist,
2151 	char *filename)
2152 {
2153 	KMF_RETURN rv;
2154 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
2155 	SEC_PKCS12ExportContext *p12ecx = NULL;
2156 	p12uContext *p12ctx = NULL;
2157 	CERTCertList *certlist = NULL;
2158 	CERTCertificate *nsscert = NULL;
2159 	CERTCertListNode* node = NULL;
2160 	PK11SlotInfo	*slot = NULL;
2161 	SECItem pwitem = {NULL, 0};
2162 
2163 	rv = Do_NSS_Init(handle,
2164 		params->nssparms, FALSE, &slot);
2165 	if (rv != KMF_OK) {
2166 		return (rv);
2167 	}
2168 
2169 	rv = nss_authenticate(handle, slot, &params->cred);
2170 	if (rv != KMF_OK) {
2171 		return (rv);
2172 	}
2173 
2174 	/*
2175 	 * Find the certificate(s) first.
2176 	 */
2177 	if (params->certLabel) {
2178 		nsscert = PK11_FindCertFromNickname(params->certLabel,
2179 			NULL);
2180 		if (nsscert == NULL) {
2181 			HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND)
2182 		}
2183 	} else {
2184 		rv = nss_find_matching_certs(slot,
2185 			params->issuer,
2186 			params->subject,
2187 			params->serial,
2188 			&certlist, 0);
2189 
2190 		if (rv == KMF_OK && certlist == NULL) {
2191 			return (KMF_ERR_CERT_NOT_FOUND);
2192 		}
2193 		if (rv != KMF_OK)
2194 			return (rv);
2195 	}
2196 
2197 	/*
2198 	 * The KMF_CREDENTIAL holds the password to use for
2199 	 * encrypting the PKCS12 key information.
2200 	 */
2201 	pwitem.data = (uchar_t *)params->p12cred.cred;
2202 	pwitem.len = params->p12cred.credlen;
2203 
2204 	p12ctx = p12u_InitContext(PR_FALSE, filename);
2205 	if (!p12ctx) {
2206 		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
2207 	}
2208 
2209 	PORT_SetUCS2_ASCIIConversionFunction(
2210 		p12u_ucs2_ascii_conversion_function);
2211 
2212 	p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL,
2213 		slot, NULL);
2214 	if (!p12ecx) {
2215 		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
2216 	}
2217 
2218 	if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
2219 		!= SECSuccess) {
2220 		HANDLE_NSS_ERROR(KMF_ERR_INTERNAL)
2221 	}
2222 
2223 	/*
2224 	 * NSS actually supports storing a list of keys and certs
2225 	 * in the PKCS#12 PDU.  Nice feature.
2226 	 */
2227 	if (certlist != NULL) {
2228 		for (node = CERT_LIST_HEAD(certlist);
2229 			!CERT_LIST_END(node, certlist) && rv == KMF_OK;
2230 			node = CERT_LIST_NEXT(node)) {
2231 
2232 			rv = add_cert_to_bag(p12ecx, node->cert, &pwitem);
2233 		}
2234 	} else if (nsscert != NULL) {
2235 		rv = add_cert_to_bag(p12ecx, nsscert, &pwitem);
2236 	}
2237 
2238 	if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx)
2239 		!= SECSuccess) {
2240 		HANDLE_NSS_ERROR(KMF_ERR_ENCODING)
2241 	}
2242 out:
2243 	if (nsscert)
2244 		CERT_DestroyCertificate(nsscert);
2245 
2246 	if (certlist)
2247 		CERT_DestroyCertList(certlist);
2248 
2249 	if (p12ctx)
2250 		p12u_DestroyContext(&p12ctx, PR_FALSE);
2251 
2252 	if (p12ecx)
2253 		SEC_PKCS12DestroyExportContext(p12ecx);
2254 
2255 	return (rv);
2256 }
2257 
2258 #define	SETATTR(t, n, atype, value, size) \
2259 	t[n].type = atype; \
2260 	t[n].pValue = (CK_BYTE *)value; \
2261 	t[n].ulValueLen = (CK_ULONG)size;
2262 
2263 KMF_RETURN
2264 NSS_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
2265 	KMF_RAW_KEY_DATA *rawkey)
2266 {
2267 	KMF_RETURN rv = KMF_OK;
2268 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2269 	SECStatus	ckrv = SECSuccess;
2270 	PK11SlotInfo	*slot = NULL;
2271 	CERTCertificate *nss_cert = NULL;
2272 	SECKEYPrivateKeyInfo rpk;
2273 	SECItem		nickname;
2274 	KMF_DATA	derkey = { NULL, 0 };
2275 	uchar_t		ver = 0;
2276 
2277 	if (!kmfh)
2278 		return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2279 
2280 	if (params == NULL || params->certificate == NULL || rawkey == NULL)
2281 		return (KMF_ERR_BAD_PARAMETER);
2282 
2283 	rv = Do_NSS_Init(handle,
2284 		params->nssparms, FALSE, &slot);
2285 
2286 	if (rv != KMF_OK)
2287 		return (rv);
2288 
2289 	rv = nss_authenticate(handle, slot, &params->cred);
2290 	if (rv != KMF_OK) {
2291 		return (rv);
2292 	}
2293 
2294 	/*
2295 	 * Decode the cert into an NSS CERT object so we can access the
2296 	 * SPKI and KeyUsage data later.
2297 	 */
2298 	nss_cert = CERT_DecodeCertFromPackage((char *)params->certificate->Data,
2299 		params->certificate->Length);
2300 
2301 	if (nss_cert == NULL) {
2302 		SET_ERROR(kmfh, PORT_GetError());
2303 		rv = KMF_ERR_BAD_CERT_FORMAT;
2304 		goto cleanup;
2305 	}
2306 
2307 	(void) memset(&rpk, 0, sizeof (rpk));
2308 
2309 	rpk.arena = NULL;
2310 	rpk.version.type = siUnsignedInteger;
2311 	rpk.version.data = &ver;
2312 	rpk.version.len = 1;
2313 	if (rawkey->keytype == KMF_RSA) {
2314 
2315 		rv = DerEncodeRSAPrivateKey(&derkey, &rawkey->rawdata.rsa);
2316 		if (rv != KMF_OK)
2317 			goto cleanup;
2318 
2319 		rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
2320 		rpk.privateKey.data = derkey.Data;
2321 		rpk.privateKey.len = derkey.Length;
2322 		rpk.attributes = NULL;
2323 
2324 
2325 	} else if (rawkey->keytype == KMF_DSA) {
2326 		rv = DerEncodeDSAPrivateKey(&derkey, &rawkey->rawdata.dsa);
2327 		if (rv != KMF_OK)
2328 			goto cleanup;
2329 
2330 		rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
2331 		rpk.privateKey.data = derkey.Data;
2332 		rpk.privateKey.len = derkey.Length;
2333 		rpk.attributes = NULL;
2334 
2335 	} else {
2336 		return (KMF_ERR_BAD_PARAMETER);
2337 	}
2338 
2339 	nickname.data = (uchar_t *)params->label;
2340 	nickname.len = (params->label ? strlen(params->label) : 0);
2341 
2342 	ckrv = PK11_ImportPrivateKeyInfo(slot, &rpk,
2343 		&nickname, &nss_cert->subjectPublicKeyInfo.subjectPublicKey,
2344 		TRUE, TRUE, nss_cert->keyUsage, NULL);
2345 
2346 	if (ckrv != CKR_OK) {
2347 		SET_ERROR(kmfh, PORT_GetError());
2348 		rv = KMF_ERR_INTERNAL;
2349 	}
2350 
2351 cleanup:
2352 	if (nss_cert != NULL) {
2353 		CERT_DestroyCertificate(nss_cert);
2354 	}
2355 	KMF_FreeData(&derkey);
2356 	return (rv);
2357 }
2358 
2359 KMF_RETURN
2360 NSS_CreateSymKey(KMF_HANDLE_T handle,
2361 	KMF_CREATESYMKEY_PARAMS *params,
2362 	KMF_KEY_HANDLE *symkey)
2363 {
2364 	KMF_RETURN rv = KMF_OK;
2365 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2366 	PK11SlotInfo *nss_slot = NULL;
2367 	PK11SymKey *nsskey = NULL;
2368 	CK_MECHANISM_TYPE keyType;
2369 	SECStatus nssrv;
2370 	int keySize;
2371 
2372 	if (params == NULL || symkey == NULL) {
2373 		return (KMF_ERR_BAD_PARAMETER);
2374 	}
2375 
2376 	switch (params->keytype) {
2377 	case KMF_AES:
2378 		keyType = CKM_AES_KEY_GEN;
2379 		keySize = params->keylength;
2380 		if (keySize == 0 || (keySize % 8) != 0)
2381 			return (KMF_ERR_BAD_KEY_SIZE);
2382 		break;
2383 	case KMF_RC4:
2384 		keyType = CKM_RC4_KEY_GEN;
2385 		keySize = params->keylength;
2386 		if (keySize == 0 || (keySize % 8) != 0)
2387 			return (KMF_ERR_BAD_KEY_SIZE);
2388 		break;
2389 	case KMF_DES:
2390 		keyType = CKM_DES_KEY_GEN;
2391 		keySize = 0; /* required by PK11_TokenKeyGen()  */
2392 		break;
2393 	case KMF_DES3:
2394 		keyType = CKM_DES3_KEY_GEN;
2395 		keySize = 0; /* required by PK11_TokenKeyGen() */
2396 		break;
2397 	case KMF_GENERIC_SECRET:
2398 		keyType = CKM_GENERIC_SECRET_KEY_GEN;
2399 		keySize = params->keylength;
2400 		if (keySize == 0 || (keySize % 8) != 0)
2401 			return (KMF_ERR_BAD_KEY_SIZE);
2402 		break;
2403 	default:
2404 		rv = KMF_ERR_BAD_KEY_TYPE;
2405 		goto out;
2406 	}
2407 
2408 	rv = Do_NSS_Init(handle,
2409 		params->ks_opt_u.nss_opts, FALSE, &nss_slot);
2410 	if (rv != KMF_OK) {
2411 		return (rv);
2412 	}
2413 
2414 	rv = nss_authenticate(handle, nss_slot, &params->cred);
2415 	if (rv != KMF_OK) {
2416 		return (rv);
2417 	}
2418 
2419 	nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize,  NULL,
2420 	    PR_TRUE, (void *)params->cred.cred);
2421 	if (nsskey == NULL) {
2422 		SET_ERROR(kmfh, PORT_GetError());
2423 		rv = KMF_ERR_KEYGEN_FAILED;
2424 		goto out;
2425 	}
2426 
2427 	nssrv = PK11_SetSymKeyNickname(nsskey, params->keylabel);
2428 	if (nssrv != SECSuccess) {
2429 		SET_ERROR(kmfh, PORT_GetError());
2430 		rv = KMF_ERR_KEYGEN_FAILED;
2431 		goto out;
2432 	}
2433 
2434 	symkey->kstype = KMF_KEYSTORE_NSS;
2435 	symkey->keyalg = params->keytype;
2436 	symkey->keyclass = KMF_SYMMETRIC;
2437 	symkey->israw = FALSE;
2438 	symkey->keyp = (void *)nsskey;
2439 
2440 out:
2441 	if (nss_slot != NULL)
2442 		PK11_FreeSlot(nss_slot);
2443 
2444 	if (rv != KMF_OK && nsskey != NULL) {
2445 		PK11_DeleteTokenSymKey(nsskey);
2446 		PK11_FreeSymKey(nsskey);
2447 	}
2448 	return (rv);
2449 }
2450 
2451 KMF_RETURN
2452 NSS_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2453 	KMF_RAW_SYM_KEY *rkey)
2454 {
2455 	KMF_RETURN rv = KMF_OK;
2456 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2457 	SECItem *value = NULL;
2458 	PK11SymKey *nsskey;
2459 	SECStatus nss_rv;
2460 
2461 	if (kmfh == NULL)
2462 		return (KMF_ERR_UNINITIALIZED);
2463 
2464 	if (symkey == NULL || rkey == NULL)
2465 		return (KMF_ERR_BAD_PARAMETER);
2466 	else if (symkey->keyclass != KMF_SYMMETRIC)
2467 		return (KMF_ERR_BAD_KEY_CLASS);
2468 
2469 	if (symkey->israw) {
2470 		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2471 
2472 		if (rawkey == NULL ||
2473 		    rawkey->rawdata.sym.keydata.val == NULL ||
2474 		    rawkey->rawdata.sym.keydata.len == 0)
2475 			return (KMF_ERR_BAD_KEYHANDLE);
2476 
2477 		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2478 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2479 			return (KMF_ERR_MEMORY);
2480 		(void) memcpy(rkey->keydata.val,
2481 			rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2482 	} else {
2483 		nsskey = (PK11SymKey *)(symkey->keyp);
2484 		if (nsskey == NULL)
2485 			return (KMF_ERR_BAD_KEYHANDLE);
2486 
2487 		nss_rv = PK11_ExtractKeyValue(nsskey);
2488 		if (nss_rv != SECSuccess) {
2489 			SET_ERROR(kmfh, PORT_GetError());
2490 			rv = KMF_ERR_GETKEYVALUE_FAILED;
2491 			goto out;
2492 		}
2493 
2494 		value = PK11_GetKeyData(nsskey);
2495 		if (value == NULL) {
2496 			SET_ERROR(kmfh, PORT_GetError());
2497 			rv = KMF_ERR_GETKEYVALUE_FAILED;
2498 			goto out;
2499 		}
2500 
2501 		if (value->len == 0 || value->data == NULL) {
2502 			rv = KMF_ERR_GETKEYVALUE_FAILED;
2503 			goto out;
2504 		}
2505 
2506 		rkey->keydata.val = malloc(value->len);
2507 		if (rkey->keydata.val == NULL) {
2508 			rv = KMF_ERR_MEMORY;
2509 			goto out;
2510 		}
2511 		(void) memcpy(rkey->keydata.val, value->data, value->len);
2512 		rkey->keydata.len = value->len;
2513 		(void) memset(value->data, 0, value->len);
2514 	}
2515 out:
2516 	if (value != NULL)
2517 		SECITEM_FreeItem(value, PR_TRUE);
2518 	return (rv);
2519 }
2520 
2521 KMF_RETURN
2522 NSS_SetTokenPin(KMF_HANDLE_T handle, KMF_SETPIN_PARAMS *params,
2523 	KMF_CREDENTIAL *newpin)
2524 {
2525 	KMF_RETURN ret = KMF_OK;
2526 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2527 	int rv;
2528 	PK11SlotInfo *nss_slot = NULL;
2529 
2530 	if (handle == NULL || params == NULL || newpin == NULL) {
2531 		return (KMF_ERR_BAD_PARAMETER);
2532 	}
2533 
2534 	ret = Do_NSS_Init(handle,
2535 		params->ks_opt_u.nss_opts,
2536 		FALSE, &nss_slot);
2537 	/* If it was uninitialized, set it */
2538 	if (ret == KMF_ERR_UNINITIALIZED_TOKEN) {
2539 		rv = PK11_InitPin(nss_slot, NULL, newpin->cred);
2540 		if (rv != SECSuccess) {
2541 			SET_ERROR(kmfh, PORT_GetError());
2542 			ret = KMF_ERR_AUTH_FAILED;
2543 		} else {
2544 			ret = KMF_OK;
2545 		}
2546 	} else if (ret == KMF_OK) {
2547 		ret = nss_authenticate(handle, nss_slot, &params->cred);
2548 		if (ret != KMF_OK) {
2549 			return (ret);
2550 		}
2551 		rv = PK11_ChangePW(nss_slot,
2552 			params->cred.cred, newpin->cred);
2553 		if (rv != SECSuccess) {
2554 			SET_ERROR(kmfh, PORT_GetError());
2555 			ret = KMF_ERR_AUTH_FAILED;
2556 		}
2557 	}
2558 
2559 	return (ret);
2560 }
2561