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