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