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