199ebb4caSwyllys /*
299ebb4caSwyllys  * CDDL HEADER START
399ebb4caSwyllys  *
499ebb4caSwyllys  * The contents of this file are subject to the terms of the
599ebb4caSwyllys  * Common Development and Distribution License (the "License").
699ebb4caSwyllys  * You may not use this file except in compliance with the License.
799ebb4caSwyllys  *
899ebb4caSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999ebb4caSwyllys  * or http://www.opensolaris.org/os/licensing.
1099ebb4caSwyllys  * See the License for the specific language governing permissions
1199ebb4caSwyllys  * and limitations under the License.
1299ebb4caSwyllys  *
1399ebb4caSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
1499ebb4caSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599ebb4caSwyllys  * If applicable, add the following below this CDDL HEADER, with the
1699ebb4caSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
1799ebb4caSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
1899ebb4caSwyllys  *
1999ebb4caSwyllys  * CDDL HEADER END
2099ebb4caSwyllys  */
215ad42b1bSSurya Prakki 
2299ebb4caSwyllys /*
2399ebb4caSwyllys  * NSS keystore wrapper
2499ebb4caSwyllys  *
25e65e5c2dSWyllys Ingersoll  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2699ebb4caSwyllys  * Use is subject to license terms.
27*99bbd8beSAndrew Stormont  *
28*99bbd8beSAndrew Stormont  * Copyright 2021 RackTop Systems, Inc.
2999ebb4caSwyllys  */
3099ebb4caSwyllys 
3199ebb4caSwyllys #include <sys/types.h>
3299ebb4caSwyllys #include <sys/stat.h>
3399ebb4caSwyllys #include <errno.h>
3499ebb4caSwyllys #include <fcntl.h>
3599ebb4caSwyllys #include <synch.h>
3699ebb4caSwyllys 
3799ebb4caSwyllys #include <mps/nss.h>
3899ebb4caSwyllys #include <mps/cert.h>
3999ebb4caSwyllys #include <mps/certdb.h>
4099ebb4caSwyllys #include <mps/secoid.h>
4199ebb4caSwyllys #include <mps/secder.h>
4299ebb4caSwyllys #include <mps/secerr.h>
4399ebb4caSwyllys #include <mps/cryptohi.h>
4499ebb4caSwyllys #include <mps/keyhi.h>
4599ebb4caSwyllys #include <mps/keythi.h>
4699ebb4caSwyllys #include <mps/pk11func.h>
4799ebb4caSwyllys #include <mps/pk11pqg.h>
4899ebb4caSwyllys #include <mps/pkcs12.h>
4999ebb4caSwyllys #include <mps/p12plcy.h>
5099ebb4caSwyllys #include <mps/prerror.h>
5199ebb4caSwyllys 
52*99bbd8beSAndrew Stormont #include <kmfapiP.h>
53*99bbd8beSAndrew Stormont #include <ber_der.h>
54*99bbd8beSAndrew Stormont 
5599ebb4caSwyllys #define	NSS_OK		0
5699ebb4caSwyllys 
5799ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
5899ebb4caSwyllys static int nss_initialized = 0;
5999ebb4caSwyllys 
6099ebb4caSwyllys KMF_RETURN
6130a5e8faSwyllys NSS_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
6299ebb4caSwyllys 
6399ebb4caSwyllys KMF_RETURN
6430a5e8faSwyllys NSS_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
6599ebb4caSwyllys 
6699ebb4caSwyllys void
6799ebb4caSwyllys NSS_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
6899ebb4caSwyllys 
6999ebb4caSwyllys KMF_RETURN
7030a5e8faSwyllys NSS_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
7199ebb4caSwyllys 
7299ebb4caSwyllys KMF_RETURN
7330a5e8faSwyllys NSS_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
7499ebb4caSwyllys 
7599ebb4caSwyllys KMF_RETURN
7630a5e8faSwyllys NSS_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
7799ebb4caSwyllys 
7899ebb4caSwyllys KMF_RETURN
7930a5e8faSwyllys NSS_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
8030a5e8faSwyllys 
8130a5e8faSwyllys KMF_RETURN
8230a5e8faSwyllys NSS_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
8399ebb4caSwyllys 
8499ebb4caSwyllys KMF_RETURN
8599ebb4caSwyllys NSS_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
8699ebb4caSwyllys 
8799ebb4caSwyllys KMF_RETURN
8899ebb4caSwyllys NSS_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
8999ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
9099ebb4caSwyllys 
9199ebb4caSwyllys KMF_RETURN
9230a5e8faSwyllys NSS_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
9399ebb4caSwyllys 
9499ebb4caSwyllys KMF_RETURN
9530a5e8faSwyllys NSS_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
9699ebb4caSwyllys 
9799ebb4caSwyllys KMF_RETURN
9830a5e8faSwyllys NSS_FindCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
9999ebb4caSwyllys 
10099ebb4caSwyllys KMF_RETURN
10130a5e8faSwyllys NSS_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
10299ebb4caSwyllys 
10399ebb4caSwyllys KMF_RETURN
10430a5e8faSwyllys NSS_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
10599ebb4caSwyllys 
10699ebb4caSwyllys KMF_RETURN
10799ebb4caSwyllys NSS_GetErrorString(KMF_HANDLE_T, char **);
10899ebb4caSwyllys 
10999ebb4caSwyllys KMF_RETURN
11030a5e8faSwyllys NSS_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
11199ebb4caSwyllys 
11299ebb4caSwyllys KMF_RETURN
11330a5e8faSwyllys NSS_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
11499ebb4caSwyllys 
11599ebb4caSwyllys KMF_RETURN
11699ebb4caSwyllys NSS_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
11799ebb4caSwyllys 	KMF_DATA *, KMF_DATA *);
11899ebb4caSwyllys 
11999ebb4caSwyllys KMF_RETURN
12030a5e8faSwyllys NSS_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
12199ebb4caSwyllys 
12299ebb4caSwyllys KMF_RETURN
12330a5e8faSwyllys NSS_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
12499ebb4caSwyllys 
12599ebb4caSwyllys KMF_RETURN
12699ebb4caSwyllys NSS_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
12799ebb4caSwyllys 
12899ebb4caSwyllys KMF_RETURN
12930a5e8faSwyllys NSS_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
13099ebb4caSwyllys 
13199ebb4caSwyllys static
13299ebb4caSwyllys KMF_PLUGIN_FUNCLIST nss_plugin_table =
13399ebb4caSwyllys {
13499ebb4caSwyllys 	1,				/* Version */
13599ebb4caSwyllys 	NSS_ConfigureKeystore,
13699ebb4caSwyllys 	NSS_FindCert,
13799ebb4caSwyllys 	NSS_FreeKMFCert,
13899ebb4caSwyllys 	NSS_StoreCert,
13999ebb4caSwyllys 	NSS_ImportCert,
14099ebb4caSwyllys 	NSS_ImportCRL,
14199ebb4caSwyllys 	NSS_DeleteCert,
14299ebb4caSwyllys 	NSS_DeleteCRL,
14399ebb4caSwyllys 	NSS_CreateKeypair,
14499ebb4caSwyllys 	NSS_FindKey,
14599ebb4caSwyllys 	NSS_EncodePubKeyData,
14699ebb4caSwyllys 	NSS_SignData,
14799ebb4caSwyllys 	NSS_DeleteKey,
14899ebb4caSwyllys 	NULL    /* ListCRL */,
14999ebb4caSwyllys 	NSS_FindCRL,
15099ebb4caSwyllys 	NSS_FindCertInCRL,
15199ebb4caSwyllys 	NSS_GetErrorString,
15230a5e8faSwyllys 	NSS_FindPrikeyByCert,
15399ebb4caSwyllys 	NSS_DecryptData,
15430a5e8faSwyllys 	NSS_ExportPK12,
15599ebb4caSwyllys 	NSS_CreateSymKey,
15699ebb4caSwyllys 	NSS_GetSymKeyValue,
15799ebb4caSwyllys 	NSS_SetTokenPin,
15830a5e8faSwyllys 	NSS_StoreKey,
15999ebb4caSwyllys 	NULL /* Finalize */
16099ebb4caSwyllys };
16199ebb4caSwyllys 
16299ebb4caSwyllys /* additions for importing and exporting PKCS 12 files */
16399ebb4caSwyllys typedef struct p12uContextStr {
16499ebb4caSwyllys 	char		*filename;	/* name of file */
16599ebb4caSwyllys 	PRFileDesc	*file;		/* pointer to file */
16699ebb4caSwyllys 	PRBool		error;		/* error occurred? */
16799ebb4caSwyllys 	int		errorValue;	/* which error occurred? */
16899ebb4caSwyllys } p12uContext;
16999ebb4caSwyllys 
17099ebb4caSwyllys #define	SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_NSS; \
17199ebb4caSwyllys 	h->lasterr.errcode = c;
17299ebb4caSwyllys 
17399ebb4caSwyllys KMF_PLUGIN_FUNCLIST *
KMF_Plugin_Initialize()17499ebb4caSwyllys KMF_Plugin_Initialize()
17599ebb4caSwyllys {
1765ad42b1bSSurya Prakki 	(void) SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
1775ad42b1bSSurya Prakki 	(void) SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
1785ad42b1bSSurya Prakki 	(void) SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
1795ad42b1bSSurya Prakki 	(void) SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
1805ad42b1bSSurya Prakki 	(void) SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
1815ad42b1bSSurya Prakki 	(void) SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
1825ad42b1bSSurya Prakki 	(void) SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
18399ebb4caSwyllys 
18499ebb4caSwyllys 	return (&nss_plugin_table);
18599ebb4caSwyllys }
18699ebb4caSwyllys 
18799ebb4caSwyllys static char *
18899ebb4caSwyllys /*ARGSUSED*/
nss_getpassword(PK11SlotInfo * slot,PRBool retry,void * arg)18999ebb4caSwyllys nss_getpassword(PK11SlotInfo *slot, PRBool retry, void *arg)
19099ebb4caSwyllys {
19199ebb4caSwyllys 	if (retry)
19299ebb4caSwyllys 		return (NULL);
19399ebb4caSwyllys 	if (arg != NULL)
19499ebb4caSwyllys 		return ((char *)strdup(arg));
19599ebb4caSwyllys 	else
19699ebb4caSwyllys 		return (NULL);
19799ebb4caSwyllys }
19899ebb4caSwyllys 
19999ebb4caSwyllys static KMF_RETURN
nss_authenticate(KMF_HANDLE_T handle,PK11SlotInfo * nss_slot,KMF_CREDENTIAL * cred)20099ebb4caSwyllys nss_authenticate(KMF_HANDLE_T handle,
20199ebb4caSwyllys 	PK11SlotInfo *nss_slot, KMF_CREDENTIAL *cred)
20299ebb4caSwyllys {
20399ebb4caSwyllys 
20499ebb4caSwyllys 	SECStatus nssrv = SECSuccess;
20599ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
20699ebb4caSwyllys 
20799ebb4caSwyllys 	/* If a password was given, try to login to the slot */
20899ebb4caSwyllys 	if (cred == NULL || cred->cred == NULL || cred->credlen == 0 ||
20930a5e8faSwyllys 	    nss_slot == NULL) {
21099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
21199ebb4caSwyllys 	}
21299ebb4caSwyllys 
21399ebb4caSwyllys 	if (PK11_IsLoggedIn(nss_slot, NULL)) {
21499ebb4caSwyllys 		return (KMF_OK);
21599ebb4caSwyllys 	}
21699ebb4caSwyllys 
21799ebb4caSwyllys 	PK11_SetPasswordFunc(nss_getpassword);
21830a5e8faSwyllys 	nssrv = PK11_Authenticate(nss_slot, PR_TRUE, (void *)cred->cred);
21999ebb4caSwyllys 
22099ebb4caSwyllys 	if (nssrv != SECSuccess) {
22199ebb4caSwyllys 		SET_ERROR(kmfh, nssrv);
22299ebb4caSwyllys 		PK11_FreeSlot(nss_slot);
22399ebb4caSwyllys 		return (KMF_ERR_AUTH_FAILED);
22499ebb4caSwyllys 	}
22599ebb4caSwyllys 
22699ebb4caSwyllys 	return (KMF_OK);
22799ebb4caSwyllys }
22899ebb4caSwyllys 
22999ebb4caSwyllys static SECStatus
Init_NSS_DBs(const char * configdir,const char * certPrefix,const char * keyPrefix,const char * secmodName)23099ebb4caSwyllys Init_NSS_DBs(const char *configdir,
23199ebb4caSwyllys 	const char *certPrefix,
23299ebb4caSwyllys 	const char *keyPrefix,
23399ebb4caSwyllys 	const char *secmodName)
23499ebb4caSwyllys {
23599ebb4caSwyllys 	SECStatus rv = NSS_OK;
23699ebb4caSwyllys 
23799ebb4caSwyllys 	(void) mutex_lock(&init_lock);
23899ebb4caSwyllys 
23999ebb4caSwyllys 	/* If another thread already did it, return OK. */
24099ebb4caSwyllys 	if (nss_initialized) {
24199ebb4caSwyllys 		(void) mutex_unlock(&init_lock);
24299ebb4caSwyllys 		return (SECSuccess);
24399ebb4caSwyllys 	}
24499ebb4caSwyllys 
24599ebb4caSwyllys 	rv = NSS_Initialize((configdir && strlen(configdir)) ?
24630a5e8faSwyllys 	    configdir : "./", certPrefix, keyPrefix,
24730a5e8faSwyllys 	    secmodName ? secmodName : "secmod.db", NSS_INIT_COOPERATE);
24899ebb4caSwyllys 	if (rv != SECSuccess) {
24999ebb4caSwyllys 		goto end;
25099ebb4caSwyllys 	}
25199ebb4caSwyllys 
25299ebb4caSwyllys 	nss_initialized++;
25399ebb4caSwyllys end:
25499ebb4caSwyllys 	(void) mutex_unlock(&init_lock);
25599ebb4caSwyllys 	return (rv);
25699ebb4caSwyllys }
25799ebb4caSwyllys 
25899ebb4caSwyllys /*
25999ebb4caSwyllys  * When it is called the first time, it will intialize NSS.  Once the NSS
26099ebb4caSwyllys  * is initialized, this function returns KMF_KEYSTORE_ALREADY_INITIALIZED
26199ebb4caSwyllys  * if it is called again.
26299ebb4caSwyllys  */
26399ebb4caSwyllys KMF_RETURN
NSS_ConfigureKeystore(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)26430a5e8faSwyllys NSS_ConfigureKeystore(KMF_HANDLE_T handle,
26530a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
26699ebb4caSwyllys {
26799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
26899ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
26930a5e8faSwyllys 	char    *configdir;
27030a5e8faSwyllys 	char    *certPrefix;
27130a5e8faSwyllys 	char    *keyPrefix;
27230a5e8faSwyllys 	char    *secModName;
27399ebb4caSwyllys 
27430a5e8faSwyllys 	configdir = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
27530a5e8faSwyllys 	certPrefix = kmf_get_attr_ptr(KMF_CERTPREFIX_ATTR, attrlist, numattr);
27630a5e8faSwyllys 	keyPrefix = kmf_get_attr_ptr(KMF_KEYPREFIX_ATTR, attrlist, numattr);
27730a5e8faSwyllys 	secModName = kmf_get_attr_ptr(KMF_SECMODNAME_ATTR, attrlist, numattr);
27899ebb4caSwyllys 
27999ebb4caSwyllys 	(void) mutex_lock(&init_lock);
28099ebb4caSwyllys 	if (nss_initialized == 0) {
28199ebb4caSwyllys 		SECStatus err;
28299ebb4caSwyllys 
28399ebb4caSwyllys 		(void) mutex_unlock(&init_lock);
28430a5e8faSwyllys 		err = Init_NSS_DBs(configdir, certPrefix,
28530a5e8faSwyllys 		    keyPrefix, secModName);
28699ebb4caSwyllys 		if (err != SECSuccess) {
28799ebb4caSwyllys 			SET_ERROR(kmfh, err);
28899ebb4caSwyllys 			return (KMF_ERR_INTERNAL);
28999ebb4caSwyllys 		}
29099ebb4caSwyllys 	} else {
29199ebb4caSwyllys 		rv = KMF_KEYSTORE_ALREADY_INITIALIZED;
29299ebb4caSwyllys 		(void) mutex_unlock(&init_lock);
29399ebb4caSwyllys 	}
29499ebb4caSwyllys 
29599ebb4caSwyllys 	return (rv);
29699ebb4caSwyllys }
29799ebb4caSwyllys 
29899ebb4caSwyllys /*
29999ebb4caSwyllys  * This function sets up the slot to be used for other operations.
30099ebb4caSwyllys  * This function is basically called by every NSS SPI function.
30199ebb4caSwyllys  * For those functions that can only be performed in the internal slot, the
30299ebb4caSwyllys  * boolean "internal_slot_only" argument needs to be TRUE.
30399ebb4caSwyllys  * A slot pointer will be returned when this function is executed successfully.
30499ebb4caSwyllys  */
30530a5e8faSwyllys KMF_RETURN
do_nss_init(void * handle,int numattr,KMF_ATTRIBUTE * attrlist,boolean_t internal_slot_only,PK11SlotInfo ** nss_slot)30630a5e8faSwyllys do_nss_init(void *handle, int numattr,
30730a5e8faSwyllys 	KMF_ATTRIBUTE *attrlist,
30899ebb4caSwyllys 	boolean_t internal_slot_only,
30999ebb4caSwyllys 	PK11SlotInfo **nss_slot)
31099ebb4caSwyllys {
31130a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
31299ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
31330a5e8faSwyllys 	char *slotlabel = NULL;
31499ebb4caSwyllys 
31599ebb4caSwyllys 	if (!nss_initialized)
31699ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
31799ebb4caSwyllys 
31830a5e8faSwyllys 	slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
31999ebb4caSwyllys 	/*
32099ebb4caSwyllys 	 * NSS Is already initialized, but we need to find
32199ebb4caSwyllys 	 * the right slot.
32299ebb4caSwyllys 	 */
32330a5e8faSwyllys 	if (slotlabel == NULL ||
32430a5e8faSwyllys 	    strcmp(slotlabel, "internal") == 0) {
32599ebb4caSwyllys 		*nss_slot = PK11_GetInternalKeySlot();
32699ebb4caSwyllys 	} else if (internal_slot_only == TRUE)  {
32730a5e8faSwyllys 		rv = KMF_ERR_SLOTNAME;
32830a5e8faSwyllys 		goto end;
32999ebb4caSwyllys 	} else {
33030a5e8faSwyllys 		*nss_slot = PK11_FindSlotByName(slotlabel);
33199ebb4caSwyllys 	}
33299ebb4caSwyllys 
33399ebb4caSwyllys 	if (*nss_slot == NULL) {
33499ebb4caSwyllys 		SET_ERROR(kmfh, PORT_GetError());
33530a5e8faSwyllys 		rv = KMF_ERR_SLOTNAME;
33630a5e8faSwyllys 		goto end;
33799ebb4caSwyllys 	}
33899ebb4caSwyllys 
33999ebb4caSwyllys 	/*
34099ebb4caSwyllys 	 * If the token was not yet initialized, return an error.
34199ebb4caSwyllys 	 */
34299ebb4caSwyllys 	if (PK11_NeedUserInit(*nss_slot)) {
34330a5e8faSwyllys 		rv = KMF_ERR_UNINITIALIZED_TOKEN;
34499ebb4caSwyllys 	}
34599ebb4caSwyllys 
34630a5e8faSwyllys end:
34730a5e8faSwyllys 	return (rv);
34899ebb4caSwyllys }
34999ebb4caSwyllys 
35099ebb4caSwyllys static KMF_RETURN
nss2kmf_cert(CERTCertificate * nss_cert,KMF_X509_DER_CERT * kmf_cert)35199ebb4caSwyllys nss2kmf_cert(CERTCertificate *nss_cert, KMF_X509_DER_CERT *kmf_cert)
35299ebb4caSwyllys {
35399ebb4caSwyllys 	kmf_cert->kmf_private.keystore_type = KMF_KEYSTORE_NSS;
35499ebb4caSwyllys 	kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID;
35599ebb4caSwyllys 
35699ebb4caSwyllys 	kmf_cert->certificate.Length = nss_cert->derCert.len;
35799ebb4caSwyllys 
35899ebb4caSwyllys 	if ((kmf_cert->certificate.Data = malloc(nss_cert->derCert.len)) ==
35930a5e8faSwyllys 	    NULL) {
36099ebb4caSwyllys 		kmf_cert->certificate.Length = 0;
36199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
36299ebb4caSwyllys 	}
36399ebb4caSwyllys 	(void) memcpy(kmf_cert->certificate.Data, nss_cert->derCert.data,
36430a5e8faSwyllys 	    nss_cert->derCert.len);
36599ebb4caSwyllys 	if (nss_cert->nickname != NULL)
36699ebb4caSwyllys 		kmf_cert->kmf_private.label =
36730a5e8faSwyllys 		    (char *)strdup(nss_cert->nickname);
36899ebb4caSwyllys 	return (KMF_OK);
36999ebb4caSwyllys }
37099ebb4caSwyllys 
37199ebb4caSwyllys 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)37299ebb4caSwyllys nss_getcert_by_label(KMF_HANDLE *kmfh,
37399ebb4caSwyllys 	char *name, KMF_X509_DER_CERT *kmf_cert,
37499ebb4caSwyllys 	uint32_t *num_certs, KMF_CERT_VALIDITY find_criteria)
37599ebb4caSwyllys {
37699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
37799ebb4caSwyllys 	CERTCertificate *nss_cert;
37899ebb4caSwyllys 	SECCertTimeValidity validity;
37999ebb4caSwyllys 
38099ebb4caSwyllys 	nss_cert = PK11_FindCertFromNickname(name, NULL);
38199ebb4caSwyllys 	if (nss_cert == NULL) {
38299ebb4caSwyllys 		*num_certs = 0;
38399ebb4caSwyllys 		SET_ERROR(kmfh, PORT_GetError());
38499ebb4caSwyllys 		*num_certs = 0;
38599ebb4caSwyllys 		return (KMF_ERR_CERT_NOT_FOUND);
38699ebb4caSwyllys 	} else {
38799ebb4caSwyllys 		*num_certs = 1;
38899ebb4caSwyllys 	}
38999ebb4caSwyllys 
39099ebb4caSwyllys 	switch (find_criteria) {
39199ebb4caSwyllys 	case KMF_ALL_CERTS:
39299ebb4caSwyllys 		break;
39399ebb4caSwyllys 	case KMF_NONEXPIRED_CERTS:
39499ebb4caSwyllys 		validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
39530a5e8faSwyllys 		    PR_FALSE);
39699ebb4caSwyllys 		if (validity != secCertTimeValid) {
39799ebb4caSwyllys 			/* this is an invalid cert, reject it */
39899ebb4caSwyllys 			*num_certs = 0;
39999ebb4caSwyllys 			CERT_DestroyCertificate(nss_cert);
40099ebb4caSwyllys 			return (KMF_OK);
40199ebb4caSwyllys 		}
40299ebb4caSwyllys 		break;
40399ebb4caSwyllys 	case KMF_EXPIRED_CERTS:
40499ebb4caSwyllys 		validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
40530a5e8faSwyllys 		    PR_FALSE);
40699ebb4caSwyllys 		if (validity == secCertTimeValid) {
40799ebb4caSwyllys 			/* this is a valid cert, reject it in this case. */
40899ebb4caSwyllys 			*num_certs = 0;
40999ebb4caSwyllys 			CERT_DestroyCertificate(nss_cert);
41099ebb4caSwyllys 			return (KMF_OK);
41199ebb4caSwyllys 		}
41299ebb4caSwyllys 		break;
41399ebb4caSwyllys 	default:
41499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
41599ebb4caSwyllys 	}
41699ebb4caSwyllys 
41799ebb4caSwyllys 	if (kmf_cert != NULL)
41899ebb4caSwyllys 		rv = nss2kmf_cert(nss_cert, kmf_cert);
41999ebb4caSwyllys 
42099ebb4caSwyllys 	/* We copied the data we need, so cleanup the internal record */
42199ebb4caSwyllys 	CERT_DestroyCertificate(nss_cert);
42299ebb4caSwyllys 
42399ebb4caSwyllys 	if (rv != KMF_OK)
42499ebb4caSwyllys 		*num_certs = 0;
42599ebb4caSwyllys 
42699ebb4caSwyllys 	return (rv);
42799ebb4caSwyllys }
42899ebb4caSwyllys 
42999ebb4caSwyllys static KMF_RETURN
nss_find_matching_certs(PK11SlotInfo * slot,char * issuer,char * subject,KMF_BIGINT * serial,CERTCertList ** certlist,KMF_CERT_VALIDITY find_criteria)43099ebb4caSwyllys nss_find_matching_certs(PK11SlotInfo *slot,
43199ebb4caSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
43299ebb4caSwyllys 	CERTCertList **certlist, KMF_CERT_VALIDITY find_criteria)
43399ebb4caSwyllys {
43499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
43599ebb4caSwyllys 	SECStatus ret;
43699ebb4caSwyllys 	CERTCertList *list;
43799ebb4caSwyllys 	CERTCertListNode *node;
43899ebb4caSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
43999ebb4caSwyllys 	boolean_t findIssuer = FALSE;
44099ebb4caSwyllys 	boolean_t findSubject = FALSE;
44199ebb4caSwyllys 	boolean_t findSerial = FALSE;
44299ebb4caSwyllys 
44399ebb4caSwyllys 	if (issuer != NULL && strlen(issuer)) {
44430a5e8faSwyllys 		rv = kmf_dn_parser(issuer,  &issuerDN);
44599ebb4caSwyllys 		if (rv != KMF_OK)
44699ebb4caSwyllys 			return (rv);
44799ebb4caSwyllys 		findIssuer = TRUE;
44899ebb4caSwyllys 	}
44999ebb4caSwyllys 	if (subject != NULL && strlen(subject)) {
45030a5e8faSwyllys 		rv = kmf_dn_parser(subject, &subjectDN);
45199ebb4caSwyllys 		if (rv != KMF_OK)
45299ebb4caSwyllys 			return (rv);
45399ebb4caSwyllys 		findSubject = TRUE;
45499ebb4caSwyllys 	}
45599ebb4caSwyllys 	if (serial != 0 && serial->val != NULL && serial->len > 0)
45699ebb4caSwyllys 		findSerial = TRUE;
45799ebb4caSwyllys 
45899ebb4caSwyllys 	list = PK11_ListCertsInSlot(slot);
45999ebb4caSwyllys 	if (list) {
46099ebb4caSwyllys 		node = CERT_LIST_HEAD(list);
46199ebb4caSwyllys 		while (!CERT_LIST_END(node, list)) {
46299ebb4caSwyllys 			KMF_X509_NAME cmpDN;
46399ebb4caSwyllys 			KMF_DATA der;
46499ebb4caSwyllys 			boolean_t match;
46599ebb4caSwyllys 			CERTCertListNode *freenode;
46699ebb4caSwyllys 
46799ebb4caSwyllys 			if (findIssuer) {
46899ebb4caSwyllys 				der.Data = node->cert->derIssuer.data;
46999ebb4caSwyllys 				der.Length = node->cert->derIssuer.len;
47099ebb4caSwyllys 				rv = DerDecodeName(&der, &cmpDN);
47199ebb4caSwyllys 				if (rv == KMF_OK) {
47299ebb4caSwyllys 					match = !KMF_CompareRDNs(&issuerDN,
47330a5e8faSwyllys 					    &cmpDN);
47430a5e8faSwyllys 					kmf_free_dn(&cmpDN);
47599ebb4caSwyllys 					if (!match)
47699ebb4caSwyllys 						goto delete_and_cont;
47799ebb4caSwyllys 				} else {
47899ebb4caSwyllys 					goto delete_and_cont;
47999ebb4caSwyllys 				}
48099ebb4caSwyllys 			}
48199ebb4caSwyllys 			if (findSubject) {
48299ebb4caSwyllys 				der.Data = node->cert->derSubject.data;
48399ebb4caSwyllys 				der.Length = node->cert->derSubject.len;
48499ebb4caSwyllys 				rv = DerDecodeName(&der, &cmpDN);
48599ebb4caSwyllys 				if (rv == KMF_OK) {
48699ebb4caSwyllys 					match = !KMF_CompareRDNs(&subjectDN,
48730a5e8faSwyllys 					    &cmpDN);
48830a5e8faSwyllys 					kmf_free_dn(&cmpDN);
48999ebb4caSwyllys 					if (!match)
49099ebb4caSwyllys 						goto delete_and_cont;
49199ebb4caSwyllys 				} else {
49299ebb4caSwyllys 					goto delete_and_cont;
49399ebb4caSwyllys 				}
49499ebb4caSwyllys 			}
49599ebb4caSwyllys 			if (findSerial) {
49699ebb4caSwyllys 				SECItem *sernum;
49799ebb4caSwyllys 
49899ebb4caSwyllys 				sernum = &node->cert->serialNumber;
49999ebb4caSwyllys 
50099ebb4caSwyllys 				if (serial->len != sernum->len)
50199ebb4caSwyllys 					goto delete_and_cont;
50299ebb4caSwyllys 
50399ebb4caSwyllys 				if (memcmp(sernum->data, serial->val,
50430a5e8faSwyllys 				    serial->len))
50599ebb4caSwyllys 					goto delete_and_cont;
50699ebb4caSwyllys 			}
50799ebb4caSwyllys 
50899ebb4caSwyllys 			/* select the certs using find criteria */
50999ebb4caSwyllys 			switch (find_criteria) {
51099ebb4caSwyllys 			case KMF_ALL_CERTS:
51199ebb4caSwyllys 				break;
51299ebb4caSwyllys 			case KMF_NONEXPIRED_CERTS:
51399ebb4caSwyllys 				ret = CERT_CertTimesValid(node->cert);
51499ebb4caSwyllys 				if (ret == SECFailure) {
51599ebb4caSwyllys 					/* this is an invalid cert */
51699ebb4caSwyllys 					goto skip;
51799ebb4caSwyllys 				}
51899ebb4caSwyllys 				break;
51999ebb4caSwyllys 
52099ebb4caSwyllys 			case KMF_EXPIRED_CERTS:
52199ebb4caSwyllys 				ret = CERT_CertTimesValid(node->cert);
52299ebb4caSwyllys 				if (ret != SECFailure) {
52399ebb4caSwyllys 					/* this is a valid cert */
52499ebb4caSwyllys 					goto skip;
52599ebb4caSwyllys 				}
52699ebb4caSwyllys 				break;
52799ebb4caSwyllys 			}
52899ebb4caSwyllys skip:
52999ebb4caSwyllys 			node = CERT_LIST_NEXT(node);
53099ebb4caSwyllys 			continue;
53199ebb4caSwyllys delete_and_cont:
53299ebb4caSwyllys 			freenode = node;
53399ebb4caSwyllys 			node = CERT_LIST_NEXT(node);
53499ebb4caSwyllys 			CERT_RemoveCertListNode(freenode);
53599ebb4caSwyllys 		}
53699ebb4caSwyllys 	}
53799ebb4caSwyllys 
53899ebb4caSwyllys 	if (rv == KMF_OK && certlist != NULL) {
53999ebb4caSwyllys 		*certlist = list;
54099ebb4caSwyllys 	} else {
54199ebb4caSwyllys 		CERT_DestroyCertList(list);
54299ebb4caSwyllys 	}
54399ebb4caSwyllys 	return (rv);
54499ebb4caSwyllys }
54599ebb4caSwyllys 
54699ebb4caSwyllys static KMF_RETURN
convertCertList(void * kmfhandle,CERTCertList * nsscerts,KMF_X509_DER_CERT * kmfcerts,uint32_t * numcerts)54799ebb4caSwyllys convertCertList(void *kmfhandle,
54899ebb4caSwyllys 	CERTCertList *nsscerts, KMF_X509_DER_CERT *kmfcerts,
54999ebb4caSwyllys 	uint32_t *numcerts)
55099ebb4caSwyllys {
55199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
55299ebb4caSwyllys 	CERTCertListNode *node;
553f482c776Swyllys 	uint32_t maxcerts = *numcerts;
55499ebb4caSwyllys 
55530a5e8faSwyllys 	maxcerts = *numcerts;
55630a5e8faSwyllys 	if (maxcerts == 0)
55730a5e8faSwyllys 		maxcerts = 0xFFFFFFFF;
55830a5e8faSwyllys 
55999ebb4caSwyllys 	*numcerts = 0;
56099ebb4caSwyllys 
56130a5e8faSwyllys 	/*
56230a5e8faSwyllys 	 * Don't copy more certs than the caller wanted.
56330a5e8faSwyllys 	 */
56499ebb4caSwyllys 	for (node = CERT_LIST_HEAD(nsscerts);
56530a5e8faSwyllys 	    !CERT_LIST_END(node, nsscerts) && rv == KMF_OK &&
56630a5e8faSwyllys 	    (*numcerts) < maxcerts;
56730a5e8faSwyllys 	    node = CERT_LIST_NEXT(node), (*numcerts)++) {
56899ebb4caSwyllys 		if (kmfcerts != NULL)
56999ebb4caSwyllys 			rv = nss2kmf_cert(node->cert, &kmfcerts[*numcerts]);
57099ebb4caSwyllys 	}
57199ebb4caSwyllys 
57299ebb4caSwyllys 	/*
57399ebb4caSwyllys 	 * If we failed, delete any certs allocated so far.
57499ebb4caSwyllys 	 */
57599ebb4caSwyllys 	if (rv != KMF_OK) {
57699ebb4caSwyllys 		int i;
57799ebb4caSwyllys 		for (i = 0; i < *numcerts; i++)
57830a5e8faSwyllys 			kmf_free_kmf_cert(kmfhandle, &kmfcerts[i]);
57930a5e8faSwyllys 
580f482c776Swyllys 		*numcerts = 0;
58199ebb4caSwyllys 	}
58299ebb4caSwyllys 	return (rv);
58399ebb4caSwyllys }
58499ebb4caSwyllys 
58599ebb4caSwyllys KMF_RETURN
NSS_FindCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)58630a5e8faSwyllys NSS_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
58799ebb4caSwyllys {
58899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
58999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
59099ebb4caSwyllys 	PK11SlotInfo *nss_slot = NULL;
59199ebb4caSwyllys 	CERTCertList *certlist = NULL;
592f482c776Swyllys 	uint32_t maxcerts;
59330a5e8faSwyllys 	uint32_t *num_certs;
59430a5e8faSwyllys 	KMF_X509_DER_CERT *kmfcerts = NULL;
59530a5e8faSwyllys 	char *certlabel = NULL;
59630a5e8faSwyllys 	char *issuer = NULL;
59730a5e8faSwyllys 	char *subject = NULL;
59830a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
59930a5e8faSwyllys 	KMF_CERT_VALIDITY  validity;
60030a5e8faSwyllys 
60130a5e8faSwyllys 	if (handle == NULL || attrlist == NULL || numattr == 0) {
60230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
60399ebb4caSwyllys 	}
60430a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
60530a5e8faSwyllys 	if (rv != KMF_OK)
60630a5e8faSwyllys 		return (rv);
60799ebb4caSwyllys 
60830a5e8faSwyllys 	num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
60930a5e8faSwyllys 	if (num_certs == NULL)
61030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
611f482c776Swyllys 
61230a5e8faSwyllys 	maxcerts = *num_certs;
61330a5e8faSwyllys 	if (maxcerts == 0)
61430a5e8faSwyllys 		maxcerts = 0xFFFFFFFF;
61599ebb4caSwyllys 	*num_certs = 0;
61630a5e8faSwyllys 
61730a5e8faSwyllys 	/* Get the optional returned certificate list  */
61830a5e8faSwyllys 	kmfcerts = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, numattr);
61930a5e8faSwyllys 
62030a5e8faSwyllys 	/* Get optional search criteria attributes */
62130a5e8faSwyllys 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
62230a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
62330a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
62430a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
62530a5e8faSwyllys 
62630a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
62730a5e8faSwyllys 	    &validity, NULL);
62830a5e8faSwyllys 	if (rv != KMF_OK) {
62930a5e8faSwyllys 		validity = KMF_ALL_CERTS;
63030a5e8faSwyllys 		rv = KMF_OK;
63130a5e8faSwyllys 	}
63230a5e8faSwyllys 
63330a5e8faSwyllys 	if (certlabel != NULL) {
634f482c776Swyllys 		/* This will only find 1 certificate */
63530a5e8faSwyllys 		rv = nss_getcert_by_label(kmfh,	certlabel, kmfcerts, num_certs,
63630a5e8faSwyllys 		    validity);
63799ebb4caSwyllys 	} else {
638f482c776Swyllys 		/*
639f482c776Swyllys 		 * Build a list of matching certs.
640f482c776Swyllys 		 */
64130a5e8faSwyllys 		rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
64230a5e8faSwyllys 		    &certlist, validity);
64399ebb4caSwyllys 
644f482c776Swyllys 		/*
645f482c776Swyllys 		 * If the caller supplied a pointer to storage for
646f482c776Swyllys 		 * a list of certs, convert up to 'maxcerts' of the
647f482c776Swyllys 		 * matching certs.
648f482c776Swyllys 		 */
64999ebb4caSwyllys 		if (rv == KMF_OK && certlist != NULL) {
65030a5e8faSwyllys 			rv = convertCertList(handle, certlist, kmfcerts,
65130a5e8faSwyllys 			    &maxcerts);
65299ebb4caSwyllys 			CERT_DestroyCertList(certlist);
653f482c776Swyllys 			if (rv == KMF_OK)
654f482c776Swyllys 				*num_certs = maxcerts;
65599ebb4caSwyllys 		}
65699ebb4caSwyllys 	}
65799ebb4caSwyllys 
65899ebb4caSwyllys 	if (nss_slot != NULL) {
65999ebb4caSwyllys 		PK11_FreeSlot(nss_slot);
66099ebb4caSwyllys 	}
66199ebb4caSwyllys 
66299ebb4caSwyllys 	if (rv == KMF_OK && *num_certs == 0)
66399ebb4caSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
66499ebb4caSwyllys 
66599ebb4caSwyllys 	return (rv);
66699ebb4caSwyllys }
66799ebb4caSwyllys 
66899ebb4caSwyllys void
66999ebb4caSwyllys /*ARGSUSED*/
NSS_FreeKMFCert(KMF_HANDLE_T handle,KMF_X509_DER_CERT * kmf_cert)67099ebb4caSwyllys NSS_FreeKMFCert(KMF_HANDLE_T handle,
67199ebb4caSwyllys 	KMF_X509_DER_CERT *kmf_cert)
67299ebb4caSwyllys {
67399ebb4caSwyllys 	if (kmf_cert != NULL) {
67499ebb4caSwyllys 		if (kmf_cert->certificate.Data != NULL) {
67599ebb4caSwyllys 			free(kmf_cert->certificate.Data);
67699ebb4caSwyllys 			kmf_cert->certificate.Data = NULL;
67799ebb4caSwyllys 			kmf_cert->certificate.Length = 0;
67899ebb4caSwyllys 		}
67999ebb4caSwyllys 		if (kmf_cert->kmf_private.label != NULL) {
68099ebb4caSwyllys 			free(kmf_cert->kmf_private.label);
68199ebb4caSwyllys 			kmf_cert->kmf_private.label = NULL;
68299ebb4caSwyllys 		}
68399ebb4caSwyllys 	}
68499ebb4caSwyllys }
68599ebb4caSwyllys 
68699ebb4caSwyllys KMF_RETURN
NSS_DeleteCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)68730a5e8faSwyllys NSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
68899ebb4caSwyllys {
68999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
69099ebb4caSwyllys 	int nssrv;
69199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
69299ebb4caSwyllys 	CERTCertificate *cert = NULL;
69399ebb4caSwyllys 	PK11SlotInfo *nss_slot = NULL;
69430a5e8faSwyllys 	char *certlabel = NULL;
69530a5e8faSwyllys 	char *issuer = NULL;
69630a5e8faSwyllys 	char *subject = NULL;
69730a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
69830a5e8faSwyllys 	KMF_CERT_VALIDITY  validity;
69999ebb4caSwyllys 
70030a5e8faSwyllys 	if (handle == NULL || attrlist == NULL || numattr == 0) {
70199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
70299ebb4caSwyllys 	}
70330a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
70430a5e8faSwyllys 	if (rv != KMF_OK)
70530a5e8faSwyllys 		return (rv);
70630a5e8faSwyllys 
70730a5e8faSwyllys 	/* Get the search criteria attributes.  They are all optional. */
70830a5e8faSwyllys 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
70930a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
71030a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
71130a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
71299ebb4caSwyllys 
71330a5e8faSwyllys 	rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
71430a5e8faSwyllys 	    &validity, NULL);
71599ebb4caSwyllys 	if (rv != KMF_OK) {
71630a5e8faSwyllys 		validity = KMF_ALL_CERTS;
71730a5e8faSwyllys 		rv = KMF_OK;
71899ebb4caSwyllys 	}
71999ebb4caSwyllys 
72030a5e8faSwyllys 	/* Start finding the matched certificates and delete them. */
72130a5e8faSwyllys 	if (certlabel != NULL) {
72230a5e8faSwyllys 		cert = PK11_FindCertFromNickname(certlabel, NULL);
72399ebb4caSwyllys 		if (cert == NULL) {
72499ebb4caSwyllys 			return (KMF_ERR_CERT_NOT_FOUND);
72599ebb4caSwyllys 		}
72699ebb4caSwyllys 
72730a5e8faSwyllys 		switch (validity) {
72899ebb4caSwyllys 		case KMF_ALL_CERTS:
72999ebb4caSwyllys 			break;
73099ebb4caSwyllys 		case KMF_NONEXPIRED_CERTS:
73199ebb4caSwyllys 			nssrv = CERT_CertTimesValid(cert);
73299ebb4caSwyllys 			if (nssrv == SECFailure) {
73399ebb4caSwyllys 				/* this is an invalid cert - skip it */
73499ebb4caSwyllys 				goto out;
73599ebb4caSwyllys 			}
73699ebb4caSwyllys 			break;
73799ebb4caSwyllys 		case KMF_EXPIRED_CERTS:
73899ebb4caSwyllys 			nssrv = CERT_CertTimesValid(cert);
73999ebb4caSwyllys 			if (nssrv != SECFailure) {
74099ebb4caSwyllys 				/* this is a valid cert - skip it */
74199ebb4caSwyllys 				goto out;
74299ebb4caSwyllys 			}
74399ebb4caSwyllys 			break;
74499ebb4caSwyllys 		}
74599ebb4caSwyllys 		/* delete it from database */
74699ebb4caSwyllys 		nssrv = SEC_DeletePermCertificate(cert);
74799ebb4caSwyllys 		if (nssrv) {
74899ebb4caSwyllys 			SET_ERROR(kmfh, nssrv);
74999ebb4caSwyllys 			rv = KMF_ERR_INTERNAL;
75099ebb4caSwyllys 		}
75199ebb4caSwyllys 	} else {
75299ebb4caSwyllys 		CERTCertListNode *node;
75399ebb4caSwyllys 		CERTCertList *certlist = NULL;
75499ebb4caSwyllys 
75530a5e8faSwyllys 		rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
75630a5e8faSwyllys 		    &certlist, validity);
75799ebb4caSwyllys 
75899ebb4caSwyllys 		for (node = CERT_LIST_HEAD(certlist);
75930a5e8faSwyllys 		    !CERT_LIST_END(node, certlist) && rv == KMF_OK;
76030a5e8faSwyllys 		    node = CERT_LIST_NEXT(node)) {
76199ebb4caSwyllys 
76299ebb4caSwyllys 			nssrv = SEC_DeletePermCertificate(node->cert);
76399ebb4caSwyllys 			if (nssrv) {
76499ebb4caSwyllys 				SET_ERROR(kmfh, nssrv);
76599ebb4caSwyllys 				rv = KMF_ERR_INTERNAL;
76699ebb4caSwyllys 			}
76799ebb4caSwyllys 		}
76899ebb4caSwyllys 
76999ebb4caSwyllys 		if (rv == KMF_OK && certlist != NULL) {
77099ebb4caSwyllys 			CERT_DestroyCertList(certlist);
77199ebb4caSwyllys 		} else if (rv == KMF_OK && certlist == NULL) {
77299ebb4caSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
77399ebb4caSwyllys 		}
77499ebb4caSwyllys 	}
77599ebb4caSwyllys out:
77699ebb4caSwyllys 	if (nss_slot != NULL) {
77799ebb4caSwyllys 		PK11_FreeSlot(nss_slot);
77899ebb4caSwyllys 	}
77999ebb4caSwyllys 
78099ebb4caSwyllys 	if (cert != NULL) {
78199ebb4caSwyllys 		CERT_DestroyCertificate(cert);
78299ebb4caSwyllys 	}
78399ebb4caSwyllys 
78499ebb4caSwyllys 	return (rv);
78599ebb4caSwyllys }
78699ebb4caSwyllys 
78799ebb4caSwyllys static void
InitRandom(char * filename)78899ebb4caSwyllys InitRandom(char *filename)
78999ebb4caSwyllys {
79099ebb4caSwyllys 	char buf[2048];
79199ebb4caSwyllys 	int fd;
79299ebb4caSwyllys 	PRInt32 count;
79399ebb4caSwyllys 
79499ebb4caSwyllys 	fd = open(filename, O_RDONLY);
79599ebb4caSwyllys 	if (!fd)
79699ebb4caSwyllys 		return;
79799ebb4caSwyllys 
79899ebb4caSwyllys 	count = read(fd, buf, sizeof (buf));
79999ebb4caSwyllys 	if (count > 0) {
8005ad42b1bSSurya Prakki 		(void) PK11_RandomUpdate(buf, count);
80199ebb4caSwyllys 	}
80299ebb4caSwyllys 
80399ebb4caSwyllys 	(void) close(fd);
80499ebb4caSwyllys }
80599ebb4caSwyllys 
80699ebb4caSwyllys KMF_RETURN
NSS_CreateKeypair(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)80799ebb4caSwyllys NSS_CreateKeypair(KMF_HANDLE_T handle,
80830a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
80999ebb4caSwyllys {
81099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
81199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
81230a5e8faSwyllys 	PK11RSAGenParams rsaparams;
81330a5e8faSwyllys 	void *nssparams;
81499ebb4caSwyllys 	CK_MECHANISM_TYPE mechanism;
81599ebb4caSwyllys 	ulong_t publicExponent = 0x010001;
81699ebb4caSwyllys 	PK11SlotInfo *nss_slot = NULL;
81799ebb4caSwyllys 	SECKEYPrivateKey *NSSprivkey = NULL;
81899ebb4caSwyllys 	SECKEYPublicKey *NSSpubkey = NULL;
819e65e5c2dSWyllys Ingersoll 	SECKEYECParams *ecparams = NULL;
82099ebb4caSwyllys 	PQGParams *pqgParams = NULL;
82130a5e8faSwyllys 	KMF_CREDENTIAL cred;
82230a5e8faSwyllys 	boolean_t storekey = TRUE;
82330a5e8faSwyllys 	uint32_t keylen = 1024, len;
82430a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
82530a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_RSA;
82630a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL;
82730a5e8faSwyllys 	KMF_KEY_HANDLE *privkey = NULL;
82830a5e8faSwyllys 	char *keylabel = NULL;
82930a5e8faSwyllys 
83030a5e8faSwyllys 	if (handle == NULL || attrlist == NULL || numattr == 0) {
83199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
83299ebb4caSwyllys 	}
83330a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
83499ebb4caSwyllys 	if (rv != KMF_OK) {
83599ebb4caSwyllys 		return (rv);
83699ebb4caSwyllys 	}
83799ebb4caSwyllys 
83830a5e8faSwyllys 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
83930a5e8faSwyllys 	    (void *)&cred, NULL);
84030a5e8faSwyllys 	if (rv != KMF_OK)
84130a5e8faSwyllys 		return (rv);
84230a5e8faSwyllys 
84330a5e8faSwyllys 	rv = nss_authenticate(handle, nss_slot, &cred);
84499ebb4caSwyllys 	if (rv != KMF_OK) {
84599ebb4caSwyllys 		return (rv);
84699ebb4caSwyllys 	}
84799ebb4caSwyllys 
84830a5e8faSwyllys 	/* "storekey" is optional. Default is TRUE */
84930a5e8faSwyllys 	(void) kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
85030a5e8faSwyllys 	    &storekey, NULL);
85130a5e8faSwyllys 
85230a5e8faSwyllys 	/* keytype is optional.  KMF_RSA is default */
85330a5e8faSwyllys 	(void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
85430a5e8faSwyllys 	    (void *)&keytype, NULL);
85530a5e8faSwyllys 
85630a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
85730a5e8faSwyllys 	    &keylen, &keylen_size);
85830a5e8faSwyllys 	if (rv == KMF_ERR_ATTR_NOT_FOUND)
85930a5e8faSwyllys 		/* Default keylen = 1024 */
86030a5e8faSwyllys 		rv = KMF_OK;
86130a5e8faSwyllys 	else if (rv != KMF_OK)
86230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
86330a5e8faSwyllys 
86430a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
86530a5e8faSwyllys 	privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
86630a5e8faSwyllys 	if (pubkey == NULL || privkey == NULL)
86730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
86830a5e8faSwyllys 
86930a5e8faSwyllys 	(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
87030a5e8faSwyllys 	(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
87130a5e8faSwyllys 
87230a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr,	NULL, &len);
87330a5e8faSwyllys 	if (rv == KMF_OK && len > 0) {
87430a5e8faSwyllys 		keylabel = malloc(len + 1);
87530a5e8faSwyllys 		if (keylabel == NULL)
87630a5e8faSwyllys 			return (KMF_ERR_MEMORY);
87730a5e8faSwyllys 		/* Now fill in the label value */
87830a5e8faSwyllys 		(void) memset(keylabel, 0, len + 1);
87930a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr,
88030a5e8faSwyllys 		    keylabel, NULL);
88130a5e8faSwyllys 		if (rv != KMF_OK) {
88230a5e8faSwyllys 			free(keylabel);
88330a5e8faSwyllys 			goto cleanup;
88430a5e8faSwyllys 		}
88530a5e8faSwyllys 	}
88630a5e8faSwyllys 
88799ebb4caSwyllys 	/* Get some random bits */
88899ebb4caSwyllys 	InitRandom("/dev/urandom");
88930a5e8faSwyllys 	if (keytype == KMF_RSA) {
89030a5e8faSwyllys 		KMF_BIGINT rsaexp;
89130a5e8faSwyllys 
89230a5e8faSwyllys 		rsaparams.keySizeInBits = keylen;
89399ebb4caSwyllys 		/*
89499ebb4caSwyllys 		 * NSS only allows for a 4 byte exponent.
89599ebb4caSwyllys 		 * Ignore the exponent parameter if it is too big.
89699ebb4caSwyllys 		 */
89730a5e8faSwyllys 		if ((rv = kmf_get_attr(KMF_RSAEXP_ATTR, attrlist, numattr,
89830a5e8faSwyllys 		    &rsaexp, NULL)) == KMF_OK) {
89930a5e8faSwyllys 			if (rsaexp.len > 0 &&
90030a5e8faSwyllys 			    rsaexp.len <= sizeof (publicExponent) &&
90130a5e8faSwyllys 			    rsaexp.val != NULL) {
90230a5e8faSwyllys 				(void) memcpy(&publicExponent, rsaexp.val,
90330a5e8faSwyllys 				    rsaexp.len);
90430a5e8faSwyllys 			}
90599ebb4caSwyllys 		}
90699ebb4caSwyllys 		rsaparams.pe = publicExponent;
90799ebb4caSwyllys 		mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
90899ebb4caSwyllys 		nssparams = &rsaparams;
90930a5e8faSwyllys 	} else if (keytype == KMF_DSA) {
91099ebb4caSwyllys 		PQGVerify *pqgVerify = NULL;
91199ebb4caSwyllys 		int ks;
91299ebb4caSwyllys 		SECStatus	nssrv, passed;
91399ebb4caSwyllys 
91499ebb4caSwyllys 		mechanism = CKM_DSA_KEY_PAIR_GEN;
91599ebb4caSwyllys 
91630a5e8faSwyllys 		ks = PQG_PBITS_TO_INDEX(keylen);
91799ebb4caSwyllys 		nssrv = PK11_PQG_ParamGen(ks, &pqgParams, &pqgVerify);
91899ebb4caSwyllys 		if (nssrv != SECSuccess) {
91999ebb4caSwyllys 			SET_ERROR(kmfh, rv);
92099ebb4caSwyllys 			PK11_PQG_DestroyVerify(pqgVerify);
92199ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
92299ebb4caSwyllys 			goto cleanup;
92399ebb4caSwyllys 		}
92499ebb4caSwyllys 
92599ebb4caSwyllys 		nssrv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
92699ebb4caSwyllys 		if (nssrv != SECSuccess || passed != SECSuccess) {
92799ebb4caSwyllys 			SET_ERROR(kmfh, rv);
92899ebb4caSwyllys 			rv = KMF_ERR_KEYGEN_FAILED;
92999ebb4caSwyllys 		}
93099ebb4caSwyllys 
93199ebb4caSwyllys 		PK11_PQG_DestroyVerify(pqgVerify);
93299ebb4caSwyllys 
93399ebb4caSwyllys 		if (rv != KMF_OK) {
93499ebb4caSwyllys 			SET_ERROR(kmfh, PORT_GetError());
93599ebb4caSwyllys 			goto cleanup;
93699ebb4caSwyllys 		}
93799ebb4caSwyllys 
93899ebb4caSwyllys 		nssparams = pqgParams;
939e65e5c2dSWyllys Ingersoll 	} else if (keytype == KMF_ECDSA) {
940e65e5c2dSWyllys Ingersoll 		KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR,
941e65e5c2dSWyllys Ingersoll 		    attrlist, numattr);
942e65e5c2dSWyllys Ingersoll 		if (eccoid == NULL)
943e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_BAD_PARAMETER);
944e65e5c2dSWyllys Ingersoll 
945e65e5c2dSWyllys Ingersoll 		ecparams = SECITEM_AllocItem(NULL, NULL, (eccoid->Length));
946e65e5c2dSWyllys Ingersoll 		if (!ecparams)
947e65e5c2dSWyllys Ingersoll 			return (KMF_ERR_MEMORY);
948e65e5c2dSWyllys Ingersoll 
949e65e5c2dSWyllys Ingersoll 		(void) memcpy(ecparams->data, eccoid->Data, eccoid->Length);
950e65e5c2dSWyllys Ingersoll 
951e65e5c2dSWyllys Ingersoll 		mechanism = CKM_EC_KEY_PAIR_GEN;
952e65e5c2dSWyllys Ingersoll 		nssparams = ecparams;
95399ebb4caSwyllys 	} else {
95499ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
95599ebb4caSwyllys 		goto cleanup;
95699ebb4caSwyllys 	}
95799ebb4caSwyllys 
95830a5e8faSwyllys 	NSSprivkey = PK11_GenerateKeyPair(nss_slot, mechanism, nssparams,
95930a5e8faSwyllys 	    &NSSpubkey,
96030a5e8faSwyllys 	    storekey, /* isPermanent */
96130a5e8faSwyllys 	    PR_TRUE, /* isSensitive */
96230a5e8faSwyllys 	    (void *)cred.cred);
96399ebb4caSwyllys 
96499ebb4caSwyllys 	if (NSSprivkey == NULL || NSSpubkey == NULL) {
96599ebb4caSwyllys 		SET_ERROR(kmfh, PORT_GetError());
96699ebb4caSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
96799ebb4caSwyllys 	} else {
96830a5e8faSwyllys 		if (keylabel != NULL && strlen(keylabel)) {
96999ebb4caSwyllys 			(void) PK11_SetPrivateKeyNickname(NSSprivkey,
97030a5e8faSwyllys 			    keylabel);
97130a5e8faSwyllys 			(void) PK11_SetPublicKeyNickname(NSSpubkey, keylabel);
97299ebb4caSwyllys 		}
97399ebb4caSwyllys 		/* Now, convert it to a KMF_KEY object for the framework */
97430a5e8faSwyllys 		privkey->kstype = KMF_KEYSTORE_NSS;
97530a5e8faSwyllys 		privkey->keyalg = keytype;
97630a5e8faSwyllys 		privkey->keyclass = KMF_ASYM_PRI;
97730a5e8faSwyllys 		privkey->keylabel = PK11_GetPrivateKeyNickname(NSSprivkey);
97830a5e8faSwyllys 		privkey->keyp = (void *)NSSprivkey;
97930a5e8faSwyllys 
98030a5e8faSwyllys 		pubkey->kstype = KMF_KEYSTORE_NSS;
98130a5e8faSwyllys 		pubkey->keyalg = keytype;
98230a5e8faSwyllys 		pubkey->keyp = (void *)NSSpubkey;
98330a5e8faSwyllys 		pubkey->keyclass = KMF_ASYM_PUB;
98430a5e8faSwyllys 		pubkey->keylabel = PK11_GetPublicKeyNickname(NSSpubkey);
98530a5e8faSwyllys 
98699ebb4caSwyllys 		rv = KMF_OK;
98799ebb4caSwyllys 	}
98899ebb4caSwyllys cleanup:
98999ebb4caSwyllys 	if (rv != KMF_OK) {
99099ebb4caSwyllys 		if (NSSpubkey)
9915ad42b1bSSurya Prakki 			(void) PK11_DeleteTokenPublicKey(NSSpubkey);
99299ebb4caSwyllys 		if (NSSprivkey)
9935ad42b1bSSurya Prakki 			(void) PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE);
99499ebb4caSwyllys 
99599ebb4caSwyllys 		privkey->keyp = NULL;
99699ebb4caSwyllys 		pubkey->keyp = NULL;
99799ebb4caSwyllys 	}
99899ebb4caSwyllys 
99930a5e8faSwyllys 	if (keylabel)
100030a5e8faSwyllys 		free(keylabel);
100130a5e8faSwyllys 
100299ebb4caSwyllys 	if (pqgParams != NULL)
100399ebb4caSwyllys 		PK11_PQG_DestroyParams(pqgParams);
100499ebb4caSwyllys 
1005e65e5c2dSWyllys Ingersoll 	if (ecparams != NULL)
1006e65e5c2dSWyllys Ingersoll 		SECITEM_FreeItem(ecparams, PR_TRUE);
1007e65e5c2dSWyllys Ingersoll 
100899ebb4caSwyllys 	if (nss_slot != NULL)
100999ebb4caSwyllys 		PK11_FreeSlot(nss_slot);
101099ebb4caSwyllys 
101199ebb4caSwyllys 	return (rv);
101299ebb4caSwyllys }
101399ebb4caSwyllys 
101499ebb4caSwyllys KMF_RETURN
NSS_SignData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * tobesigned,KMF_DATA * output)101599ebb4caSwyllys NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
101630a5e8faSwyllys     KMF_OID *AlgOID, KMF_DATA *tobesigned,
101730a5e8faSwyllys     KMF_DATA *output)
101899ebb4caSwyllys {
101999ebb4caSwyllys 	KMF_RETURN		ret = KMF_OK;
102030a5e8faSwyllys 	KMF_ALGORITHM_INDEX	AlgId;
102199ebb4caSwyllys 	SECOidTag		signAlgTag;
102299ebb4caSwyllys 	SECKEYPrivateKey	*NSSprivkey = NULL;
102399ebb4caSwyllys 	SECStatus		rv;
102499ebb4caSwyllys 	SECItem			signed_data;
102599ebb4caSwyllys 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
102699ebb4caSwyllys 
102799ebb4caSwyllys 	signed_data.data = 0;
102899ebb4caSwyllys 	if (key == NULL || AlgOID == NULL ||
102999ebb4caSwyllys 	    tobesigned == NULL || output == NULL ||
103099ebb4caSwyllys 	    tobesigned->Data == NULL ||
103199ebb4caSwyllys 	    output->Data == NULL)
103299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
103399ebb4caSwyllys 
103499ebb4caSwyllys 	/* Map the OID to a NSS algorithm */
103530a5e8faSwyllys 	AlgId = x509_algoid_to_algid(AlgOID);
103699ebb4caSwyllys 	if (AlgId == KMF_ALGID_NONE)
103799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
103899ebb4caSwyllys 
103999ebb4caSwyllys 	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
104099ebb4caSwyllys 
104199ebb4caSwyllys 	if (AlgId == KMF_ALGID_MD5WithRSA)
104299ebb4caSwyllys 		signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
104399ebb4caSwyllys 	else if (AlgId == KMF_ALGID_MD2WithRSA)
104499ebb4caSwyllys 		signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
104599ebb4caSwyllys 	else if (AlgId == KMF_ALGID_SHA1WithRSA)
104699ebb4caSwyllys 		signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1047e65e5c2dSWyllys Ingersoll 	else if (AlgId == KMF_ALGID_SHA256WithRSA)
1048e65e5c2dSWyllys Ingersoll 		signAlgTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1049e65e5c2dSWyllys Ingersoll 	else if (AlgId == KMF_ALGID_SHA384WithRSA)
1050e65e5c2dSWyllys Ingersoll 		signAlgTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1051e65e5c2dSWyllys Ingersoll 	else if (AlgId == KMF_ALGID_SHA512WithRSA)
1052e65e5c2dSWyllys Ingersoll 		signAlgTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
105399ebb4caSwyllys 	else if (AlgId == KMF_ALGID_SHA1WithDSA)
105499ebb4caSwyllys 		signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
1055e65e5c2dSWyllys Ingersoll 	else if (AlgId == KMF_ALGID_SHA1WithECDSA || AlgId == KMF_ALGID_ECDSA)
1056e65e5c2dSWyllys Ingersoll 		signAlgTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
1057e65e5c2dSWyllys Ingersoll 	else if (AlgId == KMF_ALGID_SHA256WithECDSA)
1058e65e5c2dSWyllys Ingersoll 		signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
1059e65e5c2dSWyllys Ingersoll 	else if (AlgId == KMF_ALGID_SHA384WithECDSA)
1060e65e5c2dSWyllys Ingersoll 		signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
1061e65e5c2dSWyllys Ingersoll 	else if (AlgId == KMF_ALGID_SHA512WithECDSA)
1062e65e5c2dSWyllys Ingersoll 		signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
1063e65e5c2dSWyllys Ingersoll 	else	/* NSS does not support DSA with SHA2 hashes (FIPS 186-3) */
106499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
106599ebb4caSwyllys 
106699ebb4caSwyllys 	rv = SEC_SignData(&signed_data, tobesigned->Data,
106799ebb4caSwyllys 	    tobesigned->Length, NSSprivkey, signAlgTag);
106899ebb4caSwyllys 
106999ebb4caSwyllys 	if (rv != 0) {
107099ebb4caSwyllys 		SET_ERROR(kmfh, rv);
107199ebb4caSwyllys 		return (KMF_ERR_INTERNAL);
107299ebb4caSwyllys 	}
107399ebb4caSwyllys 
107499ebb4caSwyllys 	if (signed_data.len <= output->Length) {
107599ebb4caSwyllys 		(void) memcpy(output->Data, signed_data.data, signed_data.len);
107699ebb4caSwyllys 		output->Length = signed_data.len;
107799ebb4caSwyllys 	} else {
107899ebb4caSwyllys 		output->Length = 0;
107999ebb4caSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
108099ebb4caSwyllys 	}
108199ebb4caSwyllys 	free(signed_data.data);
108299ebb4caSwyllys 
108399ebb4caSwyllys 	return (ret);
108499ebb4caSwyllys }
108599ebb4caSwyllys 
108699ebb4caSwyllys KMF_RETURN
NSS_EncodePubKeyData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * keyp,KMF_DATA * encoded)108799ebb4caSwyllys NSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
108899ebb4caSwyllys 	KMF_DATA *encoded)
108999ebb4caSwyllys {
109099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
109199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
109299ebb4caSwyllys 	SECItem *rvitem;
109399ebb4caSwyllys 	CERTSubjectPublicKeyInfo *spki = NULL;
109499ebb4caSwyllys 
109599ebb4caSwyllys 	if (keyp == NULL || encoded == NULL || keyp->keyp == NULL)
109699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
109799ebb4caSwyllys 
109899ebb4caSwyllys 	spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp);
109999ebb4caSwyllys 	if (spki == NULL) {
110099ebb4caSwyllys 		SET_ERROR(kmfh, PORT_GetError());
110199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
110299ebb4caSwyllys 	}
110399ebb4caSwyllys 
110499ebb4caSwyllys 	rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki,
110530a5e8faSwyllys 	    CERT_SubjectPublicKeyInfoTemplate);
110699ebb4caSwyllys 	if (rvitem != NULL) {
110799ebb4caSwyllys 		encoded->Data = malloc(rvitem->len);
110899ebb4caSwyllys 		if (encoded->Data == NULL) {
110999ebb4caSwyllys 			ret = KMF_ERR_MEMORY;
111099ebb4caSwyllys 		} else {
111199ebb4caSwyllys 			(void) memcpy(encoded->Data, rvitem->data, rvitem->len);
111299ebb4caSwyllys 			encoded->Length = rvitem->len;
111399ebb4caSwyllys 		}
111499ebb4caSwyllys 		SECITEM_FreeItem(rvitem, TRUE);
111599ebb4caSwyllys 	} else {
111699ebb4caSwyllys 		SET_ERROR(kmfh, PORT_GetError());
111799ebb4caSwyllys 		encoded->Data = NULL;
111899ebb4caSwyllys 		encoded->Length = 0;
111999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
112099ebb4caSwyllys 	}
112199ebb4caSwyllys 	SECKEY_DestroySubjectPublicKeyInfo(spki);
112299ebb4caSwyllys 
112399ebb4caSwyllys 	return (ret);
112499ebb4caSwyllys }
112599ebb4caSwyllys 
112699ebb4caSwyllys KMF_RETURN
NSS_DeleteKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)112730a5e8faSwyllys NSS_DeleteKey(KMF_HANDLE_T handle,
112830a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
112999ebb4caSwyllys {
113099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
113199ebb4caSwyllys 	PK11SlotInfo *nss_slot = NULL;
113230a5e8faSwyllys 	KMF_KEY_HANDLE *key;
113330a5e8faSwyllys 	KMF_CREDENTIAL cred;
113430a5e8faSwyllys 	boolean_t delete_token = B_TRUE;
113599ebb4caSwyllys 
113630a5e8faSwyllys 	if (handle == NULL || attrlist == NULL || numattr == 0) {
113730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
113830a5e8faSwyllys 	}
113999ebb4caSwyllys 	/*
114099ebb4caSwyllys 	 * "delete_token" means to clear it from the token storage as well
114199ebb4caSwyllys 	 * as from memory.
114299ebb4caSwyllys 	 */
114330a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
114499ebb4caSwyllys 	if (key == NULL || key->keyp == NULL)
114599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
114699ebb4caSwyllys 
114730a5e8faSwyllys 	rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
114830a5e8faSwyllys 	    (void *)&delete_token, NULL);
114930a5e8faSwyllys 	if (rv != KMF_OK)
115030a5e8faSwyllys 		/* "delete_token" is optional. Default is TRUE */
115130a5e8faSwyllys 		rv = KMF_OK;
115230a5e8faSwyllys 
115399ebb4caSwyllys 	if (delete_token) {
115499ebb4caSwyllys 		SECStatus nssrv = SECSuccess;
115599ebb4caSwyllys 		if (key->keyclass != KMF_ASYM_PUB &&
115630a5e8faSwyllys 		    key->keyclass != KMF_ASYM_PRI &&
115730a5e8faSwyllys 		    key->keyclass != KMF_SYMMETRIC)
115899ebb4caSwyllys 			return (KMF_ERR_BAD_KEY_CLASS);
115999ebb4caSwyllys 
116030a5e8faSwyllys 		rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
116199ebb4caSwyllys 		if (rv != KMF_OK) {
116299ebb4caSwyllys 			return (rv);
116399ebb4caSwyllys 		}
116430a5e8faSwyllys 
116530a5e8faSwyllys 		rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
116630a5e8faSwyllys 		    (void *)&cred, NULL);
116730a5e8faSwyllys 		if (rv != KMF_OK)
116830a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
116930a5e8faSwyllys 
117030a5e8faSwyllys 		rv = nss_authenticate(handle, nss_slot, &cred);
117199ebb4caSwyllys 		if (rv != KMF_OK) {
117299ebb4caSwyllys 			return (rv);
117399ebb4caSwyllys 		}
117499ebb4caSwyllys 
117599ebb4caSwyllys 		if (key->keyclass == KMF_ASYM_PUB) {
117699ebb4caSwyllys 			nssrv = PK11_DeleteTokenPublicKey(
117730a5e8faSwyllys 			    (SECKEYPublicKey *)key->keyp);
117899ebb4caSwyllys 		} else if (key->keyclass == KMF_ASYM_PRI) {
117999ebb4caSwyllys 			nssrv = PK11_DeleteTokenPrivateKey(
118030a5e8faSwyllys 			    (SECKEYPrivateKey *)key->keyp, PR_TRUE);
118199ebb4caSwyllys 		} else if (key->keyclass == KMF_SYMMETRIC) {
118299ebb4caSwyllys 			nssrv = PK11_DeleteTokenSymKey(
118330a5e8faSwyllys 			    (PK11SymKey *) key->keyp);
118499ebb4caSwyllys 			if (nssrv == SECSuccess)
118530a5e8faSwyllys 				PK11_FreeSymKey((PK11SymKey *) key->keyp);
118699ebb4caSwyllys 		}
118799ebb4caSwyllys 		if (nssrv != SECSuccess) {
118899ebb4caSwyllys 			SET_ERROR(handle, PORT_GetError());
118999ebb4caSwyllys 			rv = KMF_ERR_INTERNAL;
119099ebb4caSwyllys 		}
119199ebb4caSwyllys 	} else {
119299ebb4caSwyllys 		if (key->keyclass == KMF_ASYM_PUB) {
119399ebb4caSwyllys 			SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp);
119499ebb4caSwyllys 		} else if (key->keyclass == KMF_ASYM_PRI) {
119599ebb4caSwyllys 			SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp);
119699ebb4caSwyllys 		} else if (key->keyclass == KMF_SYMMETRIC) {
119799ebb4caSwyllys 			PK11_FreeSymKey((PK11SymKey *) key->keyp);
119899ebb4caSwyllys 		} else {
119999ebb4caSwyllys 			return (KMF_ERR_BAD_KEY_CLASS);
120099ebb4caSwyllys 		}
120199ebb4caSwyllys 	}
120299ebb4caSwyllys 	key->keyp = NULL;
120399ebb4caSwyllys 
120499ebb4caSwyllys 	return (rv);
120599ebb4caSwyllys }
120699ebb4caSwyllys 
120799ebb4caSwyllys KMF_RETURN
NSS_GetErrorString(KMF_HANDLE_T handle,char ** msgstr)120830a5e8faSwyllys NSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
120999ebb4caSwyllys {
121099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
121199ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
121230a5e8faSwyllys 	char *str;
121330a5e8faSwyllys 
121430a5e8faSwyllys 	/* Get the error string in the default language */
121530a5e8faSwyllys 	str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode);
121630a5e8faSwyllys 
121730a5e8faSwyllys 	if (str != NULL) {
121830a5e8faSwyllys 		*msgstr = (char *)strdup(str);
121930a5e8faSwyllys 		if ((*msgstr) == NULL)
122030a5e8faSwyllys 			ret = KMF_ERR_MEMORY;
122130a5e8faSwyllys 	} else {
122230a5e8faSwyllys 		*msgstr = NULL;
122330a5e8faSwyllys 	}
122430a5e8faSwyllys 
122530a5e8faSwyllys 	return (ret);
122630a5e8faSwyllys }
122730a5e8faSwyllys 
122830a5e8faSwyllys KMF_RETURN
NSS_FindPrikeyByCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)122930a5e8faSwyllys NSS_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
123030a5e8faSwyllys {
123130a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
123230a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
123399ebb4caSwyllys 	PK11SlotInfo *nss_slot = NULL;
123430a5e8faSwyllys 	KMF_CREDENTIAL cred;
123530a5e8faSwyllys 	KMF_KEY_HANDLE *key = NULL;
123630a5e8faSwyllys 	KMF_DATA *cert = NULL;
123730a5e8faSwyllys 	CERTCertificate *nss_cert = NULL;
123830a5e8faSwyllys 	SECKEYPrivateKey* privkey = NULL;
123999ebb4caSwyllys 
124030a5e8faSwyllys 	if (handle == NULL || attrlist == NULL || numattr == 0) {
124199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
124299ebb4caSwyllys 	}
124399ebb4caSwyllys 
124430a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
124530a5e8faSwyllys 	if (rv != KMF_OK)
124630a5e8faSwyllys 		return (rv);
124799ebb4caSwyllys 
124830a5e8faSwyllys 	/* Get the credential */
124930a5e8faSwyllys 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
125030a5e8faSwyllys 	    (void *)&cred, NULL);
125130a5e8faSwyllys 	if (rv != KMF_OK)
125230a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
125330a5e8faSwyllys 	rv = nss_authenticate(handle, nss_slot, &cred);
125430a5e8faSwyllys 	if (rv != KMF_OK)
125530a5e8faSwyllys 		return (rv);
125699ebb4caSwyllys 
125730a5e8faSwyllys 	/* Get the key handle */
125830a5e8faSwyllys 	key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
125930a5e8faSwyllys 	if (key == NULL)
126030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
126199ebb4caSwyllys 
126230a5e8faSwyllys 	/* Get the cert data and decode it */
126330a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
126430a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
126530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
126699ebb4caSwyllys 
126730a5e8faSwyllys 	nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
126830a5e8faSwyllys 	    cert->Length);
126930a5e8faSwyllys 	if (nss_cert == NULL) {
127030a5e8faSwyllys 		SET_ERROR(kmfh, PORT_GetError());
127130a5e8faSwyllys 		return (KMF_ERR_BAD_CERT_FORMAT);
127299ebb4caSwyllys 	}
127399ebb4caSwyllys 
127430a5e8faSwyllys 	privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL);
127530a5e8faSwyllys 	if (privkey == NULL) {
127630a5e8faSwyllys 		SET_ERROR(kmfh, PORT_GetError());
127730a5e8faSwyllys 		return (KMF_ERR_KEY_NOT_FOUND);
127899ebb4caSwyllys 	}
127999ebb4caSwyllys 
128030a5e8faSwyllys 	key->kstype = KMF_KEYSTORE_NSS;
128130a5e8faSwyllys 	key->keyclass = KMF_ASYM_PRI;
128230a5e8faSwyllys 	key->keyp = (void *)privkey;
128330a5e8faSwyllys 	key->keylabel = PK11_GetPrivateKeyNickname(privkey);
128499ebb4caSwyllys 
128530a5e8faSwyllys 	CERT_DestroyCertificate(nss_cert);
128699ebb4caSwyllys 
128730a5e8faSwyllys 	return (KMF_OK);
128830a5e8faSwyllys }
128999ebb4caSwyllys 
129099ebb4caSwyllys 
129130a5e8faSwyllys KMF_RETURN
NSS_DecryptData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * ciphertext,KMF_DATA * output)129230a5e8faSwyllys NSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
129330a5e8faSwyllys 	KMF_OID *AlgOID, KMF_DATA *ciphertext,
129430a5e8faSwyllys 	KMF_DATA *output)
129530a5e8faSwyllys {
129630a5e8faSwyllys 	KMF_RETURN		ret = KMF_OK;
129730a5e8faSwyllys 	SECKEYPrivateKey	*NSSprivkey = NULL;
129830a5e8faSwyllys 	SECStatus		rv;
129930a5e8faSwyllys 	KMF_HANDLE		*kmfh = (KMF_HANDLE *)handle;
130030a5e8faSwyllys 	unsigned int in_len = 0, out_len = 0;
130130a5e8faSwyllys 	unsigned int total_decrypted = 0, modulus_len = 0;
130230a5e8faSwyllys 	uint8_t *in_data, *out_data;
130330a5e8faSwyllys 	int i, blocks;
130499ebb4caSwyllys 
130530a5e8faSwyllys 	if (key == NULL || AlgOID == NULL ||
130630a5e8faSwyllys 	    ciphertext == NULL || output == NULL ||
130730a5e8faSwyllys 	    ciphertext->Data == NULL ||
130830a5e8faSwyllys 	    output->Data == NULL)
130930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
131099ebb4caSwyllys 
131130a5e8faSwyllys 	NSSprivkey = (SECKEYPrivateKey *)key->keyp;
131230a5e8faSwyllys 	modulus_len = PK11_GetPrivateModulusLen(NSSprivkey);
131330a5e8faSwyllys 
131430a5e8faSwyllys 	blocks = ciphertext->Length/modulus_len;
131530a5e8faSwyllys 	out_data = output->Data;
131630a5e8faSwyllys 	in_data = ciphertext->Data;
131730a5e8faSwyllys 	out_len = modulus_len - 11;
131830a5e8faSwyllys 	in_len = modulus_len;
131930a5e8faSwyllys 
132030a5e8faSwyllys 	for (i = 0; i < blocks; i++) {
132130a5e8faSwyllys 		rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data,
132230a5e8faSwyllys 		    &out_len, ciphertext->Length, in_data, in_len);
132330a5e8faSwyllys 
132430a5e8faSwyllys 		if (rv != 0) {
132530a5e8faSwyllys 			SET_ERROR(kmfh, rv);
132630a5e8faSwyllys 			return (KMF_ERR_INTERNAL);
132730a5e8faSwyllys 		}
132830a5e8faSwyllys 
132930a5e8faSwyllys 		out_data += out_len;
133030a5e8faSwyllys 		total_decrypted += out_len;
133130a5e8faSwyllys 		in_data += in_len;
133299ebb4caSwyllys 	}
133399ebb4caSwyllys 
133430a5e8faSwyllys 	output->Length = total_decrypted;
133530a5e8faSwyllys 
133699ebb4caSwyllys 	return (ret);
133799ebb4caSwyllys }
133899ebb4caSwyllys 
133930a5e8faSwyllys static KMF_KEY_ALG
pk11keytype2kmf(CK_KEY_TYPE type)134030a5e8faSwyllys pk11keytype2kmf(CK_KEY_TYPE type)
134130a5e8faSwyllys {
134230a5e8faSwyllys 	switch (type) {
134330a5e8faSwyllys 	case CKK_RSA:
134430a5e8faSwyllys 		return (KMF_RSA);
134530a5e8faSwyllys 	case CKK_DSA:
134630a5e8faSwyllys 		return (KMF_RSA);
134730a5e8faSwyllys 	case CKK_AES:
134830a5e8faSwyllys 		return (KMF_AES);
134930a5e8faSwyllys 	case CKK_RC4:
135030a5e8faSwyllys 		return (KMF_RC4);
135130a5e8faSwyllys 	case CKK_DES:
135230a5e8faSwyllys 		return (KMF_DES);
135330a5e8faSwyllys 	case CKK_DES3:
135430a5e8faSwyllys 		return (KMF_DES3);
1355e65e5c2dSWyllys Ingersoll 	case CKK_EC:
1356e65e5c2dSWyllys Ingersoll 		return (KMF_ECDSA);
135730a5e8faSwyllys 	default:
135830a5e8faSwyllys 		/* not supported */
135930a5e8faSwyllys 		return (KMF_KEYALG_NONE);
136030a5e8faSwyllys 	}
136130a5e8faSwyllys }
136230a5e8faSwyllys 
136399ebb4caSwyllys KMF_RETURN
NSS_FindKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)136430a5e8faSwyllys NSS_FindKey(KMF_HANDLE_T handle,
136530a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
136699ebb4caSwyllys {
136730a5e8faSwyllys 	KMF_RETURN rv;
136830a5e8faSwyllys 	SECKEYPrivateKeyList *prilist;
136930a5e8faSwyllys 	SECKEYPrivateKeyListNode *prinode;
137030a5e8faSwyllys 	SECKEYPublicKeyList *publist;
137130a5e8faSwyllys 	SECKEYPublicKeyListNode *pubnode;
137299ebb4caSwyllys 	PK11SlotInfo *nss_slot = NULL;
137330a5e8faSwyllys 	PK11SymKey *symlist = NULL;
137430a5e8faSwyllys 	int count;
137530a5e8faSwyllys 	uint32_t maxkeys;
137630a5e8faSwyllys 	KMF_KEY_HANDLE *keys;
137730a5e8faSwyllys 	uint32_t *numkeys;
13782cbed729Swyllys 	KMF_CREDENTIAL *cred = NULL;
137930a5e8faSwyllys 	KMF_KEY_CLASS keyclass;
138030a5e8faSwyllys 	char *findLabel;
13812cbed729Swyllys 	char *nick;
13822cbed729Swyllys 	int match = 0;
138330a5e8faSwyllys 	KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
138430a5e8faSwyllys 
138530a5e8faSwyllys 	if (handle == NULL || attrlist == NULL || numattr == 0) {
138630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
138730a5e8faSwyllys 	}
138899ebb4caSwyllys 
138930a5e8faSwyllys 	numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
139030a5e8faSwyllys 	if (numkeys == NULL)
139199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
139230a5e8faSwyllys 
139330a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
139430a5e8faSwyllys 	if (rv != KMF_OK) {
139530a5e8faSwyllys 		return (rv);
139699ebb4caSwyllys 	}
139799ebb4caSwyllys 
13982cbed729Swyllys 	/* It is OK if this is NULL, we dont need a cred to find public keys */
13992cbed729Swyllys 	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
140030a5e8faSwyllys 
14012cbed729Swyllys 	if (cred != NULL) {
14022cbed729Swyllys 		rv = nss_authenticate(handle, nss_slot, cred);
14032cbed729Swyllys 		if (rv != KMF_OK) {
14042cbed729Swyllys 			return (rv);
14052cbed729Swyllys 		}
140699ebb4caSwyllys 	}
140799ebb4caSwyllys 
140830a5e8faSwyllys 	maxkeys = *numkeys;
140930a5e8faSwyllys 	if (maxkeys == 0)
141030a5e8faSwyllys 		maxkeys = 0xFFFFFFFF;
141130a5e8faSwyllys 	*numkeys = 0;
141299ebb4caSwyllys 
141330a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
141430a5e8faSwyllys 	    (void *)&keyclass, NULL);
141530a5e8faSwyllys 	if (rv != KMF_OK)
141630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
141730a5e8faSwyllys 
141830a5e8faSwyllys 	findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
141930a5e8faSwyllys 
142030a5e8faSwyllys 	if (keyclass == KMF_ASYM_PUB) {
142130a5e8faSwyllys 		publist = PK11_ListPublicKeysInSlot(nss_slot, findLabel);
142230a5e8faSwyllys 		if (publist == NULL) {
142330a5e8faSwyllys 			rv = KMF_ERR_KEY_NOT_FOUND;
142430a5e8faSwyllys 			goto cleanup;
142530a5e8faSwyllys 		}
142630a5e8faSwyllys 	} else if (keyclass == KMF_ASYM_PRI) {
142730a5e8faSwyllys 		prilist = PK11_ListPrivKeysInSlot(nss_slot, findLabel, NULL);
142830a5e8faSwyllys 		if (prilist == NULL) {
142930a5e8faSwyllys 			rv = KMF_ERR_KEY_NOT_FOUND;
143030a5e8faSwyllys 			goto cleanup;
143130a5e8faSwyllys 		}
143230a5e8faSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
143330a5e8faSwyllys 		symlist = PK11_ListFixedKeysInSlot(nss_slot, findLabel, NULL);
143430a5e8faSwyllys 		if (symlist == NULL) {
143530a5e8faSwyllys 			rv = KMF_ERR_KEY_NOT_FOUND;
143630a5e8faSwyllys 			goto cleanup;
143799ebb4caSwyllys 		}
143899ebb4caSwyllys 	} else {
143930a5e8faSwyllys 		rv = KMF_ERR_BAD_KEY_CLASS;
144030a5e8faSwyllys 		goto cleanup;
144130a5e8faSwyllys 	}
144299ebb4caSwyllys 
144330a5e8faSwyllys 	keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
144430a5e8faSwyllys 	/* it is okay to have "keys" contains NULL */
144599ebb4caSwyllys 
144630a5e8faSwyllys 	if (keyclass == KMF_ASYM_PUB) {
144730a5e8faSwyllys 		for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist);
144830a5e8faSwyllys 		    !PUBKEY_LIST_END(pubnode, publist) && count < maxkeys;
14492cbed729Swyllys 		    pubnode = PUBKEY_LIST_NEXT(pubnode)) {
14502cbed729Swyllys 			match = 0;
14512cbed729Swyllys 			/*
14522cbed729Swyllys 			 * Due to bug in NSS, we have to manually match
14532cbed729Swyllys 			 * the labels to be sure we have a match.
14542cbed729Swyllys 			 */
14552cbed729Swyllys 			nick = PK11_GetPublicKeyNickname(pubnode->key);
14562cbed729Swyllys 			if (findLabel) {
14572cbed729Swyllys 				match = (nick &&
14582cbed729Swyllys 				    (strcmp(nick, findLabel) == 0));
14592cbed729Swyllys 			} else {
14602cbed729Swyllys 				/* always match if findLabel is NULL */
14612cbed729Swyllys 				match = 1;
14622cbed729Swyllys 			}
14632cbed729Swyllys 			if (keys != NULL && match) {
146430a5e8faSwyllys 				keys[count].kstype = KMF_KEYSTORE_NSS;
146530a5e8faSwyllys 				keys[count].keyclass = KMF_ASYM_PUB;
146630a5e8faSwyllys 				keys[count].keyp = (void *)pubnode->key;
14672cbed729Swyllys 				keys[count].keylabel = nick;
146899ebb4caSwyllys 
146930a5e8faSwyllys 				if (pubnode->key->keyType == rsaKey)
147030a5e8faSwyllys 					keys[count].keyalg = KMF_RSA;
147130a5e8faSwyllys 				else if (pubnode->key->keyType == dsaKey)
147230a5e8faSwyllys 					keys[count].keyalg = KMF_DSA;
1473e65e5c2dSWyllys Ingersoll 				else if (pubnode->key->keyType == ecKey)
1474e65e5c2dSWyllys Ingersoll 					keys[count].keyalg = KMF_ECDSA;
147530a5e8faSwyllys 			}
14762cbed729Swyllys 			if (match)
14772cbed729Swyllys 				count++;
147899ebb4caSwyllys 		}
147930a5e8faSwyllys 		*numkeys = count;
148030a5e8faSwyllys 	} else if (keyclass == KMF_ASYM_PRI) {
148130a5e8faSwyllys 		for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist);
148230a5e8faSwyllys 		    !PRIVKEY_LIST_END(prinode, prilist) && count < maxkeys;
14832cbed729Swyllys 		    prinode = PRIVKEY_LIST_NEXT(prinode)) {
14842cbed729Swyllys 			match = 0;
14852cbed729Swyllys 			/*
14862cbed729Swyllys 			 * Due to bug in NSS, we have to manually match
14872cbed729Swyllys 			 * the labels to be sure we have a match.
14882cbed729Swyllys 			 */
14892cbed729Swyllys 			nick = PK11_GetPrivateKeyNickname(prinode->key);
14902cbed729Swyllys 			if (findLabel) {
14912cbed729Swyllys 				match = (nick &&
14922cbed729Swyllys 				    (strcmp(nick, findLabel) == 0));
14932cbed729Swyllys 			} else {
14942cbed729Swyllys 				/* always match if findLabel is NULL */
14952cbed729Swyllys 				match = 1;
14962cbed729Swyllys 			}
14972cbed729Swyllys 			if (keys != NULL && match) {
149830a5e8faSwyllys 				keys[count].kstype = KMF_KEYSTORE_NSS;
149930a5e8faSwyllys 				keys[count].keyclass = KMF_ASYM_PRI;
150030a5e8faSwyllys 				keys[count].keyp = (void *)prinode->key;
15012cbed729Swyllys 				keys[count].keylabel = nick;
150299ebb4caSwyllys 
150330a5e8faSwyllys 				if (prinode->key->keyType == rsaKey)
150430a5e8faSwyllys 					keys[count].keyalg = KMF_RSA;
150530a5e8faSwyllys 				else if (prinode->key->keyType == dsaKey)
150630a5e8faSwyllys 					keys[count].keyalg = KMF_DSA;
1507e65e5c2dSWyllys Ingersoll 				else if (prinode->key->keyType == ecKey)
1508e65e5c2dSWyllys Ingersoll 					keys[count].keyalg = KMF_ECDSA;
150930a5e8faSwyllys 			}
15102cbed729Swyllys 			if (match)
15112cbed729Swyllys 				count++;
151299ebb4caSwyllys 		}
151330a5e8faSwyllys 		*numkeys = count;
151430a5e8faSwyllys 	} else if (keyclass == KMF_SYMMETRIC) {
151530a5e8faSwyllys 		count = 0;
151630a5e8faSwyllys 		rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
151730a5e8faSwyllys 		    (void *)&keytype, NULL);
151830a5e8faSwyllys 		if (rv != KMF_OK)
151930a5e8faSwyllys 			rv = KMF_OK;
152030a5e8faSwyllys 		while (symlist && count < maxkeys) {
152130a5e8faSwyllys 			PK11SymKey *symkey = symlist;
152230a5e8faSwyllys 			CK_KEY_TYPE type;
152330a5e8faSwyllys 			KMF_KEY_ALG keyalg;
152499ebb4caSwyllys 
15252cbed729Swyllys 			match = 0;
152630a5e8faSwyllys 			type = PK11_GetSymKeyType(symkey);
152730a5e8faSwyllys 			keyalg = pk11keytype2kmf(type);
152899ebb4caSwyllys 
152930a5e8faSwyllys 			symlist = PK11_GetNextSymKey(symkey);
153099ebb4caSwyllys 
153130a5e8faSwyllys 			/*
153230a5e8faSwyllys 			 * If keytype is specified in the searching parameter,
153330a5e8faSwyllys 			 * check the keytype and skip the key if its keytype
153430a5e8faSwyllys 			 * doesn't match.
153530a5e8faSwyllys 			 */
153630a5e8faSwyllys 			if (keytype != KMF_KEYALG_NONE && keytype != keyalg) {
153730a5e8faSwyllys 				/* free that key since we arent using it */
153830a5e8faSwyllys 				PK11_FreeSymKey(symkey);
153930a5e8faSwyllys 				continue;
154099ebb4caSwyllys 			}
15412cbed729Swyllys 			/*
15422cbed729Swyllys 			 * Due to bug in NSS, we have to manually match
15432cbed729Swyllys 			 * the labels to be sure we have a match.
15442cbed729Swyllys 			 */
15452cbed729Swyllys 			nick = PK11_GetSymKeyNickname(symkey);
15462cbed729Swyllys 			if (findLabel) {
15472cbed729Swyllys 				match = (nick &&
15482cbed729Swyllys 				    (strcmp(nick, findLabel) == 0));
15492cbed729Swyllys 			} else {
15502cbed729Swyllys 				/* always match if findLabel is NULL */
15512cbed729Swyllys 				match = 1;
15522cbed729Swyllys 			}
155399ebb4caSwyllys 
15542cbed729Swyllys 			if (keys != NULL && match) {
155530a5e8faSwyllys 				keys[count].kstype = KMF_KEYSTORE_NSS;
155630a5e8faSwyllys 				keys[count].keyclass = KMF_SYMMETRIC;
155730a5e8faSwyllys 				keys[count].keyp = (void *) symkey;
15582cbed729Swyllys 				keys[count].keylabel = nick;
155930a5e8faSwyllys 				keys[count].keyalg = keyalg;
156030a5e8faSwyllys 			} else {
156130a5e8faSwyllys 				PK11_FreeSymKey(symkey);
156299ebb4caSwyllys 			}
15632cbed729Swyllys 			if (match)
15642cbed729Swyllys 				count++;
156599ebb4caSwyllys 		}
156630a5e8faSwyllys 		/*
156730a5e8faSwyllys 		 * Cleanup memory for unused keys.
156830a5e8faSwyllys 		 */
156930a5e8faSwyllys 		while (symlist != NULL) {
157030a5e8faSwyllys 			PK11SymKey *symkey = symlist;
157199ebb4caSwyllys 
157230a5e8faSwyllys 			PK11_FreeSymKey(symkey);
157330a5e8faSwyllys 			symlist = PK11_GetNextSymKey(symkey);
157499ebb4caSwyllys 		}
157530a5e8faSwyllys 		*numkeys = count;
157699ebb4caSwyllys 	}
157799ebb4caSwyllys 
157830a5e8faSwyllys cleanup:
157999ebb4caSwyllys 	if (nss_slot != NULL) {
158099ebb4caSwyllys 		PK11_FreeSlot(nss_slot);
158199ebb4caSwyllys 	}
158299ebb4caSwyllys 
158330a5e8faSwyllys 	return (rv);
158430a5e8faSwyllys }
158530a5e8faSwyllys 
158630a5e8faSwyllys static SECStatus
p12u_SwapUnicodeBytes(SECItem * uniItem)158730a5e8faSwyllys p12u_SwapUnicodeBytes(SECItem *uniItem)
158830a5e8faSwyllys {
158930a5e8faSwyllys 	unsigned int i;
159030a5e8faSwyllys 	unsigned char a;
159130a5e8faSwyllys 	if ((uniItem == NULL) || (uniItem->len % 2)) {
159230a5e8faSwyllys 		return (SECFailure);
159330a5e8faSwyllys 		}
159430a5e8faSwyllys 	for (i = 0; i < uniItem->len; i += 2) {
159530a5e8faSwyllys 		a = uniItem->data[i];
159630a5e8faSwyllys 		uniItem->data[i] = uniItem->data[i+1];
159730a5e8faSwyllys 		uniItem->data[i+1] = a;
159899ebb4caSwyllys 	}
159930a5e8faSwyllys 	return (SECSuccess);
160030a5e8faSwyllys }
160199ebb4caSwyllys 
160230a5e8faSwyllys 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)160330a5e8faSwyllys p12u_ucs2_ascii_conversion_function(
160430a5e8faSwyllys 	PRBool		toUnicode,
160530a5e8faSwyllys 	unsigned char	*inBuf,
160630a5e8faSwyllys 	unsigned int	inBufLen,
160730a5e8faSwyllys 	unsigned char	*outBuf,
160830a5e8faSwyllys 	unsigned int	maxOutBufLen,
160930a5e8faSwyllys 	unsigned int	*outBufLen,
161030a5e8faSwyllys 	PRBool		swapBytes)
161130a5e8faSwyllys {
16126b35cb3cSRichard PALO 	SECItem it = { siBuffer, NULL, 0 };
161330a5e8faSwyllys 	SECItem *dup = NULL;
161430a5e8faSwyllys 	PRBool ret;
161530a5e8faSwyllys 
161630a5e8faSwyllys 	it.data = inBuf;
161730a5e8faSwyllys 	it.len = inBufLen;
161830a5e8faSwyllys 	dup = SECITEM_DupItem(&it);
161930a5e8faSwyllys 	/*
162030a5e8faSwyllys 	 * If converting Unicode to ASCII, swap bytes before conversion
162130a5e8faSwyllys 	 * as neccessary.
162230a5e8faSwyllys 	 */
162330a5e8faSwyllys 	if (!toUnicode && swapBytes) {
162430a5e8faSwyllys 		if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
162530a5e8faSwyllys 			SECITEM_ZfreeItem(dup, PR_TRUE);
162630a5e8faSwyllys 			return (PR_FALSE);
162730a5e8faSwyllys 		}
162899ebb4caSwyllys 	}
162930a5e8faSwyllys 	/* Perform the conversion. */
163030a5e8faSwyllys 	ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
163130a5e8faSwyllys 	    outBuf, maxOutBufLen, outBufLen);
163230a5e8faSwyllys 	if (dup)
163330a5e8faSwyllys 		SECITEM_ZfreeItem(dup, PR_TRUE);
163499ebb4caSwyllys 
163530a5e8faSwyllys 	return (ret);
163630a5e8faSwyllys }
163730a5e8faSwyllys 
163830a5e8faSwyllys static PRBool
p12u_OpenFile(p12uContext * p12ctx,PRBool fileRead)163930a5e8faSwyllys p12u_OpenFile(p12uContext *p12ctx, PRBool fileRead)
164030a5e8faSwyllys {
164130a5e8faSwyllys 	if (!p12ctx || !p12ctx->filename) {
164230a5e8faSwyllys 		return (PR_FALSE);
164399ebb4caSwyllys 	}
164499ebb4caSwyllys 
164530a5e8faSwyllys 	if (fileRead) {
164630a5e8faSwyllys 		p12ctx->file = PR_Open(p12ctx->filename, PR_RDONLY, 0400);
164730a5e8faSwyllys 	} else {
164830a5e8faSwyllys 		p12ctx->file = PR_Open(p12ctx->filename,
164930a5e8faSwyllys 		    PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600);
165099ebb4caSwyllys 	}
165199ebb4caSwyllys 
165230a5e8faSwyllys 	if (!p12ctx->file) {
165330a5e8faSwyllys 		p12ctx->error = PR_TRUE;
165430a5e8faSwyllys 		return (PR_FALSE);
165530a5e8faSwyllys 	}
165630a5e8faSwyllys 
165730a5e8faSwyllys 	return (PR_TRUE);
165899ebb4caSwyllys }
165999ebb4caSwyllys 
166030a5e8faSwyllys static void
p12u_DestroyContext(p12uContext ** ppCtx,PRBool removeFile)166130a5e8faSwyllys p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
166230a5e8faSwyllys {
166330a5e8faSwyllys 	if (!ppCtx || !(*ppCtx)) {
166430a5e8faSwyllys 		return;
166530a5e8faSwyllys 	}
166699ebb4caSwyllys 
166730a5e8faSwyllys 	if ((*ppCtx)->file != NULL) {
16685ad42b1bSSurya Prakki 		(void) PR_Close((*ppCtx)->file);
166930a5e8faSwyllys 	}
167030a5e8faSwyllys 
167130a5e8faSwyllys 	if ((*ppCtx)->filename != NULL) {
167230a5e8faSwyllys 		if (removeFile) {
16735ad42b1bSSurya Prakki 			(void) PR_Delete((*ppCtx)->filename);
167430a5e8faSwyllys 		}
167530a5e8faSwyllys 		free((*ppCtx)->filename);
167630a5e8faSwyllys 	}
167730a5e8faSwyllys 
167830a5e8faSwyllys 	free(*ppCtx);
167930a5e8faSwyllys 	*ppCtx = NULL;
168030a5e8faSwyllys }
168130a5e8faSwyllys 
168230a5e8faSwyllys static p12uContext *
p12u_InitContext(PRBool fileImport,char * filename)168330a5e8faSwyllys p12u_InitContext(PRBool fileImport, char *filename)
168499ebb4caSwyllys {
168530a5e8faSwyllys 	p12uContext *p12ctx;
168699ebb4caSwyllys 
168730a5e8faSwyllys 	p12ctx = PORT_ZNew(p12uContext);
168830a5e8faSwyllys 	if (!p12ctx) {
168930a5e8faSwyllys 		return (NULL);
169099ebb4caSwyllys 	}
169199ebb4caSwyllys 
169230a5e8faSwyllys 	p12ctx->error = PR_FALSE;
169330a5e8faSwyllys 	p12ctx->errorValue = 0;
169430a5e8faSwyllys 	p12ctx->filename = strdup(filename);
169599ebb4caSwyllys 
169630a5e8faSwyllys 	if (!p12u_OpenFile(p12ctx, fileImport)) {
169730a5e8faSwyllys 		p12u_DestroyContext(&p12ctx, PR_FALSE);
169830a5e8faSwyllys 		return (NULL);
169999ebb4caSwyllys 	}
170099ebb4caSwyllys 
170130a5e8faSwyllys 	return (p12ctx);
170230a5e8faSwyllys }
170330a5e8faSwyllys 
170430a5e8faSwyllys static void
p12u_WriteToExportFile(void * arg,const char * buf,unsigned long len)170530a5e8faSwyllys p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
170630a5e8faSwyllys {
170730a5e8faSwyllys 	p12uContext *p12cxt = arg;
170830a5e8faSwyllys 	int writeLen;
170930a5e8faSwyllys 
171030a5e8faSwyllys 	if (!p12cxt || (p12cxt->error == PR_TRUE)) {
171130a5e8faSwyllys 		return;
171230a5e8faSwyllys 	}
171330a5e8faSwyllys 
171430a5e8faSwyllys 	if (p12cxt->file == NULL) {
171530a5e8faSwyllys 		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
171630a5e8faSwyllys 		p12cxt->error = PR_TRUE;
171730a5e8faSwyllys 		return;
171830a5e8faSwyllys 	}
171930a5e8faSwyllys 
172030a5e8faSwyllys 	writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
172130a5e8faSwyllys 
172230a5e8faSwyllys 	if (writeLen != (int)len) {
17235ad42b1bSSurya Prakki 		(void) PR_Close(p12cxt->file);
172430a5e8faSwyllys 		free(p12cxt->filename);
172530a5e8faSwyllys 		p12cxt->filename = NULL;
172630a5e8faSwyllys 		p12cxt->file = NULL;
172730a5e8faSwyllys 		p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
172830a5e8faSwyllys 		p12cxt->error = PR_TRUE;
172930a5e8faSwyllys 	}
173030a5e8faSwyllys }
173130a5e8faSwyllys 
173230a5e8faSwyllys #define	HANDLE_NSS_ERROR(r) {\
173330a5e8faSwyllys 	SET_ERROR(kmfh, PORT_GetError()); \
173430a5e8faSwyllys 	rv = r; \
173530a5e8faSwyllys 	goto out; }
173630a5e8faSwyllys 
173730a5e8faSwyllys static KMF_RETURN
add_cert_to_bag(SEC_PKCS12ExportContext * p12ecx,CERTCertificate * cert,SECItem * pwitem)173830a5e8faSwyllys add_cert_to_bag(SEC_PKCS12ExportContext *p12ecx,
173930a5e8faSwyllys 	CERTCertificate *cert, SECItem *pwitem)
174030a5e8faSwyllys {
174130a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
174230a5e8faSwyllys 	SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
174330a5e8faSwyllys 
174430a5e8faSwyllys 	keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
174530a5e8faSwyllys 	if (PK11_IsFIPS()) {
174630a5e8faSwyllys 		certSafe = keySafe;
174730a5e8faSwyllys 	} else {
174830a5e8faSwyllys 		certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
174930a5e8faSwyllys 		    SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
175030a5e8faSwyllys 	}
175130a5e8faSwyllys 
175230a5e8faSwyllys 	if (!certSafe || !keySafe) {
175330a5e8faSwyllys 		rv = KMF_ERR_INTERNAL;
175499ebb4caSwyllys 		goto out;
175599ebb4caSwyllys 	}
175699ebb4caSwyllys 
175730a5e8faSwyllys 	if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
175830a5e8faSwyllys 	    CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
175930a5e8faSwyllys 	    SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
176030a5e8faSwyllys 	    != SECSuccess) {
176130a5e8faSwyllys 		rv = KMF_ERR_INTERNAL;
176230a5e8faSwyllys 	}
176330a5e8faSwyllys out:
176430a5e8faSwyllys 	return (rv);
176530a5e8faSwyllys }
176630a5e8faSwyllys 
176730a5e8faSwyllys KMF_RETURN
NSS_ExportPK12(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)176830a5e8faSwyllys NSS_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
176930a5e8faSwyllys {
177030a5e8faSwyllys 	KMF_RETURN rv;
177130a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE  *)handle;
177230a5e8faSwyllys 	SEC_PKCS12ExportContext *p12ecx = NULL;
177330a5e8faSwyllys 	p12uContext *p12ctx = NULL;
177430a5e8faSwyllys 	CERTCertList *certlist = NULL;
177530a5e8faSwyllys 	CERTCertificate *nsscert = NULL;
177630a5e8faSwyllys 	CERTCertListNode* node = NULL;
177730a5e8faSwyllys 	PK11SlotInfo	*slot = NULL;
17786b35cb3cSRichard PALO 	SECItem pwitem = { siBuffer, NULL, 0 };
177930a5e8faSwyllys 	KMF_CREDENTIAL *cred = NULL;
178030a5e8faSwyllys 	KMF_CREDENTIAL *p12cred = NULL;
178130a5e8faSwyllys 	char *certlabel = NULL;
178230a5e8faSwyllys 	char *issuer = NULL;
178330a5e8faSwyllys 	char *subject = NULL;
178430a5e8faSwyllys 	KMF_BIGINT *serial = NULL;
178530a5e8faSwyllys 	char *filename = NULL;
178630a5e8faSwyllys 
178730a5e8faSwyllys 	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
178830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
178999ebb4caSwyllys 	}
179099ebb4caSwyllys 
179130a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &slot);
179230a5e8faSwyllys 	if (rv != KMF_OK)
179330a5e8faSwyllys 		return (rv);
179430a5e8faSwyllys 
179530a5e8faSwyllys 	cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
179630a5e8faSwyllys 	if (cred == NULL)
179730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
179830a5e8faSwyllys 
179930a5e8faSwyllys 	rv = nss_authenticate(handle, slot, cred);
180030a5e8faSwyllys 	if (rv != KMF_OK)
180130a5e8faSwyllys 		return (rv);
180230a5e8faSwyllys 
180330a5e8faSwyllys 	p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
180430a5e8faSwyllys 	if (p12cred  == NULL)
180530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
180630a5e8faSwyllys 
180730a5e8faSwyllys 	filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
180830a5e8faSwyllys 	    numattr);
180930a5e8faSwyllys 	if (filename == NULL)
181030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
181130a5e8faSwyllys 
181230a5e8faSwyllys 	/* Get optional search criteria attributes */
181330a5e8faSwyllys 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
181430a5e8faSwyllys 	issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
181530a5e8faSwyllys 	subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
181630a5e8faSwyllys 	serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
181730a5e8faSwyllys 
181830a5e8faSwyllys 	/*
181930a5e8faSwyllys 	 * Find the certificate(s) first.
182030a5e8faSwyllys 	 */
182130a5e8faSwyllys 	if (certlabel != NULL) {
182230a5e8faSwyllys 		nsscert = PK11_FindCertFromNickname(certlabel, NULL);
182330a5e8faSwyllys 		if (nsscert == NULL) {
182430a5e8faSwyllys 			HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND)
182530a5e8faSwyllys 		}
182630a5e8faSwyllys 	} else {
182730a5e8faSwyllys 		rv = nss_find_matching_certs(slot, issuer, subject, serial,
182830a5e8faSwyllys 		    &certlist, 0);
182930a5e8faSwyllys 
183030a5e8faSwyllys 		if (rv == KMF_OK && certlist == NULL) {
183130a5e8faSwyllys 			return (KMF_ERR_CERT_NOT_FOUND);
183230a5e8faSwyllys 		}
183330a5e8faSwyllys 		if (rv != KMF_OK)
183430a5e8faSwyllys 			return (rv);
183599ebb4caSwyllys 	}
183699ebb4caSwyllys 
183799ebb4caSwyllys 	/*
183830a5e8faSwyllys 	 * The KMF_CREDENTIAL holds the password to use for
183930a5e8faSwyllys 	 * encrypting the PKCS12 key information.
184099ebb4caSwyllys 	 */
184130a5e8faSwyllys 	pwitem.data = (uchar_t *)p12cred->cred;
184230a5e8faSwyllys 	pwitem.len = p12cred->credlen;
184399ebb4caSwyllys 
184430a5e8faSwyllys 	p12ctx = p12u_InitContext(PR_FALSE, filename);
184530a5e8faSwyllys 	if (!p12ctx) {
184630a5e8faSwyllys 		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
184730a5e8faSwyllys 	}
184899ebb4caSwyllys 
184930a5e8faSwyllys 	PORT_SetUCS2_ASCIIConversionFunction(
185030a5e8faSwyllys 	    p12u_ucs2_ascii_conversion_function);
185199ebb4caSwyllys 
185230a5e8faSwyllys 	p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, NULL);
185330a5e8faSwyllys 	if (!p12ecx) {
185430a5e8faSwyllys 		HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
185599ebb4caSwyllys 	}
185699ebb4caSwyllys 
185730a5e8faSwyllys 	if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
185830a5e8faSwyllys 	    != SECSuccess) {
185930a5e8faSwyllys 		HANDLE_NSS_ERROR(KMF_ERR_INTERNAL)
186099ebb4caSwyllys 	}
186199ebb4caSwyllys 
186230a5e8faSwyllys 	/*
186330a5e8faSwyllys 	 * NSS actually supports storing a list of keys and certs
186430a5e8faSwyllys 	 * in the PKCS#12 PDU.  Nice feature.
186530a5e8faSwyllys 	 */
186630a5e8faSwyllys 	if (certlist != NULL) {
186730a5e8faSwyllys 		for (node = CERT_LIST_HEAD(certlist);
186830a5e8faSwyllys 		    !CERT_LIST_END(node, certlist) && rv == KMF_OK;
186930a5e8faSwyllys 		    node = CERT_LIST_NEXT(node)) {
187030a5e8faSwyllys 			rv = add_cert_to_bag(p12ecx, node->cert, &pwitem);
187130a5e8faSwyllys 		}
187230a5e8faSwyllys 	} else if (nsscert != NULL) {
187330a5e8faSwyllys 		rv = add_cert_to_bag(p12ecx, nsscert, &pwitem);
187499ebb4caSwyllys 	}
187599ebb4caSwyllys 
187630a5e8faSwyllys 	if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx)
187730a5e8faSwyllys 	    != SECSuccess) {
187830a5e8faSwyllys 		HANDLE_NSS_ERROR(KMF_ERR_ENCODING)
187999ebb4caSwyllys 	}
188030a5e8faSwyllys out:
188130a5e8faSwyllys 	if (nsscert)
188230a5e8faSwyllys 		CERT_DestroyCertificate(nsscert);
188399ebb4caSwyllys 
188430a5e8faSwyllys 	if (certlist)
188530a5e8faSwyllys 		CERT_DestroyCertList(certlist);
188699ebb4caSwyllys 
188730a5e8faSwyllys 	if (p12ctx)
188830a5e8faSwyllys 		p12u_DestroyContext(&p12ctx, PR_FALSE);
188930a5e8faSwyllys 
189030a5e8faSwyllys 	if (p12ecx)
189130a5e8faSwyllys 		SEC_PKCS12DestroyExportContext(p12ecx);
189299ebb4caSwyllys 
189399ebb4caSwyllys 	return (rv);
189499ebb4caSwyllys }
189599ebb4caSwyllys 
189630a5e8faSwyllys #define	SETATTR(t, n, atype, value, size) \
189730a5e8faSwyllys 	t[n].type = atype; \
189830a5e8faSwyllys 	t[n].pValue = (CK_BYTE *)value; \
189930a5e8faSwyllys 	t[n].ulValueLen = (CK_ULONG)size;
190099ebb4caSwyllys 
190199ebb4caSwyllys KMF_RETURN
NSS_CreateSymKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)190230a5e8faSwyllys NSS_CreateSymKey(KMF_HANDLE_T handle,
190330a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
190499ebb4caSwyllys {
190599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
190699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
190799ebb4caSwyllys 	PK11SlotInfo *nss_slot = NULL;
190830a5e8faSwyllys 	PK11SymKey *nsskey = NULL;
190930a5e8faSwyllys 	CK_MECHANISM_TYPE keyType;
191030a5e8faSwyllys 	SECStatus nssrv;
191130a5e8faSwyllys 	int keySize;
191230a5e8faSwyllys 	KMF_KEY_HANDLE *symkey;
191330a5e8faSwyllys 	KMF_CREDENTIAL cred;
191430a5e8faSwyllys 	uint32_t keylen;
191530a5e8faSwyllys 	uint32_t keylen_size = sizeof (uint32_t);
191630a5e8faSwyllys 	KMF_KEY_ALG keytype;
191730a5e8faSwyllys 	char *keylabel = NULL;
191830a5e8faSwyllys 
191930a5e8faSwyllys 	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
192030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
192130a5e8faSwyllys 	}
192299ebb4caSwyllys 
192330a5e8faSwyllys 	symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
192430a5e8faSwyllys 	if (symkey == NULL)
192530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
192630a5e8faSwyllys 
192730a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, (void *)&keytype,
192830a5e8faSwyllys 	    NULL);
192930a5e8faSwyllys 	if (rv != KMF_OK)
193030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
193130a5e8faSwyllys 
193230a5e8faSwyllys 	rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, &keylen,
193330a5e8faSwyllys 	    &keylen_size);
193430a5e8faSwyllys 	if (rv == KMF_ERR_ATTR_NOT_FOUND &&
193530a5e8faSwyllys 	    (keytype == KMF_DES || keytype == KMF_DES3))
193630a5e8faSwyllys 		/* keylength is not required for DES and 3DES */
193730a5e8faSwyllys 		rv = KMF_OK;
193830a5e8faSwyllys 	if (rv != KMF_OK)
193930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
194030a5e8faSwyllys 
194130a5e8faSwyllys 	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
194230a5e8faSwyllys 	if (keylabel == NULL)
194399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
194430a5e8faSwyllys 
194530a5e8faSwyllys 	switch (keytype) {
194630a5e8faSwyllys 	case KMF_AES:
194730a5e8faSwyllys 		keyType = CKM_AES_KEY_GEN;
194830a5e8faSwyllys 		keySize = keylen;
194930a5e8faSwyllys 		if (keySize == 0 || (keySize % 8) != 0)
195030a5e8faSwyllys 			return (KMF_ERR_BAD_KEY_SIZE);
195130a5e8faSwyllys 		break;
195230a5e8faSwyllys 	case KMF_RC4:
195330a5e8faSwyllys 		keyType = CKM_RC4_KEY_GEN;
195430a5e8faSwyllys 		keySize = keylen;
195530a5e8faSwyllys 		if (keySize == 0 || (keySize % 8) != 0)
195630a5e8faSwyllys 			return (KMF_ERR_BAD_KEY_SIZE);
195730a5e8faSwyllys 		break;
195830a5e8faSwyllys 	case KMF_DES:
195930a5e8faSwyllys 		keyType = CKM_DES_KEY_GEN;
196030a5e8faSwyllys 		keySize = 0; /* required by PK11_TokenKeyGen()  */
196130a5e8faSwyllys 		break;
196230a5e8faSwyllys 	case KMF_DES3:
196330a5e8faSwyllys 		keyType = CKM_DES3_KEY_GEN;
196430a5e8faSwyllys 		keySize = 0; /* required by PK11_TokenKeyGen() */
196530a5e8faSwyllys 		break;
196630a5e8faSwyllys 	case KMF_GENERIC_SECRET:
196730a5e8faSwyllys 		keyType = CKM_GENERIC_SECRET_KEY_GEN;
196830a5e8faSwyllys 		keySize = keylen;
196930a5e8faSwyllys 		if (keySize == 0 || (keySize % 8) != 0)
197030a5e8faSwyllys 			return (KMF_ERR_BAD_KEY_SIZE);
197130a5e8faSwyllys 		break;
197230a5e8faSwyllys 	default:
197330a5e8faSwyllys 		rv = KMF_ERR_BAD_KEY_TYPE;
197430a5e8faSwyllys 		goto out;
197599ebb4caSwyllys 	}
197699ebb4caSwyllys 
197730a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
197899ebb4caSwyllys 	if (rv != KMF_OK) {
197999ebb4caSwyllys 		return (rv);
198099ebb4caSwyllys 	}
198199ebb4caSwyllys 
198230a5e8faSwyllys 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
198330a5e8faSwyllys 	    (void *)&cred, NULL);
198430a5e8faSwyllys 	if (rv != KMF_OK)
198530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
19865363b112Shylee 
198730a5e8faSwyllys 	rv = nss_authenticate(handle, nss_slot, &cred);
198830a5e8faSwyllys 	if (rv != KMF_OK) {
198930a5e8faSwyllys 		return (rv);
19905363b112Shylee 	}
19915363b112Shylee 
1992ab8b4e5cSWyllys Ingersoll 	/* convert key length to bytes */
1993ab8b4e5cSWyllys Ingersoll 	nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize / 8,  NULL,
199430a5e8faSwyllys 	    PR_TRUE, (void *)cred.cred);
199530a5e8faSwyllys 	if (nsskey == NULL) {
199699ebb4caSwyllys 		SET_ERROR(kmfh, PORT_GetError());
199730a5e8faSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
199899ebb4caSwyllys 		goto out;
199999ebb4caSwyllys 	}
200099ebb4caSwyllys 
200130a5e8faSwyllys 	nssrv = PK11_SetSymKeyNickname(nsskey, keylabel);
200230a5e8faSwyllys 	if (nssrv != SECSuccess) {
200399ebb4caSwyllys 		SET_ERROR(kmfh, PORT_GetError());
200430a5e8faSwyllys 		rv = KMF_ERR_KEYGEN_FAILED;
200599ebb4caSwyllys 		goto out;
200699ebb4caSwyllys 	}
200799ebb4caSwyllys 
200830a5e8faSwyllys 	symkey->kstype = KMF_KEYSTORE_NSS;
200930a5e8faSwyllys 	symkey->keyalg = keytype;
201030a5e8faSwyllys 	symkey->keyclass = KMF_SYMMETRIC;
201130a5e8faSwyllys 	symkey->israw = FALSE;
201230a5e8faSwyllys 	symkey->keyp = (void *)nsskey;
201399ebb4caSwyllys 
201499ebb4caSwyllys out:
201530a5e8faSwyllys 	if (nss_slot != NULL)
201699ebb4caSwyllys 		PK11_FreeSlot(nss_slot);
201799ebb4caSwyllys 
201830a5e8faSwyllys 	if (rv != KMF_OK && nsskey != NULL) {
20195ad42b1bSSurya Prakki 		(void) PK11_DeleteTokenSymKey(nsskey);
202030a5e8faSwyllys 		PK11_FreeSymKey(nsskey);
202199ebb4caSwyllys 	}
202230a5e8faSwyllys 	return (rv);
202330a5e8faSwyllys }
202499ebb4caSwyllys 
202530a5e8faSwyllys KMF_RETURN
NSS_GetSymKeyValue(KMF_HANDLE_T handle,KMF_KEY_HANDLE * symkey,KMF_RAW_SYM_KEY * rkey)202630a5e8faSwyllys NSS_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
202730a5e8faSwyllys 	KMF_RAW_SYM_KEY *rkey)
202830a5e8faSwyllys {
202930a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
203030a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
203130a5e8faSwyllys 	SECItem *value = NULL;
203230a5e8faSwyllys 	PK11SymKey *nsskey;
203330a5e8faSwyllys 	SECStatus nss_rv;
203430a5e8faSwyllys 
203530a5e8faSwyllys 	if (kmfh == NULL)
203630a5e8faSwyllys 		return (KMF_ERR_UNINITIALIZED);
203730a5e8faSwyllys 
203830a5e8faSwyllys 	if (symkey == NULL || rkey == NULL)
203930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
204030a5e8faSwyllys 	else if (symkey->keyclass != KMF_SYMMETRIC)
204130a5e8faSwyllys 		return (KMF_ERR_BAD_KEY_CLASS);
204230a5e8faSwyllys 
204330a5e8faSwyllys 	if (symkey->israw) {
204430a5e8faSwyllys 		KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
204530a5e8faSwyllys 
204630a5e8faSwyllys 		if (rawkey == NULL ||
204730a5e8faSwyllys 		    rawkey->rawdata.sym.keydata.val == NULL ||
204830a5e8faSwyllys 		    rawkey->rawdata.sym.keydata.len == 0)
204930a5e8faSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
205030a5e8faSwyllys 
205130a5e8faSwyllys 		rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
205230a5e8faSwyllys 		if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
205330a5e8faSwyllys 			return (KMF_ERR_MEMORY);
205430a5e8faSwyllys 		(void) memcpy(rkey->keydata.val,
205530a5e8faSwyllys 		    rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
205630a5e8faSwyllys 	} else {
205730a5e8faSwyllys 		nsskey = (PK11SymKey *)(symkey->keyp);
205830a5e8faSwyllys 		if (nsskey == NULL)
205930a5e8faSwyllys 			return (KMF_ERR_BAD_KEYHANDLE);
206030a5e8faSwyllys 
206130a5e8faSwyllys 		nss_rv = PK11_ExtractKeyValue(nsskey);
206230a5e8faSwyllys 		if (nss_rv != SECSuccess) {
206330a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
206430a5e8faSwyllys 			rv = KMF_ERR_GETKEYVALUE_FAILED;
206530a5e8faSwyllys 			goto out;
206630a5e8faSwyllys 		}
206730a5e8faSwyllys 
206830a5e8faSwyllys 		value = PK11_GetKeyData(nsskey);
206930a5e8faSwyllys 		if (value == NULL) {
207030a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
207130a5e8faSwyllys 			rv = KMF_ERR_GETKEYVALUE_FAILED;
207230a5e8faSwyllys 			goto out;
207330a5e8faSwyllys 		}
207430a5e8faSwyllys 
207530a5e8faSwyllys 		if (value->len == 0 || value->data == NULL) {
207630a5e8faSwyllys 			rv = KMF_ERR_GETKEYVALUE_FAILED;
207730a5e8faSwyllys 			goto out;
207830a5e8faSwyllys 		}
207930a5e8faSwyllys 
208030a5e8faSwyllys 		rkey->keydata.val = malloc(value->len);
208130a5e8faSwyllys 		if (rkey->keydata.val == NULL) {
208230a5e8faSwyllys 			rv = KMF_ERR_MEMORY;
208330a5e8faSwyllys 			goto out;
208430a5e8faSwyllys 		}
208530a5e8faSwyllys 		(void) memcpy(rkey->keydata.val, value->data, value->len);
208630a5e8faSwyllys 		rkey->keydata.len = value->len;
208730a5e8faSwyllys 		(void) memset(value->data, 0, value->len);
208899ebb4caSwyllys 	}
208930a5e8faSwyllys out:
209030a5e8faSwyllys 	if (value != NULL)
209130a5e8faSwyllys 		SECITEM_FreeItem(value, PR_TRUE);
209299ebb4caSwyllys 	return (rv);
209399ebb4caSwyllys }
209499ebb4caSwyllys 
209599ebb4caSwyllys KMF_RETURN
NSS_SetTokenPin(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)209630a5e8faSwyllys NSS_SetTokenPin(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
209799ebb4caSwyllys {
209899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
209999ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
210030a5e8faSwyllys 	int rv;
210130a5e8faSwyllys 	PK11SlotInfo *nss_slot = NULL;
210230a5e8faSwyllys 	KMF_CREDENTIAL oldcred, newcred;
210399ebb4caSwyllys 
210430a5e8faSwyllys 	if (handle == NULL || attrlist == NULL || numattr == 0)
210530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
210699ebb4caSwyllys 
210730a5e8faSwyllys 	ret = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
210830a5e8faSwyllys 	    (void *)&oldcred, NULL);
210930a5e8faSwyllys 	if (ret != KMF_OK)
211030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
211130a5e8faSwyllys 	ret = kmf_get_attr(KMF_NEWPIN_ATTR, attrlist, numattr,
211230a5e8faSwyllys 	    (void *)&newcred, NULL);
211330a5e8faSwyllys 	if (ret != KMF_OK)
211430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
211530a5e8faSwyllys 
211630a5e8faSwyllys 	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
211730a5e8faSwyllys 	/* If it was uninitialized, set it */
211830a5e8faSwyllys 	if (ret == KMF_ERR_UNINITIALIZED_TOKEN) {
211930a5e8faSwyllys 		rv = PK11_InitPin(nss_slot, NULL, newcred.cred);
212030a5e8faSwyllys 		if (rv != SECSuccess) {
212130a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
212230a5e8faSwyllys 			ret = KMF_ERR_AUTH_FAILED;
212330a5e8faSwyllys 		} else {
212430a5e8faSwyllys 			ret = KMF_OK;
212530a5e8faSwyllys 		}
212630a5e8faSwyllys 	} else if (ret == KMF_OK) {
212730a5e8faSwyllys 		ret = nss_authenticate(handle, nss_slot, &oldcred);
212830a5e8faSwyllys 		if (ret != KMF_OK) {
212930a5e8faSwyllys 			return (ret);
213030a5e8faSwyllys 		}
213130a5e8faSwyllys 		rv = PK11_ChangePW(nss_slot, oldcred.cred, newcred.cred);
213230a5e8faSwyllys 		if (rv != SECSuccess) {
213330a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
213430a5e8faSwyllys 			ret = KMF_ERR_AUTH_FAILED;
213530a5e8faSwyllys 		}
213699ebb4caSwyllys 	}
213799ebb4caSwyllys 
213899ebb4caSwyllys 	return (ret);
213999ebb4caSwyllys }
214099ebb4caSwyllys 
214199ebb4caSwyllys KMF_RETURN
NSS_StoreKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)214230a5e8faSwyllys NSS_StoreKey(KMF_HANDLE_T handle,
214330a5e8faSwyllys 	int numattr, KMF_ATTRIBUTE *attrlist)
214499ebb4caSwyllys {
214599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
214699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
214730a5e8faSwyllys 	PK11SlotInfo *nss_slot = NULL;
21486b35cb3cSRichard PALO 	KMF_CREDENTIAL cred = { NULL, 0 };
214930a5e8faSwyllys 	KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
215030a5e8faSwyllys 	KMF_RAW_KEY_DATA *rawkey = NULL;
215130a5e8faSwyllys 	char *keylabel = NULL;
215230a5e8faSwyllys 	SECStatus ckrv = SECSuccess;
21536b35cb3cSRichard PALO 	SECItem nickname = { siBuffer, NULL, 0 };
215430a5e8faSwyllys 	CERTCertificate *nss_cert = NULL;
215599ebb4caSwyllys 
215630a5e8faSwyllys 	if (kmfh == NULL || attrlist == NULL || numattr == 0) {
215730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
215899ebb4caSwyllys 	}
215999ebb4caSwyllys 
216030a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
216199ebb4caSwyllys 	if (rv != KMF_OK) {
216299ebb4caSwyllys 		return (rv);
216399ebb4caSwyllys 	}
216499ebb4caSwyllys 
216530a5e8faSwyllys 	rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
216630a5e8faSwyllys 	    (void *)&cred, NULL);
216730a5e8faSwyllys 	if (rv != KMF_OK)
216899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
216999ebb4caSwyllys 
217030a5e8faSwyllys 	rv = nss_authenticate(handle, nss_slot, &cred);
217130a5e8faSwyllys 	if (rv != KMF_OK) {
217230a5e8faSwyllys 		return (rv);
217399ebb4caSwyllys 	}
217499ebb4caSwyllys 
217530a5e8faSwyllys 	pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
217630a5e8faSwyllys 	if (pubkey == NULL) {
217730a5e8faSwyllys 		/* look for private key */
217830a5e8faSwyllys 		prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist,
217930a5e8faSwyllys 		    numattr);
218030a5e8faSwyllys 		if (prikey == NULL)
218130a5e8faSwyllys 			/* look for raw key */
218230a5e8faSwyllys 			rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR,
218330a5e8faSwyllys 			    attrlist, numattr);
218499ebb4caSwyllys 	}
218599ebb4caSwyllys 
218630a5e8faSwyllys 	/* If no keys were found, return error */
218730a5e8faSwyllys 	if (pubkey == NULL && prikey == NULL && rawkey == NULL)
218830a5e8faSwyllys 		return (KMF_ERR_ATTR_NOT_FOUND);
218999ebb4caSwyllys 
219030a5e8faSwyllys 	keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
219130a5e8faSwyllys 	if (keylabel != NULL) {
219230a5e8faSwyllys 		nickname.data = (uchar_t *)keylabel;
219330a5e8faSwyllys 		nickname.len = strlen(keylabel);
219499ebb4caSwyllys 	}
219599ebb4caSwyllys 
219630a5e8faSwyllys 	if (rawkey != NULL) {
219730a5e8faSwyllys 		uchar_t ver = 0;
219830a5e8faSwyllys 		SECKEYPrivateKeyInfo rpk;
21996b35cb3cSRichard PALO 		KMF_DATA derkey = { 0, NULL };
220030a5e8faSwyllys 		KMF_DATA *cert;
220199ebb4caSwyllys 
220230a5e8faSwyllys 		cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
220330a5e8faSwyllys 		if (cert == NULL)
220430a5e8faSwyllys 			return (rv);
220530a5e8faSwyllys 		/*
220630a5e8faSwyllys 		 * Decode the cert into an NSS CERT object so we can access the
220730a5e8faSwyllys 		 * SPKI and KeyUsage data later.
220830a5e8faSwyllys 		 */
220930a5e8faSwyllys 		nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
221030a5e8faSwyllys 		    cert->Length);
2211f482c776Swyllys 
221230a5e8faSwyllys 		if (nss_cert == NULL) {
221330a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
221430a5e8faSwyllys 			rv = KMF_ERR_BAD_CERT_FORMAT;
221599ebb4caSwyllys 			goto cleanup;
221699ebb4caSwyllys 		}
221799ebb4caSwyllys 
221830a5e8faSwyllys 		(void) memset(&rpk, 0, sizeof (rpk));
221930a5e8faSwyllys 		rpk.arena = NULL;
222030a5e8faSwyllys 		rpk.version.type = siUnsignedInteger;
222130a5e8faSwyllys 		rpk.version.data = &ver;
222230a5e8faSwyllys 		rpk.version.len = 1;
222330a5e8faSwyllys 		if (rawkey->keytype == KMF_RSA) {
222430a5e8faSwyllys 			rv = DerEncodeRSAPrivateKey(&derkey,
222530a5e8faSwyllys 			    &rawkey->rawdata.rsa);
222630a5e8faSwyllys 			if (rv != KMF_OK)
222730a5e8faSwyllys 				goto cleanup;
222830a5e8faSwyllys 		} else if (rawkey->keytype == KMF_DSA) {
222930a5e8faSwyllys 			rv = DerEncodeDSAPrivateKey(&derkey,
223030a5e8faSwyllys 			    &rawkey->rawdata.dsa);
223130a5e8faSwyllys 			if (rv != KMF_OK)
223230a5e8faSwyllys 				goto cleanup;
2233e65e5c2dSWyllys Ingersoll 		} else if (rawkey->keytype == KMF_ECDSA) {
2234e65e5c2dSWyllys Ingersoll 			rv = DerEncodeECPrivateKey(&derkey,
2235e65e5c2dSWyllys Ingersoll 			    &rawkey->rawdata.ec);
2236e65e5c2dSWyllys Ingersoll 			if (rv != KMF_OK)
2237e65e5c2dSWyllys Ingersoll 				goto cleanup;
223830a5e8faSwyllys 		}
223930a5e8faSwyllys 		rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
224030a5e8faSwyllys 		rpk.privateKey.data = derkey.Data;
224130a5e8faSwyllys 		rpk.privateKey.len = derkey.Length;
224230a5e8faSwyllys 		rpk.attributes = NULL;
224399ebb4caSwyllys 
224430a5e8faSwyllys 		ckrv = PK11_ImportPrivateKeyInfo(nss_slot, &rpk, &nickname,
224530a5e8faSwyllys 		    &nss_cert->subjectPublicKeyInfo.subjectPublicKey, TRUE,
224630a5e8faSwyllys 		    TRUE, nss_cert->keyUsage, NULL);
224730a5e8faSwyllys 		if (ckrv != CKR_OK) {
224830a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
224930a5e8faSwyllys 			rv = KMF_ERR_INTERNAL;
225099ebb4caSwyllys 		}
225130a5e8faSwyllys 		kmf_free_data(&derkey);
225230a5e8faSwyllys 	} else if (pubkey != NULL && pubkey->kstype == KMF_KEYSTORE_NSS) {
225330a5e8faSwyllys 		CK_OBJECT_HANDLE pk;
225430a5e8faSwyllys 		SECKEYPublicKey *publicKey = (SECKEYPublicKey *) pubkey->keyp;
225599ebb4caSwyllys 
225630a5e8faSwyllys 		pk = PK11_ImportPublicKey(nss_slot, publicKey, PR_TRUE);
225730a5e8faSwyllys 		if (pk == CK_INVALID_HANDLE) {
225830a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
225930a5e8faSwyllys 			rv = KMF_ERR_INTERNAL;
226099ebb4caSwyllys 		}
226130a5e8faSwyllys 	} else if (prikey != NULL && prikey->kstype == KMF_KEYSTORE_NSS) {
226230a5e8faSwyllys 		SECKEYPrivateKey *pk;
226330a5e8faSwyllys 		SECKEYPrivateKey *privKey = (SECKEYPrivateKey *) prikey->keyp;
226499ebb4caSwyllys 
226530a5e8faSwyllys 		pk = PK11_LoadPrivKey(nss_slot, privKey, NULL, PR_TRUE,
226630a5e8faSwyllys 		    PR_TRUE);
226730a5e8faSwyllys 		if (pk == CK_INVALID_HANDLE) {
226830a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
226930a5e8faSwyllys 			rv = KMF_ERR_INTERNAL;
227030a5e8faSwyllys 		}
227130a5e8faSwyllys 		/* We stored it, but don't need the handle anymore */
227230a5e8faSwyllys 		SECKEY_DestroyPrivateKey(pk);
227330a5e8faSwyllys 	}
227499ebb4caSwyllys 
227530a5e8faSwyllys cleanup:
227630a5e8faSwyllys 	if (nss_cert != NULL)
227730a5e8faSwyllys 		CERT_DestroyCertificate(nss_cert);
227830a5e8faSwyllys 	PK11_FreeSlot(nss_slot);
227930a5e8faSwyllys 	return (rv);
228030a5e8faSwyllys }
228199ebb4caSwyllys 
228230a5e8faSwyllys /*
228330a5e8faSwyllys  * This function is called by NSS_StoreCert() and NSS_ImportCert().
228430a5e8faSwyllys  * The "label" and "trust_flag" arguments can be NULL.
228530a5e8faSwyllys  */
228630a5e8faSwyllys static KMF_RETURN
store_cert(KMF_HANDLE_T handle,PK11SlotInfo * nss_slot,KMF_DATA * cert,char * label,char * trust_flag)228730a5e8faSwyllys store_cert(KMF_HANDLE_T handle, PK11SlotInfo *nss_slot, KMF_DATA *cert,
228830a5e8faSwyllys     char *label, char *trust_flag)
228930a5e8faSwyllys {
229030a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
229130a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
229230a5e8faSwyllys 	SECStatus nss_rv;
229330a5e8faSwyllys 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
229430a5e8faSwyllys 	CERTCertificate *nss_cert = NULL;
229530a5e8faSwyllys 	CERTCertTrust *nss_trust = NULL;
229630a5e8faSwyllys 
229730a5e8faSwyllys 	if (nss_slot == NULL || cert == NULL)
229830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
229930a5e8faSwyllys 
230030a5e8faSwyllys 	nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
230130a5e8faSwyllys 	    cert->Length);
230230a5e8faSwyllys 	if (nss_cert == NULL) {
230330a5e8faSwyllys 		SET_ERROR(kmfh, PORT_GetError());
230430a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
230530a5e8faSwyllys 		goto out;
230699ebb4caSwyllys 	}
230799ebb4caSwyllys 
230830a5e8faSwyllys 	/* Store the cert into the NSS database */
230930a5e8faSwyllys 	nss_rv = PK11_ImportCert(nss_slot, nss_cert, CK_INVALID_HANDLE,
231030a5e8faSwyllys 	    label, 0);
231130a5e8faSwyllys 	if (nss_rv) {
231230a5e8faSwyllys 		SET_ERROR(kmfh, nss_rv);
231330a5e8faSwyllys 		ret = KMF_ERR_BAD_CERT_FORMAT;
231430a5e8faSwyllys 		goto out;
231599ebb4caSwyllys 	}
231699ebb4caSwyllys 
231730a5e8faSwyllys 	/* If trust_flag is NULL, then we are done */
231830a5e8faSwyllys 	if (trust_flag == NULL)
231930a5e8faSwyllys 		goto out;
232099ebb4caSwyllys 
232130a5e8faSwyllys 	nss_trust = (CERTCertTrust *) malloc(sizeof (CERTCertTrust));
232230a5e8faSwyllys 	if (nss_trust == NULL) {
232330a5e8faSwyllys 		ret = KMF_ERR_MEMORY;
232430a5e8faSwyllys 		goto out;
232599ebb4caSwyllys 	}
232699ebb4caSwyllys 
232730a5e8faSwyllys 	nss_rv = CERT_DecodeTrustString(nss_trust, trust_flag);
232830a5e8faSwyllys 	if (nss_rv) {
232930a5e8faSwyllys 		SET_ERROR(kmfh, nss_rv);
233030a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
233130a5e8faSwyllys 		goto out;
233230a5e8faSwyllys 	}
233399ebb4caSwyllys 
233430a5e8faSwyllys 	nss_rv = CERT_ChangeCertTrust(certHandle, nss_cert, nss_trust);
233530a5e8faSwyllys 	if (nss_rv) {
233630a5e8faSwyllys 		SET_ERROR(kmfh, nss_rv);
233730a5e8faSwyllys 		ret = KMF_ERR_BAD_PARAMETER;
233830a5e8faSwyllys 	}
233930a5e8faSwyllys 
234030a5e8faSwyllys out:
234130a5e8faSwyllys 	if (nss_cert != NULL) {
234230a5e8faSwyllys 		CERT_DestroyCertificate(nss_cert);
234330a5e8faSwyllys 	}
234430a5e8faSwyllys 
234530a5e8faSwyllys 	if (nss_trust != NULL) {
234630a5e8faSwyllys 		free(nss_trust);
234799ebb4caSwyllys 	}
234899ebb4caSwyllys 
234999ebb4caSwyllys 	return (ret);
235099ebb4caSwyllys }
235199ebb4caSwyllys 
235230a5e8faSwyllys 
235330a5e8faSwyllys KMF_RETURN
NSS_StoreCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)235430a5e8faSwyllys NSS_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
235599ebb4caSwyllys {
235630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
235730a5e8faSwyllys 	PK11SlotInfo *nss_slot = NULL;
235830a5e8faSwyllys 	KMF_DATA *cert = NULL;
235930a5e8faSwyllys 	char *label = NULL;
236030a5e8faSwyllys 	char *trust_flag = NULL;
236199ebb4caSwyllys 
236230a5e8faSwyllys 	if (handle == NULL || attrlist == NULL || numattr == 0) {
236330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
236499ebb4caSwyllys 	}
236599ebb4caSwyllys 
236630a5e8faSwyllys 	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
236730a5e8faSwyllys 	if (ret != KMF_OK)
236830a5e8faSwyllys 		return (ret);
236930a5e8faSwyllys 
237030a5e8faSwyllys 	/* Get the cert data  */
237130a5e8faSwyllys 	cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
237230a5e8faSwyllys 	if (cert == NULL || cert->Data == NULL)
237330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
237430a5e8faSwyllys 
237530a5e8faSwyllys 	/* The label attribute is optional */
237630a5e8faSwyllys 	label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
237730a5e8faSwyllys 
237830a5e8faSwyllys 	/* The trustflag attriburte is optional */
237930a5e8faSwyllys 	trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
238030a5e8faSwyllys 
238130a5e8faSwyllys 	ret = store_cert(handle, nss_slot, cert, label, trust_flag);
238230a5e8faSwyllys 
238330a5e8faSwyllys out:
238430a5e8faSwyllys 	if (nss_slot != NULL) {
238530a5e8faSwyllys 		PK11_FreeSlot(nss_slot);
238699ebb4caSwyllys 	}
238799ebb4caSwyllys 
238830a5e8faSwyllys 	return (ret);
238999ebb4caSwyllys }
239099ebb4caSwyllys 
239130a5e8faSwyllys 
239230a5e8faSwyllys KMF_RETURN
NSS_ImportCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)239330a5e8faSwyllys NSS_ImportCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
239499ebb4caSwyllys {
239530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
239630a5e8faSwyllys 	PK11SlotInfo *nss_slot = NULL;
23976b35cb3cSRichard PALO 	KMF_DATA cert = { 0, NULL };
23986b35cb3cSRichard PALO 	KMF_DATA cert_der = { 0, NULL };
239930a5e8faSwyllys 	KMF_DATA *cptr = NULL;
240030a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
240130a5e8faSwyllys 	char *label = NULL;
240230a5e8faSwyllys 	char *trust_flag = NULL;
240330a5e8faSwyllys 	char *certfile = NULL;
240430a5e8faSwyllys 
240530a5e8faSwyllys 	if (handle == NULL || attrlist == NULL || numattr == 0) {
240630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
240799ebb4caSwyllys 	}
240899ebb4caSwyllys 
240930a5e8faSwyllys 	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
241030a5e8faSwyllys 	if (ret != KMF_OK)
241130a5e8faSwyllys 		return (ret);
241230a5e8faSwyllys 
241330a5e8faSwyllys 	/* Get the input cert filename attribute */
241430a5e8faSwyllys 	certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
241530a5e8faSwyllys 	if (certfile == NULL)
241630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
241730a5e8faSwyllys 
241830a5e8faSwyllys 	/* Check the cert file and auto-detect the file format of it. */
241930a5e8faSwyllys 	ret = kmf_is_cert_file(handle, certfile, &format);
242030a5e8faSwyllys 	if (ret != KMF_OK)
242130a5e8faSwyllys 		return (ret);
242230a5e8faSwyllys 
242330a5e8faSwyllys 	ret = kmf_read_input_file(handle, certfile, &cert);
242430a5e8faSwyllys 	if (ret != KMF_OK) {
242530a5e8faSwyllys 		return (ret);
242699ebb4caSwyllys 	}
242799ebb4caSwyllys 
242830a5e8faSwyllys 	/*
242930a5e8faSwyllys 	 * If the imported cert is in PEM format, convert it to
243030a5e8faSwyllys 	 * DER format in order to store it in NSS token.
243130a5e8faSwyllys 	 */
243230a5e8faSwyllys 	if (format == KMF_FORMAT_PEM) {
243330a5e8faSwyllys 		int derlen;
243430a5e8faSwyllys 		ret = kmf_pem_to_der(cert.Data, cert.Length,
243530a5e8faSwyllys 		    &cert_der.Data, &derlen);
243630a5e8faSwyllys 		if (ret != KMF_OK) {
243730a5e8faSwyllys 			goto cleanup;
243899ebb4caSwyllys 		}
243930a5e8faSwyllys 		cert_der.Length = (size_t)derlen;
244030a5e8faSwyllys 		cptr = &cert_der;
244130a5e8faSwyllys 	} else {
244230a5e8faSwyllys 		cptr = &cert;
244399ebb4caSwyllys 	}
244499ebb4caSwyllys 
244530a5e8faSwyllys 	label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
244630a5e8faSwyllys 	trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
244730a5e8faSwyllys 	ret = store_cert(handle, nss_slot, cptr, label, trust_flag);
244830a5e8faSwyllys 
244930a5e8faSwyllys cleanup:
245030a5e8faSwyllys 	if (format == KMF_FORMAT_PEM) {
245130a5e8faSwyllys 		kmf_free_data(&cert_der);
245230a5e8faSwyllys 	}
245330a5e8faSwyllys 
245430a5e8faSwyllys 	kmf_free_data(&cert);
245530a5e8faSwyllys 
245630a5e8faSwyllys 	return (ret);
245799ebb4caSwyllys }
245899ebb4caSwyllys 
245930a5e8faSwyllys 
246030a5e8faSwyllys KMF_RETURN
NSS_ImportCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)246130a5e8faSwyllys NSS_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
246299ebb4caSwyllys {
246330a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
246430a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
246530a5e8faSwyllys 	PK11SlotInfo *nss_slot = NULL;
246630a5e8faSwyllys 	CERTSignedCrl *nss_crl = NULL;
246730a5e8faSwyllys 	KMF_ENCODE_FORMAT format;
246830a5e8faSwyllys 	int importOptions;
246930a5e8faSwyllys 	SECItem crlDER;
247030a5e8faSwyllys 	KMF_DATA crl1;
247130a5e8faSwyllys 	KMF_DATA crl2;
247230a5e8faSwyllys 	char *crlfilename;
247330a5e8faSwyllys 	boolean_t crlcheck = FALSE;
247499ebb4caSwyllys 
247530a5e8faSwyllys 	if (attrlist == NULL || numattr == 0) {
247630a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
247799ebb4caSwyllys 	}
247899ebb4caSwyllys 
247930a5e8faSwyllys 	ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
248030a5e8faSwyllys 	if (ret != KMF_OK) {
248130a5e8faSwyllys 		return (ret);
248299ebb4caSwyllys 	}
248399ebb4caSwyllys 
248430a5e8faSwyllys 	crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist,
248530a5e8faSwyllys 	    numattr);
248630a5e8faSwyllys 	if (crlfilename == NULL)
248730a5e8faSwyllys 		return (KMF_ERR_BAD_CRLFILE);
248899ebb4caSwyllys 
248930a5e8faSwyllys 	/*
249030a5e8faSwyllys 	 * Check if the input CRL file is a valid CRL file and auto-detect
249130a5e8faSwyllys 	 * the encoded format of the file.
249230a5e8faSwyllys 	 */
249330a5e8faSwyllys 	ret = kmf_is_crl_file(handle, crlfilename, &format);
249430a5e8faSwyllys 	if (ret != KMF_OK)
249530a5e8faSwyllys 		return (ret);
249699ebb4caSwyllys 
249730a5e8faSwyllys 	ret = kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
249830a5e8faSwyllys 	    &crlcheck, NULL);
249930a5e8faSwyllys 	if (ret != KMF_OK)
250030a5e8faSwyllys 		ret = KMF_OK; /* CRL_CHECK is optional */
250130a5e8faSwyllys 
250230a5e8faSwyllys 	/* set importOptions */
250330a5e8faSwyllys 	if (crlcheck == B_FALSE) {
250430a5e8faSwyllys 		importOptions = CRL_IMPORT_DEFAULT_OPTIONS |
250530a5e8faSwyllys 		    CRL_IMPORT_BYPASS_CHECKS;
250630a5e8faSwyllys 	} else {
250730a5e8faSwyllys 		importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
250899ebb4caSwyllys 	}
250999ebb4caSwyllys 
251030a5e8faSwyllys 
251130a5e8faSwyllys 	/* Read in the CRL file */
251230a5e8faSwyllys 	crl1.Data = NULL;
251330a5e8faSwyllys 	crl2.Data = NULL;
251430a5e8faSwyllys 	ret = kmf_read_input_file(handle, crlfilename, &crl1);
251530a5e8faSwyllys 	if (ret != KMF_OK) {
251630a5e8faSwyllys 		return (ret);
251799ebb4caSwyllys 	}
251899ebb4caSwyllys 
251930a5e8faSwyllys 	/* If the input CRL is in PEM format, convert it to DER first. */
252030a5e8faSwyllys 	if (format == KMF_FORMAT_PEM) {
252130a5e8faSwyllys 		int len;
252230a5e8faSwyllys 		ret = kmf_pem_to_der(crl1.Data, crl1.Length,
252330a5e8faSwyllys 		    &crl2.Data, &len);
252430a5e8faSwyllys 		if (ret != KMF_OK) {
252530a5e8faSwyllys 			goto out;
252630a5e8faSwyllys 		}
252730a5e8faSwyllys 		crl2.Length = (size_t)len;
252830a5e8faSwyllys 	}
252999ebb4caSwyllys 
253030a5e8faSwyllys 	crlDER.data = format == KMF_FORMAT_ASN1 ? crl1.Data : crl2.Data;
253130a5e8faSwyllys 	crlDER.len = format == KMF_FORMAT_ASN1 ? crl1.Length : crl2.Length;
253230a5e8faSwyllys 
253330a5e8faSwyllys 	nss_crl = PK11_ImportCRL(nss_slot, &crlDER, NULL, SEC_CRL_TYPE,
253430a5e8faSwyllys 	    NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
253530a5e8faSwyllys 
253630a5e8faSwyllys 	if (nss_crl == NULL) {
253730a5e8faSwyllys 		SET_ERROR(kmfh, PORT_GetError());
253830a5e8faSwyllys 		ret = KMF_ERR_BAD_CRLFILE;
253930a5e8faSwyllys 		goto out;
254099ebb4caSwyllys 	}
254199ebb4caSwyllys 
254230a5e8faSwyllys out:
254330a5e8faSwyllys 	if (nss_slot != NULL) {
254430a5e8faSwyllys 		PK11_FreeSlot(nss_slot);
254530a5e8faSwyllys 	}
254699ebb4caSwyllys 
254730a5e8faSwyllys 	if (crl1.Data != NULL) {
254830a5e8faSwyllys 		free(crl1.Data);
254999ebb4caSwyllys 	}
255099ebb4caSwyllys 
255130a5e8faSwyllys 	if (crl2.Data != NULL) {
255230a5e8faSwyllys 		free(crl2.Data);
255399ebb4caSwyllys 	}
255499ebb4caSwyllys 
255530a5e8faSwyllys 	if (nss_crl != NULL) {
25565ad42b1bSSurya Prakki 		(void) SEC_DestroyCrl(nss_crl);
255799ebb4caSwyllys 	}
255830a5e8faSwyllys 
255930a5e8faSwyllys 	return (ret);
256099ebb4caSwyllys }
256199ebb4caSwyllys 
256299ebb4caSwyllys KMF_RETURN
NSS_DeleteCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)256330a5e8faSwyllys NSS_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
256499ebb4caSwyllys {
256530a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
256630a5e8faSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
256730a5e8faSwyllys 	CERTSignedCrl *crl = NULL;
256830a5e8faSwyllys 	CERTCertificate *cert = NULL;
256930a5e8faSwyllys 	PK11SlotInfo *nss_slot = NULL;
257030a5e8faSwyllys 	CERTCrlHeadNode *crlList = NULL;
257130a5e8faSwyllys 	CERTCrlNode *crlNode = NULL;
257230a5e8faSwyllys 	PRArenaPool *arena = NULL;
257330a5e8faSwyllys 	CERTName *name = NULL;
257430a5e8faSwyllys 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
257530a5e8faSwyllys 	char *issuername, *subjectname;
257699ebb4caSwyllys 
257730a5e8faSwyllys 	/* check params */
257830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
257930a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
258099ebb4caSwyllys 	}
258199ebb4caSwyllys 
258230a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
258399ebb4caSwyllys 	if (rv != KMF_OK) {
258499ebb4caSwyllys 		return (rv);
258599ebb4caSwyllys 	}
258699ebb4caSwyllys 
258730a5e8faSwyllys 	issuername = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist,
258830a5e8faSwyllys 	    numattr);
258930a5e8faSwyllys 	subjectname = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist,
259030a5e8faSwyllys 	    numattr);
259130a5e8faSwyllys 
259230a5e8faSwyllys 	/* Caller must specify issuer or subject but not both */
259330a5e8faSwyllys 	if ((issuername == NULL && subjectname == NULL) ||
259430a5e8faSwyllys 	    (issuername != NULL && subjectname != NULL))
259530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
259630a5e8faSwyllys 
259730a5e8faSwyllys 	/* Find the CRL based on the deletion criteria. */
259830a5e8faSwyllys 	if (issuername != NULL) {
259930a5e8faSwyllys 		/*
260030a5e8faSwyllys 		 * If the deletion is based on the issuer's certificate
260130a5e8faSwyllys 		 * nickname, we will get the issuer's cert first, then
260230a5e8faSwyllys 		 * get the CRL from the cert.
260330a5e8faSwyllys 		 */
260430a5e8faSwyllys 		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
260530a5e8faSwyllys 		    issuername);
260630a5e8faSwyllys 		if (!cert) {
260730a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
260830a5e8faSwyllys 			rv = KMF_ERR_CERT_NOT_FOUND;
260930a5e8faSwyllys 			goto out;
261030a5e8faSwyllys 		}
261130a5e8faSwyllys 
261230a5e8faSwyllys 		crl = SEC_FindCrlByName(certHandle, &cert->derSubject,
261330a5e8faSwyllys 		    SEC_CRL_TYPE);
261430a5e8faSwyllys 		if (crl == NULL) {
261530a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
261630a5e8faSwyllys 			rv = KMF_ERR_CRL_NOT_FOUND;
261730a5e8faSwyllys 			goto out;
261899ebb4caSwyllys 		}
261999ebb4caSwyllys 	} else {
262030a5e8faSwyllys 		/*
262130a5e8faSwyllys 		 * If the deletion is based on the CRL's subject name, we will
262230a5e8faSwyllys 		 * get all the CRLs from the internal database and search
262330a5e8faSwyllys 		 * for the CRL with the same subject name.
262430a5e8faSwyllys 		 */
262530a5e8faSwyllys 		boolean_t found = B_FALSE;
262630a5e8faSwyllys 		int nssrv;
262799ebb4caSwyllys 
262830a5e8faSwyllys 		nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
262930a5e8faSwyllys 		if (nssrv) {
263030a5e8faSwyllys 			SET_ERROR(kmfh, nssrv);
263130a5e8faSwyllys 			rv = KMF_ERR_CRL_NOT_FOUND;
263230a5e8faSwyllys 			goto out;
263399ebb4caSwyllys 		}
263499ebb4caSwyllys 
263530a5e8faSwyllys 		if (crlList == NULL) {
263630a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
263730a5e8faSwyllys 			rv = KMF_ERR_CRL_NOT_FOUND;
263830a5e8faSwyllys 			goto out;
263930a5e8faSwyllys 		}
264099ebb4caSwyllys 
264130a5e8faSwyllys 		/* Allocate space for name */
264230a5e8faSwyllys 		arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
264330a5e8faSwyllys 		if (arena == NULL) {
264430a5e8faSwyllys 			rv = KMF_ERR_MEMORY;
264530a5e8faSwyllys 			goto out;
264630a5e8faSwyllys 		}
264799ebb4caSwyllys 
264830a5e8faSwyllys 		name = PORT_ArenaZAlloc(arena, sizeof (*name));
264930a5e8faSwyllys 		if (name == NULL) {
265030a5e8faSwyllys 			rv = KMF_ERR_MEMORY;
265130a5e8faSwyllys 			goto out;
265230a5e8faSwyllys 		}
265330a5e8faSwyllys 		name->arena = arena;
265499ebb4caSwyllys 
265530a5e8faSwyllys 		crlNode  = crlList->first;
265630a5e8faSwyllys 		while (crlNode && !found) {
265730a5e8faSwyllys 			char *asciiname = NULL;
265830a5e8faSwyllys 			SECItem* issuer;
265999ebb4caSwyllys 
266030a5e8faSwyllys 			name = &crlNode->crl->crl.name;
266130a5e8faSwyllys 			if (!name) {
266230a5e8faSwyllys 				SET_ERROR(kmfh, PORT_GetError());
266330a5e8faSwyllys 				rv = KMF_ERR_CRL_NOT_FOUND;
266430a5e8faSwyllys 				break;
266530a5e8faSwyllys 			}
266699ebb4caSwyllys 
266730a5e8faSwyllys 			asciiname = CERT_NameToAscii(name);
266830a5e8faSwyllys 			if (asciiname == NULL) {
266930a5e8faSwyllys 				SET_ERROR(kmfh, PORT_GetError());
267030a5e8faSwyllys 				rv = KMF_ERR_CRL_NOT_FOUND;
267130a5e8faSwyllys 				break;
267230a5e8faSwyllys 			}
267399ebb4caSwyllys 
267430a5e8faSwyllys 			if (strcmp(subjectname, asciiname) == 0) {
267530a5e8faSwyllys 				found = B_TRUE;
267630a5e8faSwyllys 				issuer = &crlNode->crl->crl.derName;
267730a5e8faSwyllys 				crl = SEC_FindCrlByName(certHandle, issuer,
267830a5e8faSwyllys 				    SEC_CRL_TYPE);
267930a5e8faSwyllys 				if (crl == NULL) {
268030a5e8faSwyllys 					/* We found a cert but no CRL */
268130a5e8faSwyllys 					SET_ERROR(kmfh,  PORT_GetError());
268230a5e8faSwyllys 					rv = KMF_ERR_CRL_NOT_FOUND;
268330a5e8faSwyllys 				}
268430a5e8faSwyllys 			}
268530a5e8faSwyllys 			PORT_Free(asciiname);
268630a5e8faSwyllys 			crlNode = crlNode->next;
268730a5e8faSwyllys 		}
268830a5e8faSwyllys 
268930a5e8faSwyllys 		if (rv) {
269030a5e8faSwyllys 			goto out;
269199ebb4caSwyllys 		}
269299ebb4caSwyllys 	}
269399ebb4caSwyllys 
269430a5e8faSwyllys 	if (crl) {
269530a5e8faSwyllys 		(void) SEC_DeletePermCRL(crl);
269699ebb4caSwyllys 	}
269730a5e8faSwyllys 
269899ebb4caSwyllys out:
269930a5e8faSwyllys 	if (nss_slot != NULL) {
270030a5e8faSwyllys 		PK11_FreeSlot(nss_slot);
270130a5e8faSwyllys 	}
270299ebb4caSwyllys 
270330a5e8faSwyllys 	if (crlList != NULL) {
270430a5e8faSwyllys 		PORT_FreeArena(crlList->arena, PR_FALSE);
270530a5e8faSwyllys 	}
270699ebb4caSwyllys 
270730a5e8faSwyllys 	if (arena != NULL) {
270830a5e8faSwyllys 		PORT_FreeArena(arena, PR_FALSE);
270930a5e8faSwyllys 	}
271099ebb4caSwyllys 
271130a5e8faSwyllys 	if (cert != NULL) {
271230a5e8faSwyllys 		CERT_DestroyCertificate(cert);
271330a5e8faSwyllys 	}
271430a5e8faSwyllys 
271530a5e8faSwyllys 	if (crl != NULL) {
27165ad42b1bSSurya Prakki 		(void) SEC_DestroyCrl(crl);
271730a5e8faSwyllys 	}
271899ebb4caSwyllys 
271999ebb4caSwyllys 	return (rv);
272099ebb4caSwyllys }
272199ebb4caSwyllys 
272299ebb4caSwyllys KMF_RETURN
NSS_FindCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)272330a5e8faSwyllys NSS_FindCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
272499ebb4caSwyllys {
272599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
272699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
272730a5e8faSwyllys 	PK11SlotInfo *nss_slot = NULL;
272830a5e8faSwyllys 	CERTCrlHeadNode *crlList = NULL;
272930a5e8faSwyllys 	CERTCrlNode *crlNode = NULL;
273030a5e8faSwyllys 	PRArenaPool *arena = NULL;
273130a5e8faSwyllys 	CERTName *name = NULL;
273230a5e8faSwyllys 	SECStatus nssrv;
273330a5e8faSwyllys 	char *asciiname = NULL;
273430a5e8faSwyllys 	int crl_num;
273530a5e8faSwyllys 	int i, *CRLCount;
273630a5e8faSwyllys 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
273730a5e8faSwyllys 	char **CRLNameList;
273899ebb4caSwyllys 
273930a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
274099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
274130a5e8faSwyllys 	}
274299ebb4caSwyllys 
274330a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
274499ebb4caSwyllys 	if (rv != KMF_OK) {
274599ebb4caSwyllys 		return (rv);
274699ebb4caSwyllys 	}
274799ebb4caSwyllys 
274830a5e8faSwyllys 	CRLCount = kmf_get_attr_ptr(KMF_CRL_COUNT_ATTR,	attrlist, numattr);
274930a5e8faSwyllys 	if (CRLCount == NULL)
275030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
275199ebb4caSwyllys 
275230a5e8faSwyllys 	CRLNameList = (char **)kmf_get_attr_ptr(KMF_CRL_NAMELIST_ATTR,
275330a5e8faSwyllys 	    attrlist, numattr);
275430a5e8faSwyllys 
275530a5e8faSwyllys 	/* Look up Crls */
275630a5e8faSwyllys 	nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
275730a5e8faSwyllys 	if (nssrv) {
275830a5e8faSwyllys 		SET_ERROR(kmfh, rv);
275930a5e8faSwyllys 		rv = KMF_ERR_CRL_NOT_FOUND;
276030a5e8faSwyllys 		goto out;
276199ebb4caSwyllys 	}
276299ebb4caSwyllys 
276330a5e8faSwyllys 	/* Allocate space for name first */
276430a5e8faSwyllys 	arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
276530a5e8faSwyllys 	if (arena == NULL) {
276630a5e8faSwyllys 		rv = KMF_ERR_MEMORY;
276730a5e8faSwyllys 		goto out;
276830a5e8faSwyllys 	}
276999ebb4caSwyllys 
277030a5e8faSwyllys 	name = PORT_ArenaZAlloc(arena, sizeof (*name));
277130a5e8faSwyllys 	if (name == NULL) {
277230a5e8faSwyllys 		rv = KMF_ERR_MEMORY;
277330a5e8faSwyllys 		goto out;
277430a5e8faSwyllys 	}
277530a5e8faSwyllys 	name->arena = arena;
277699ebb4caSwyllys 
277730a5e8faSwyllys 	/*
277830a5e8faSwyllys 	 * Loop thru the crlList and create a crl list with CRL's subject name.
277930a5e8faSwyllys 	 */
278030a5e8faSwyllys 	crlNode  = crlList->first;
278130a5e8faSwyllys 	crl_num = 0;
278230a5e8faSwyllys 	while (crlNode) {
278330a5e8faSwyllys 		char *subj_name;
278499ebb4caSwyllys 
278530a5e8faSwyllys 		/* Get the CRL subject name */
278630a5e8faSwyllys 		name = &crlNode->crl->crl.name;
278730a5e8faSwyllys 		if (!name) {
278830a5e8faSwyllys 			SET_ERROR(kmfh, PORT_GetError());
278930a5e8faSwyllys 			rv = KMF_ERR_CRL_NOT_FOUND;
279030a5e8faSwyllys 			break;
279130a5e8faSwyllys 		}
279299ebb4caSwyllys 
279399ebb4caSwyllys 
279430a5e8faSwyllys 		if (CRLNameList != NULL) {
279530a5e8faSwyllys 			asciiname = CERT_NameToAscii(name);
279630a5e8faSwyllys 			if (asciiname == NULL) {
279730a5e8faSwyllys 				SET_ERROR(kmfh, PORT_GetError());
279830a5e8faSwyllys 				rv = KMF_ERR_CRL_NOT_FOUND;
279930a5e8faSwyllys 				break;
280030a5e8faSwyllys 			}
280130a5e8faSwyllys 			subj_name = strdup(asciiname);
280230a5e8faSwyllys 			PORT_Free(asciiname);
280330a5e8faSwyllys 			if (subj_name == NULL) {
280430a5e8faSwyllys 				rv = KMF_ERR_MEMORY;
280530a5e8faSwyllys 				break;
280630a5e8faSwyllys 			}
280730a5e8faSwyllys 			CRLNameList[crl_num] = subj_name;
280830a5e8faSwyllys 		}
280999ebb4caSwyllys 
281030a5e8faSwyllys 		crl_num++;
281130a5e8faSwyllys 		crlNode = crlNode->next;
281230a5e8faSwyllys 	}
281399ebb4caSwyllys 
281430a5e8faSwyllys 	if (rv == KMF_OK) {
281530a5e8faSwyllys 		/* success */
281630a5e8faSwyllys 		*CRLCount = crl_num;
281799ebb4caSwyllys 	}
281899ebb4caSwyllys 
281930a5e8faSwyllys out:
282030a5e8faSwyllys 	if (nss_slot != NULL) {
282130a5e8faSwyllys 		PK11_FreeSlot(nss_slot);
282230a5e8faSwyllys 	}
282399ebb4caSwyllys 
282430a5e8faSwyllys 	if (crlList != NULL) {
282530a5e8faSwyllys 		PORT_FreeArena(crlList->arena, PR_FALSE);
282630a5e8faSwyllys 	}
282799ebb4caSwyllys 
282830a5e8faSwyllys 	if (arena != NULL) {
282930a5e8faSwyllys 		PORT_FreeArena(arena, PR_FALSE);
283099ebb4caSwyllys 	}
283199ebb4caSwyllys 
283230a5e8faSwyllys 	/* If failed, free memory allocated for the returning rlist */
283330a5e8faSwyllys 	if (rv && (CRLNameList != NULL)) {
283430a5e8faSwyllys 		for (i = 0; i < crl_num; i++) {
283530a5e8faSwyllys 			free(CRLNameList[i]);
283630a5e8faSwyllys 		}
283799ebb4caSwyllys 	}
283830a5e8faSwyllys 
283999ebb4caSwyllys 	return (rv);
284099ebb4caSwyllys }
284199ebb4caSwyllys 
284299ebb4caSwyllys KMF_RETURN
NSS_FindCertInCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)284330a5e8faSwyllys NSS_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
284499ebb4caSwyllys {
284599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
284699ebb4caSwyllys 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
284799ebb4caSwyllys 	PK11SlotInfo *nss_slot = NULL;
284830a5e8faSwyllys 	CERTCertificate *cert = NULL;
284930a5e8faSwyllys 	CERTSignedCrl *crl = NULL;
285030a5e8faSwyllys 	CERTCrlEntry *entry;
285130a5e8faSwyllys 	boolean_t match = B_FALSE;
285230a5e8faSwyllys 	int i;
285330a5e8faSwyllys 	CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
285430a5e8faSwyllys 	char *certlabel;
285530a5e8faSwyllys 	KMF_DATA *certdata;
285699ebb4caSwyllys 
285730a5e8faSwyllys 	/* check params */
285830a5e8faSwyllys 	if (numattr == 0 || attrlist == NULL) {
285999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
286099ebb4caSwyllys 	}
286199ebb4caSwyllys 
286230a5e8faSwyllys 	rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
286399ebb4caSwyllys 	if (rv != KMF_OK) {
286499ebb4caSwyllys 		return (rv);
286599ebb4caSwyllys 	}
286699ebb4caSwyllys 
286730a5e8faSwyllys 	certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
286830a5e8faSwyllys 
286930a5e8faSwyllys 	/* Find the certificate first */
287030a5e8faSwyllys 	if (certlabel != NULL) {
287130a5e8faSwyllys 		cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
287230a5e8faSwyllys 		    certlabel);
287330a5e8faSwyllys 	} else {
28746b35cb3cSRichard PALO 		SECItem derCert = { siBuffer, NULL, 0 };
287530a5e8faSwyllys 
287630a5e8faSwyllys 		certdata = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR,
287730a5e8faSwyllys 		    attrlist, numattr);
287830a5e8faSwyllys 
287930a5e8faSwyllys 		if (certdata == NULL)
288030a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
288130a5e8faSwyllys 
288230a5e8faSwyllys 		derCert.data = certdata->Data;
288330a5e8faSwyllys 		derCert.len = certdata->Length;
288430a5e8faSwyllys 
288530a5e8faSwyllys 		cert = CERT_FindCertByDERCert(certHandle, &derCert);
288699ebb4caSwyllys 	}
288799ebb4caSwyllys 
288830a5e8faSwyllys 	if (cert == NULL) {
288999ebb4caSwyllys 		SET_ERROR(kmfh, PORT_GetError());
289030a5e8faSwyllys 		rv = KMF_ERR_CERT_NOT_FOUND;
289199ebb4caSwyllys 		goto out;
289299ebb4caSwyllys 	}
289399ebb4caSwyllys 
289430a5e8faSwyllys 	/* Find the CRL with the same issuer as the given certificate. */
289530a5e8faSwyllys 	crl = SEC_FindCrlByName(certHandle, &cert->derIssuer, SEC_CRL_TYPE);
289630a5e8faSwyllys 	if (crl == NULL) {
289730a5e8faSwyllys 		/*
289830a5e8faSwyllys 		 * Could not find the CRL issued by the same issuer. This
289930a5e8faSwyllys 		 * usually means that the CRL is not installed in the DB.
290030a5e8faSwyllys 		 */
290199ebb4caSwyllys 		SET_ERROR(kmfh, PORT_GetError());
290230a5e8faSwyllys 		rv = KMF_ERR_CRL_NOT_FOUND;
290399ebb4caSwyllys 		goto out;
290499ebb4caSwyllys 
290599ebb4caSwyllys 	}
290699ebb4caSwyllys 
290730a5e8faSwyllys 	/* Check if the certificate's serialNumber is revoked in the CRL */
290830a5e8faSwyllys 	i = 0;
290930a5e8faSwyllys 	while ((entry = (crl->crl).entries[i++]) != NULL) {
291030a5e8faSwyllys 		if (SECITEM_CompareItem(&(cert->serialNumber),
291130a5e8faSwyllys 		    &(entry->serialNumber)) == SECEqual) {
291230a5e8faSwyllys 			match = B_TRUE;
291330a5e8faSwyllys 			break;
291499ebb4caSwyllys 		}
291530a5e8faSwyllys 	}
291699ebb4caSwyllys 
291730a5e8faSwyllys 	if (!match) {
291830a5e8faSwyllys 		rv = KMF_ERR_NOT_REVOKED;
291999ebb4caSwyllys 	}
292099ebb4caSwyllys 
292130a5e8faSwyllys out:
292230a5e8faSwyllys 	if (nss_slot != NULL) {
292330a5e8faSwyllys 		PK11_FreeSlot(nss_slot);
292430a5e8faSwyllys 	}
292599ebb4caSwyllys 
292630a5e8faSwyllys 	if (cert != NULL) {
292730a5e8faSwyllys 		CERT_DestroyCertificate(cert);
292899ebb4caSwyllys 	}
292999ebb4caSwyllys 
293030a5e8faSwyllys 	if (crl != NULL) {
29315ad42b1bSSurya Prakki 		(void) SEC_DestroyCrl(crl);
293299ebb4caSwyllys 	}
293399ebb4caSwyllys 
293430a5e8faSwyllys 	return (rv);
293599ebb4caSwyllys }
2936