2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * NSS keystore wrapper
2N/A *
2N/A * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <errno.h>
2N/A#include <fcntl.h>
2N/A#include <synch.h>
2N/A
2N/A#include <kmfapiP.h>
2N/A#include <ber_der.h>
2N/A/* NSS related headers */
2N/A
2N/A#include <mps/nss.h>
2N/A#include <mps/cert.h>
2N/A#include <mps/certdb.h>
2N/A#include <mps/secoid.h>
2N/A#include <mps/secder.h>
2N/A#include <mps/secerr.h>
2N/A#include <mps/cryptohi.h>
2N/A#include <mps/keyhi.h>
2N/A#include <mps/keythi.h>
2N/A#include <mps/pk11func.h>
2N/A#include <mps/pk11pqg.h>
2N/A#include <mps/pkcs12.h>
2N/A#include <mps/p12plcy.h>
2N/A#include <mps/prerror.h>
2N/A
2N/A#define NSS_OK 0
2N/A
2N/Amutex_t init_lock = DEFAULTMUTEX;
2N/Astatic int nss_initialized = 0;
2N/A
2N/AKMF_RETURN
2N/ANSS_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/Avoid
2N/ANSS_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
2N/A
2N/AKMF_RETURN
2N/ANSS_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
2N/A
2N/AKMF_RETURN
2N/ANSS_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
2N/A KMF_DATA *, KMF_DATA *);
2N/A
2N/AKMF_RETURN
2N/ANSS_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_FindCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_GetErrorString(KMF_HANDLE_T, char **);
2N/A
2N/AKMF_RETURN
2N/ANSS_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
2N/A KMF_DATA *, KMF_DATA *);
2N/A
2N/AKMF_RETURN
2N/ANSS_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/ANSS_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
2N/A
2N/AKMF_RETURN
2N/ANSS_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/Astatic
2N/AKMF_PLUGIN_FUNCLIST nss_plugin_table =
2N/A{
2N/A 1, /* Version */
2N/A NSS_ConfigureKeystore,
2N/A NSS_FindCert,
2N/A NSS_FreeKMFCert,
2N/A NSS_StoreCert,
2N/A NSS_ImportCert,
2N/A NSS_ImportCRL,
2N/A NSS_DeleteCert,
2N/A NSS_DeleteCRL,
2N/A NSS_CreateKeypair,
2N/A NSS_FindKey,
2N/A NSS_EncodePubKeyData,
2N/A NSS_SignData,
2N/A NSS_DeleteKey,
2N/A NULL /* ListCRL */,
2N/A NSS_FindCRL,
2N/A NSS_FindCertInCRL,
2N/A NSS_GetErrorString,
2N/A NSS_FindPrikeyByCert,
2N/A NSS_DecryptData,
2N/A NSS_ExportPK12,
2N/A NSS_CreateSymKey,
2N/A NSS_GetSymKeyValue,
2N/A NSS_SetTokenPin,
2N/A NSS_StoreKey,
2N/A NULL /* Finalize */
2N/A};
2N/A
2N/A/* additions for importing and exporting PKCS 12 files */
2N/Atypedef struct p12uContextStr {
2N/A char *filename; /* name of file */
2N/A PRFileDesc *file; /* pointer to file */
2N/A PRBool error; /* error occurred? */
2N/A int errorValue; /* which error occurred? */
2N/A} p12uContext;
2N/A
2N/A#define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_NSS; \
2N/A h->lasterr.errcode = c;
2N/A
2N/AKMF_PLUGIN_FUNCLIST *
2N/AKMF_Plugin_Initialize()
2N/A{
2N/A (void) SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
2N/A (void) SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
2N/A (void) SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
2N/A (void) SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
2N/A (void) SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
2N/A (void) SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
2N/A (void) SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
2N/A
2N/A return (&nss_plugin_table);
2N/A}
2N/A
2N/Astatic char *
2N/A/*ARGSUSED*/
2N/Anss_getpassword(PK11SlotInfo *slot, PRBool retry, void *arg)
2N/A{
2N/A if (retry)
2N/A return (NULL);
2N/A if (arg != NULL)
2N/A return ((char *)strdup(arg));
2N/A else
2N/A return (NULL);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Anss_authenticate(KMF_HANDLE_T handle,
2N/A PK11SlotInfo *nss_slot, KMF_CREDENTIAL *cred)
2N/A{
2N/A
2N/A SECStatus nssrv = SECSuccess;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A
2N/A /* If a password was given, try to login to the slot */
2N/A if (cred == NULL || cred->cred == NULL || cred->credlen == 0 ||
2N/A nss_slot == NULL) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A if (PK11_IsLoggedIn(nss_slot, NULL)) {
2N/A return (KMF_OK);
2N/A }
2N/A
2N/A PK11_SetPasswordFunc(nss_getpassword);
2N/A nssrv = PK11_Authenticate(nss_slot, PR_TRUE, (void *)cred->cred);
2N/A
2N/A if (nssrv != SECSuccess) {
2N/A SET_ERROR(kmfh, nssrv);
2N/A PK11_FreeSlot(nss_slot);
2N/A return (KMF_ERR_AUTH_FAILED);
2N/A }
2N/A
2N/A return (KMF_OK);
2N/A}
2N/A
2N/Astatic SECStatus
2N/AInit_NSS_DBs(const char *configdir,
2N/A const char *certPrefix,
2N/A const char *keyPrefix,
2N/A const char *secmodName)
2N/A{
2N/A SECStatus rv = NSS_OK;
2N/A
2N/A (void) mutex_lock(&init_lock);
2N/A
2N/A /* If another thread already did it, return OK. */
2N/A if (nss_initialized) {
2N/A (void) mutex_unlock(&init_lock);
2N/A return (SECSuccess);
2N/A }
2N/A
2N/A rv = NSS_Initialize((configdir && strlen(configdir)) ?
2N/A configdir : "./", certPrefix, keyPrefix,
2N/A secmodName ? secmodName : "secmod.db", NSS_INIT_COOPERATE);
2N/A if (rv != SECSuccess) {
2N/A goto end;
2N/A }
2N/A
2N/A nss_initialized++;
2N/Aend:
2N/A (void) mutex_unlock(&init_lock);
2N/A return (rv);
2N/A}
2N/A
2N/A/*
2N/A * When it is called the first time, it will intialize NSS. Once the NSS
2N/A * is initialized, this function returns KMF_KEYSTORE_ALREADY_INITIALIZED
2N/A * if it is called again.
2N/A */
2N/AKMF_RETURN
2N/ANSS_ConfigureKeystore(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A char *configdir;
2N/A char *certPrefix;
2N/A char *keyPrefix;
2N/A char *secModName;
2N/A
2N/A configdir = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2N/A certPrefix = kmf_get_attr_ptr(KMF_CERTPREFIX_ATTR, attrlist, numattr);
2N/A keyPrefix = kmf_get_attr_ptr(KMF_KEYPREFIX_ATTR, attrlist, numattr);
2N/A secModName = kmf_get_attr_ptr(KMF_SECMODNAME_ATTR, attrlist, numattr);
2N/A
2N/A (void) mutex_lock(&init_lock);
2N/A if (nss_initialized == 0) {
2N/A SECStatus err;
2N/A
2N/A (void) mutex_unlock(&init_lock);
2N/A err = Init_NSS_DBs(configdir, certPrefix,
2N/A keyPrefix, secModName);
2N/A if (err != SECSuccess) {
2N/A SET_ERROR(kmfh, err);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A } else {
2N/A rv = KMF_KEYSTORE_ALREADY_INITIALIZED;
2N/A (void) mutex_unlock(&init_lock);
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/A/*
2N/A * This function sets up the slot to be used for other operations.
2N/A * This function is basically called by every NSS SPI function.
2N/A * For those functions that can only be performed in the internal slot, the
2N/A * boolean "internal_slot_only" argument needs to be TRUE.
2N/A * A slot pointer will be returned when this function is executed successfully.
2N/A */
2N/AKMF_RETURN
2N/Ado_nss_init(void *handle, int numattr,
2N/A KMF_ATTRIBUTE *attrlist,
2N/A boolean_t internal_slot_only,
2N/A PK11SlotInfo **nss_slot)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A char *slotlabel = NULL;
2N/A
2N/A if (!nss_initialized)
2N/A return (KMF_ERR_PLUGIN_INIT);
2N/A
2N/A slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
2N/A /*
2N/A * NSS Is already initialized, but we need to find
2N/A * the right slot.
2N/A */
2N/A if (slotlabel == NULL ||
2N/A strcmp(slotlabel, "internal") == 0) {
2N/A *nss_slot = PK11_GetInternalKeySlot();
2N/A } else if (internal_slot_only == TRUE) {
2N/A rv = KMF_ERR_SLOTNAME;
2N/A goto end;
2N/A } else {
2N/A *nss_slot = PK11_FindSlotByName(slotlabel);
2N/A }
2N/A
2N/A if (*nss_slot == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_SLOTNAME;
2N/A goto end;
2N/A }
2N/A
2N/A /*
2N/A * If the token was not yet initialized, return an error.
2N/A */
2N/A if (PK11_NeedUserInit(*nss_slot)) {
2N/A rv = KMF_ERR_UNINITIALIZED_TOKEN;
2N/A }
2N/A
2N/Aend:
2N/A return (rv);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Anss2kmf_cert(CERTCertificate *nss_cert, KMF_X509_DER_CERT *kmf_cert)
2N/A{
2N/A kmf_cert->kmf_private.keystore_type = KMF_KEYSTORE_NSS;
2N/A kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID;
2N/A
2N/A kmf_cert->certificate.Length = nss_cert->derCert.len;
2N/A
2N/A if ((kmf_cert->certificate.Data = malloc(nss_cert->derCert.len)) ==
2N/A NULL) {
2N/A kmf_cert->certificate.Length = 0;
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A (void) memcpy(kmf_cert->certificate.Data, nss_cert->derCert.data,
2N/A nss_cert->derCert.len);
2N/A if (nss_cert->nickname != NULL)
2N/A kmf_cert->kmf_private.label =
2N/A (char *)strdup(nss_cert->nickname);
2N/A return (KMF_OK);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Anss_getcert_by_label(KMF_HANDLE *kmfh,
2N/A char *name, KMF_X509_DER_CERT *kmf_cert,
2N/A uint32_t *num_certs, KMF_CERT_VALIDITY find_criteria)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A CERTCertificate *nss_cert;
2N/A SECCertTimeValidity validity;
2N/A
2N/A nss_cert = PK11_FindCertFromNickname(name, NULL);
2N/A if (nss_cert == NULL) {
2N/A *num_certs = 0;
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A *num_certs = 0;
2N/A return (KMF_ERR_CERT_NOT_FOUND);
2N/A } else {
2N/A *num_certs = 1;
2N/A }
2N/A
2N/A switch (find_criteria) {
2N/A case KMF_ALL_CERTS:
2N/A break;
2N/A case KMF_NONEXPIRED_CERTS:
2N/A validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
2N/A PR_FALSE);
2N/A if (validity != secCertTimeValid) {
2N/A /* this is an invalid cert, reject it */
2N/A *num_certs = 0;
2N/A CERT_DestroyCertificate(nss_cert);
2N/A return (KMF_OK);
2N/A }
2N/A break;
2N/A case KMF_EXPIRED_CERTS:
2N/A validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
2N/A PR_FALSE);
2N/A if (validity == secCertTimeValid) {
2N/A /* this is a valid cert, reject it in this case. */
2N/A *num_certs = 0;
2N/A CERT_DestroyCertificate(nss_cert);
2N/A return (KMF_OK);
2N/A }
2N/A break;
2N/A default:
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A if (kmf_cert != NULL)
2N/A rv = nss2kmf_cert(nss_cert, kmf_cert);
2N/A
2N/A /* We copied the data we need, so cleanup the internal record */
2N/A CERT_DestroyCertificate(nss_cert);
2N/A
2N/A if (rv != KMF_OK)
2N/A *num_certs = 0;
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Anss_find_matching_certs(PK11SlotInfo *slot,
2N/A char *issuer, char *subject, KMF_BIGINT *serial,
2N/A CERTCertList **certlist, KMF_CERT_VALIDITY find_criteria)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A SECStatus ret;
2N/A CERTCertList *list;
2N/A CERTCertListNode *node;
2N/A KMF_X509_NAME issuerDN, subjectDN;
2N/A boolean_t findIssuer = FALSE;
2N/A boolean_t findSubject = FALSE;
2N/A boolean_t findSerial = FALSE;
2N/A
2N/A if (issuer != NULL && strlen(issuer)) {
2N/A rv = kmf_dn_parser(issuer, &issuerDN);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A findIssuer = TRUE;
2N/A }
2N/A if (subject != NULL && strlen(subject)) {
2N/A rv = kmf_dn_parser(subject, &subjectDN);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A findSubject = TRUE;
2N/A }
2N/A if (serial != 0 && serial->val != NULL && serial->len > 0)
2N/A findSerial = TRUE;
2N/A
2N/A list = PK11_ListCertsInSlot(slot);
2N/A if (list) {
2N/A node = CERT_LIST_HEAD(list);
2N/A while (!CERT_LIST_END(node, list)) {
2N/A KMF_X509_NAME cmpDN;
2N/A KMF_DATA der;
2N/A boolean_t match;
2N/A CERTCertListNode *freenode;
2N/A
2N/A if (findIssuer) {
2N/A der.Data = node->cert->derIssuer.data;
2N/A der.Length = node->cert->derIssuer.len;
2N/A rv = DerDecodeName(&der, &cmpDN);
2N/A if (rv == KMF_OK) {
2N/A match = !KMF_CompareRDNs(&issuerDN,
2N/A &cmpDN);
2N/A kmf_free_dn(&cmpDN);
2N/A if (!match)
2N/A goto delete_and_cont;
2N/A } else {
2N/A goto delete_and_cont;
2N/A }
2N/A }
2N/A if (findSubject) {
2N/A der.Data = node->cert->derSubject.data;
2N/A der.Length = node->cert->derSubject.len;
2N/A rv = DerDecodeName(&der, &cmpDN);
2N/A if (rv == KMF_OK) {
2N/A match = !KMF_CompareRDNs(&subjectDN,
2N/A &cmpDN);
2N/A kmf_free_dn(&cmpDN);
2N/A if (!match)
2N/A goto delete_and_cont;
2N/A } else {
2N/A goto delete_and_cont;
2N/A }
2N/A }
2N/A if (findSerial) {
2N/A SECItem *sernum;
2N/A
2N/A sernum = &node->cert->serialNumber;
2N/A
2N/A if (serial->len != sernum->len)
2N/A goto delete_and_cont;
2N/A
2N/A if (memcmp(sernum->data, serial->val,
2N/A serial->len))
2N/A goto delete_and_cont;
2N/A }
2N/A
2N/A /* select the certs using find criteria */
2N/A switch (find_criteria) {
2N/A case KMF_ALL_CERTS:
2N/A break;
2N/A case KMF_NONEXPIRED_CERTS:
2N/A ret = CERT_CertTimesValid(node->cert);
2N/A if (ret == SECFailure) {
2N/A /* this is an invalid cert */
2N/A goto skip;
2N/A }
2N/A break;
2N/A
2N/A case KMF_EXPIRED_CERTS:
2N/A ret = CERT_CertTimesValid(node->cert);
2N/A if (ret != SECFailure) {
2N/A /* this is a valid cert */
2N/A goto skip;
2N/A }
2N/A break;
2N/A }
2N/Askip:
2N/A node = CERT_LIST_NEXT(node);
2N/A continue;
2N/Adelete_and_cont:
2N/A freenode = node;
2N/A node = CERT_LIST_NEXT(node);
2N/A CERT_RemoveCertListNode(freenode);
2N/A }
2N/A }
2N/A
2N/A if (rv == KMF_OK && certlist != NULL) {
2N/A *certlist = list;
2N/A } else {
2N/A CERT_DestroyCertList(list);
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/AconvertCertList(void *kmfhandle,
2N/A CERTCertList *nsscerts, KMF_X509_DER_CERT *kmfcerts,
2N/A uint32_t *numcerts)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A CERTCertListNode *node;
2N/A uint32_t maxcerts = *numcerts;
2N/A
2N/A maxcerts = *numcerts;
2N/A if (maxcerts == 0)
2N/A maxcerts = 0xFFFFFFFF;
2N/A
2N/A *numcerts = 0;
2N/A
2N/A /*
2N/A * Don't copy more certs than the caller wanted.
2N/A */
2N/A for (node = CERT_LIST_HEAD(nsscerts);
2N/A !CERT_LIST_END(node, nsscerts) && rv == KMF_OK &&
2N/A (*numcerts) < maxcerts;
2N/A node = CERT_LIST_NEXT(node), (*numcerts)++) {
2N/A if (kmfcerts != NULL)
2N/A rv = nss2kmf_cert(node->cert, &kmfcerts[*numcerts]);
2N/A }
2N/A
2N/A /*
2N/A * If we failed, delete any certs allocated so far.
2N/A */
2N/A if (rv != KMF_OK) {
2N/A int i;
2N/A for (i = 0; i < *numcerts; i++)
2N/A kmf_free_kmf_cert(kmfhandle, &kmfcerts[i]);
2N/A
2N/A *numcerts = 0;
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A CERTCertList *certlist = NULL;
2N/A uint32_t maxcerts;
2N/A uint32_t *num_certs;
2N/A KMF_X509_DER_CERT *kmfcerts = NULL;
2N/A char *certlabel = NULL;
2N/A char *issuer = NULL;
2N/A char *subject = NULL;
2N/A KMF_BIGINT *serial = NULL;
2N/A KMF_CERT_VALIDITY validity;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2N/A if (num_certs == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A maxcerts = *num_certs;
2N/A if (maxcerts == 0)
2N/A maxcerts = 0xFFFFFFFF;
2N/A *num_certs = 0;
2N/A
2N/A /* Get the optional returned certificate list */
2N/A kmfcerts = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, numattr);
2N/A
2N/A /* Get optional search criteria attributes */
2N/A certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
2N/A subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
2N/A serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
2N/A
2N/A rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
2N/A &validity, NULL);
2N/A if (rv != KMF_OK) {
2N/A validity = KMF_ALL_CERTS;
2N/A rv = KMF_OK;
2N/A }
2N/A
2N/A if (certlabel != NULL) {
2N/A /* This will only find 1 certificate */
2N/A rv = nss_getcert_by_label(kmfh, certlabel, kmfcerts, num_certs,
2N/A validity);
2N/A } else {
2N/A /*
2N/A * Build a list of matching certs.
2N/A */
2N/A rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
2N/A &certlist, validity);
2N/A
2N/A /*
2N/A * If the caller supplied a pointer to storage for
2N/A * a list of certs, convert up to 'maxcerts' of the
2N/A * matching certs.
2N/A */
2N/A if (rv == KMF_OK && certlist != NULL) {
2N/A rv = convertCertList(handle, certlist, kmfcerts,
2N/A &maxcerts);
2N/A CERT_DestroyCertList(certlist);
2N/A if (rv == KMF_OK)
2N/A *num_certs = maxcerts;
2N/A }
2N/A }
2N/A
2N/A if (nss_slot != NULL) {
2N/A PK11_FreeSlot(nss_slot);
2N/A }
2N/A
2N/A if (rv == KMF_OK && *num_certs == 0)
2N/A rv = KMF_ERR_CERT_NOT_FOUND;
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/Avoid
2N/A/*ARGSUSED*/
2N/ANSS_FreeKMFCert(KMF_HANDLE_T handle,
2N/A KMF_X509_DER_CERT *kmf_cert)
2N/A{
2N/A if (kmf_cert != NULL) {
2N/A if (kmf_cert->certificate.Data != NULL) {
2N/A free(kmf_cert->certificate.Data);
2N/A kmf_cert->certificate.Data = NULL;
2N/A kmf_cert->certificate.Length = 0;
2N/A }
2N/A if (kmf_cert->kmf_private.label != NULL) {
2N/A free(kmf_cert->kmf_private.label);
2N/A kmf_cert->kmf_private.label = NULL;
2N/A }
2N/A }
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A int nssrv;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CERTCertificate *cert = NULL;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A char *certlabel = NULL;
2N/A char *issuer = NULL;
2N/A char *subject = NULL;
2N/A KMF_BIGINT *serial = NULL;
2N/A KMF_CERT_VALIDITY validity;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A /* Get the search criteria attributes. They are all optional. */
2N/A certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
2N/A subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
2N/A serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
2N/A
2N/A rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
2N/A &validity, NULL);
2N/A if (rv != KMF_OK) {
2N/A validity = KMF_ALL_CERTS;
2N/A rv = KMF_OK;
2N/A }
2N/A
2N/A /* Start finding the matched certificates and delete them. */
2N/A if (certlabel != NULL) {
2N/A cert = PK11_FindCertFromNickname(certlabel, NULL);
2N/A if (cert == NULL) {
2N/A return (KMF_ERR_CERT_NOT_FOUND);
2N/A }
2N/A
2N/A switch (validity) {
2N/A case KMF_ALL_CERTS:
2N/A break;
2N/A case KMF_NONEXPIRED_CERTS:
2N/A nssrv = CERT_CertTimesValid(cert);
2N/A if (nssrv == SECFailure) {
2N/A /* this is an invalid cert - skip it */
2N/A goto out;
2N/A }
2N/A break;
2N/A case KMF_EXPIRED_CERTS:
2N/A nssrv = CERT_CertTimesValid(cert);
2N/A if (nssrv != SECFailure) {
2N/A /* this is a valid cert - skip it */
2N/A goto out;
2N/A }
2N/A break;
2N/A }
2N/A /* delete it from database */
2N/A nssrv = SEC_DeletePermCertificate(cert);
2N/A if (nssrv) {
2N/A SET_ERROR(kmfh, nssrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A }
2N/A } else {
2N/A CERTCertListNode *node;
2N/A CERTCertList *certlist = NULL;
2N/A
2N/A rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
2N/A &certlist, validity);
2N/A
2N/A for (node = CERT_LIST_HEAD(certlist);
2N/A !CERT_LIST_END(node, certlist) && rv == KMF_OK;
2N/A node = CERT_LIST_NEXT(node)) {
2N/A
2N/A nssrv = SEC_DeletePermCertificate(node->cert);
2N/A if (nssrv) {
2N/A SET_ERROR(kmfh, nssrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A }
2N/A }
2N/A
2N/A if (rv == KMF_OK && certlist != NULL) {
2N/A CERT_DestroyCertList(certlist);
2N/A } else if (rv == KMF_OK && certlist == NULL) {
2N/A rv = KMF_ERR_CERT_NOT_FOUND;
2N/A }
2N/A }
2N/Aout:
2N/A if (nss_slot != NULL) {
2N/A PK11_FreeSlot(nss_slot);
2N/A }
2N/A
2N/A if (cert != NULL) {
2N/A CERT_DestroyCertificate(cert);
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/Astatic void
2N/AInitRandom(char *filename)
2N/A{
2N/A char buf[2048];
2N/A int fd;
2N/A PRInt32 count;
2N/A
2N/A fd = open(filename, O_RDONLY);
2N/A if (!fd)
2N/A return;
2N/A
2N/A count = read(fd, buf, sizeof (buf));
2N/A if (count > 0) {
2N/A (void) PK11_RandomUpdate(buf, count);
2N/A }
2N/A
2N/A (void) close(fd);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_CreateKeypair(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A PK11RSAGenParams rsaparams;
2N/A void *nssparams;
2N/A CK_MECHANISM_TYPE mechanism;
2N/A ulong_t publicExponent = 0x010001;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A SECKEYPrivateKey *NSSprivkey = NULL;
2N/A SECKEYPublicKey *NSSpubkey = NULL;
2N/A SECKEYECParams *ecparams = NULL;
2N/A PQGParams *pqgParams = NULL;
2N/A KMF_CREDENTIAL cred;
2N/A boolean_t storekey = TRUE;
2N/A uint32_t keylen = 1024, len;
2N/A uint32_t keylen_size = sizeof (uint32_t);
2N/A KMF_KEY_ALG keytype = KMF_RSA;
2N/A KMF_KEY_HANDLE *pubkey = NULL;
2N/A KMF_KEY_HANDLE *privkey = NULL;
2N/A char *keylabel = NULL;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2N/A (void *)&cred, NULL);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A rv = nss_authenticate(handle, nss_slot, &cred);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A /* "storekey" is optional. Default is TRUE */
2N/A (void) kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
2N/A &storekey, NULL);
2N/A
2N/A /* keytype is optional. KMF_RSA is default */
2N/A (void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
2N/A (void *)&keytype, NULL);
2N/A
2N/A rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
2N/A &keylen, &keylen_size);
2N/A if (rv == KMF_ERR_ATTR_NOT_FOUND)
2N/A /* Default keylen = 1024 */
2N/A rv = KMF_OK;
2N/A else if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
2N/A privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
2N/A if (pubkey == NULL || privkey == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
2N/A (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
2N/A
2N/A rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr, NULL, &len);
2N/A if (rv == KMF_OK && len > 0) {
2N/A keylabel = malloc(len + 1);
2N/A if (keylabel == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A /* Now fill in the label value */
2N/A (void) memset(keylabel, 0, len + 1);
2N/A rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr,
2N/A keylabel, NULL);
2N/A if (rv != KMF_OK) {
2N/A free(keylabel);
2N/A goto cleanup;
2N/A }
2N/A }
2N/A
2N/A /* Get some random bits */
2N/A InitRandom("/dev/urandom");
2N/A if (keytype == KMF_RSA) {
2N/A KMF_BIGINT rsaexp;
2N/A
2N/A rsaparams.keySizeInBits = keylen;
2N/A /*
2N/A * NSS only allows for a 4 byte exponent.
2N/A * Ignore the exponent parameter if it is too big.
2N/A */
2N/A if ((rv = kmf_get_attr(KMF_RSAEXP_ATTR, attrlist, numattr,
2N/A &rsaexp, NULL)) == KMF_OK) {
2N/A if (rsaexp.len > 0 &&
2N/A rsaexp.len <= sizeof (publicExponent) &&
2N/A rsaexp.val != NULL) {
2N/A (void) memcpy(&publicExponent, rsaexp.val,
2N/A rsaexp.len);
2N/A }
2N/A }
2N/A rsaparams.pe = publicExponent;
2N/A mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
2N/A nssparams = &rsaparams;
2N/A } else if (keytype == KMF_DSA) {
2N/A PQGVerify *pqgVerify = NULL;
2N/A int ks;
2N/A SECStatus nssrv, passed;
2N/A
2N/A mechanism = CKM_DSA_KEY_PAIR_GEN;
2N/A
2N/A ks = PQG_PBITS_TO_INDEX(keylen);
2N/A nssrv = PK11_PQG_ParamGen(ks, &pqgParams, &pqgVerify);
2N/A if (nssrv != SECSuccess) {
2N/A SET_ERROR(kmfh, rv);
2N/A PK11_PQG_DestroyVerify(pqgVerify);
2N/A rv = KMF_ERR_KEYGEN_FAILED;
2N/A goto cleanup;
2N/A }
2N/A
2N/A nssrv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
2N/A if (nssrv != SECSuccess || passed != SECSuccess) {
2N/A SET_ERROR(kmfh, rv);
2N/A rv = KMF_ERR_KEYGEN_FAILED;
2N/A }
2N/A
2N/A PK11_PQG_DestroyVerify(pqgVerify);
2N/A
2N/A if (rv != KMF_OK) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A goto cleanup;
2N/A }
2N/A
2N/A nssparams = pqgParams;
2N/A } else if (keytype == KMF_ECDSA) {
2N/A KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR,
2N/A attrlist, numattr);
2N/A if (eccoid == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A ecparams = SECITEM_AllocItem(NULL, NULL, (eccoid->Length));
2N/A if (!ecparams)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A (void) memcpy(ecparams->data, eccoid->Data, eccoid->Length);
2N/A
2N/A mechanism = CKM_EC_KEY_PAIR_GEN;
2N/A nssparams = ecparams;
2N/A } else {
2N/A rv = KMF_ERR_BAD_PARAMETER;
2N/A goto cleanup;
2N/A }
2N/A
2N/A NSSprivkey = PK11_GenerateKeyPair(nss_slot, mechanism, nssparams,
2N/A &NSSpubkey,
2N/A storekey, /* isPermanent */
2N/A PR_TRUE, /* isSensitive */
2N/A (void *)cred.cred);
2N/A
2N/A if (NSSprivkey == NULL || NSSpubkey == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_KEYGEN_FAILED;
2N/A } else {
2N/A if (keylabel != NULL && strlen(keylabel)) {
2N/A (void) PK11_SetPrivateKeyNickname(NSSprivkey,
2N/A keylabel);
2N/A (void) PK11_SetPublicKeyNickname(NSSpubkey, keylabel);
2N/A }
2N/A /* Now, convert it to a KMF_KEY object for the framework */
2N/A privkey->kstype = KMF_KEYSTORE_NSS;
2N/A privkey->keyalg = keytype;
2N/A privkey->keyclass = KMF_ASYM_PRI;
2N/A privkey->keylabel = PK11_GetPrivateKeyNickname(NSSprivkey);
2N/A privkey->keyp = (void *)NSSprivkey;
2N/A
2N/A pubkey->kstype = KMF_KEYSTORE_NSS;
2N/A pubkey->keyalg = keytype;
2N/A pubkey->keyp = (void *)NSSpubkey;
2N/A pubkey->keyclass = KMF_ASYM_PUB;
2N/A pubkey->keylabel = PK11_GetPublicKeyNickname(NSSpubkey);
2N/A
2N/A rv = KMF_OK;
2N/A }
2N/Acleanup:
2N/A if (rv != KMF_OK) {
2N/A if (NSSpubkey)
2N/A (void) PK11_DeleteTokenPublicKey(NSSpubkey);
2N/A if (NSSprivkey)
2N/A (void) PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE);
2N/A
2N/A privkey->keyp = NULL;
2N/A pubkey->keyp = NULL;
2N/A }
2N/A
2N/A if (keylabel)
2N/A free(keylabel);
2N/A
2N/A if (pqgParams != NULL)
2N/A PK11_PQG_DestroyParams(pqgParams);
2N/A
2N/A if (ecparams != NULL)
2N/A SECITEM_FreeItem(ecparams, PR_TRUE);
2N/A
2N/A if (nss_slot != NULL)
2N/A PK11_FreeSlot(nss_slot);
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2N/A KMF_OID *AlgOID, KMF_DATA *tobesigned,
2N/A KMF_DATA *output)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A KMF_ALGORITHM_INDEX AlgId;
2N/A SECOidTag signAlgTag;
2N/A SECKEYPrivateKey *NSSprivkey = NULL;
2N/A SECStatus rv;
2N/A SECItem signed_data;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A
2N/A signed_data.data = 0;
2N/A if (key == NULL || AlgOID == NULL ||
2N/A tobesigned == NULL || output == NULL ||
2N/A tobesigned->Data == NULL ||
2N/A output->Data == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* Map the OID to a NSS algorithm */
2N/A AlgId = x509_algoid_to_algid(AlgOID);
2N/A if (AlgId == KMF_ALGID_NONE)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A NSSprivkey = (SECKEYPrivateKey *)key->keyp;
2N/A
2N/A if (AlgId == KMF_ALGID_MD5WithRSA)
2N/A signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
2N/A else if (AlgId == KMF_ALGID_MD2WithRSA)
2N/A signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
2N/A else if (AlgId == KMF_ALGID_SHA1WithRSA)
2N/A signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
2N/A else if (AlgId == KMF_ALGID_SHA256WithRSA)
2N/A signAlgTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
2N/A else if (AlgId == KMF_ALGID_SHA384WithRSA)
2N/A signAlgTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
2N/A else if (AlgId == KMF_ALGID_SHA512WithRSA)
2N/A signAlgTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
2N/A else if (AlgId == KMF_ALGID_SHA1WithDSA)
2N/A signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
2N/A else if (AlgId == KMF_ALGID_SHA1WithECDSA || AlgId == KMF_ALGID_ECDSA)
2N/A signAlgTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
2N/A else if (AlgId == KMF_ALGID_SHA256WithECDSA)
2N/A signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
2N/A else if (AlgId == KMF_ALGID_SHA384WithECDSA)
2N/A signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
2N/A else if (AlgId == KMF_ALGID_SHA512WithECDSA)
2N/A signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
2N/A else /* NSS does not support DSA with SHA2 hashes (FIPS 186-3) */
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = SEC_SignData(&signed_data, tobesigned->Data,
2N/A tobesigned->Length, NSSprivkey, signAlgTag);
2N/A
2N/A if (rv != 0) {
2N/A SET_ERROR(kmfh, rv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A if (signed_data.len <= output->Length) {
2N/A (void) memcpy(output->Data, signed_data.data, signed_data.len);
2N/A output->Length = signed_data.len;
2N/A } else {
2N/A output->Length = 0;
2N/A ret = KMF_ERR_BAD_PARAMETER;
2N/A }
2N/A free(signed_data.data);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
2N/A KMF_DATA *encoded)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A SECItem *rvitem;
2N/A CERTSubjectPublicKeyInfo *spki = NULL;
2N/A
2N/A if (keyp == NULL || encoded == NULL || keyp->keyp == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp);
2N/A if (spki == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A
2N/A rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki,
2N/A CERT_SubjectPublicKeyInfoTemplate);
2N/A if (rvitem != NULL) {
2N/A encoded->Data = malloc(rvitem->len);
2N/A if (encoded->Data == NULL) {
2N/A ret = KMF_ERR_MEMORY;
2N/A } else {
2N/A (void) memcpy(encoded->Data, rvitem->data, rvitem->len);
2N/A encoded->Length = rvitem->len;
2N/A }
2N/A SECITEM_FreeItem(rvitem, TRUE);
2N/A } else {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A encoded->Data = NULL;
2N/A encoded->Length = 0;
2N/A ret = KMF_ERR_ENCODING;
2N/A }
2N/A SECKEY_DestroySubjectPublicKeyInfo(spki);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_DeleteKey(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A KMF_KEY_HANDLE *key;
2N/A KMF_CREDENTIAL cred;
2N/A boolean_t delete_token = B_TRUE;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A /*
2N/A * "delete_token" means to clear it from the token storage as well
2N/A * as from memory.
2N/A */
2N/A key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2N/A if (key == NULL || key->keyp == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&delete_token, NULL);
2N/A if (rv != KMF_OK)
2N/A /* "delete_token" is optional. Default is TRUE */
2N/A rv = KMF_OK;
2N/A
2N/A if (delete_token) {
2N/A SECStatus nssrv = SECSuccess;
2N/A if (key->keyclass != KMF_ASYM_PUB &&
2N/A key->keyclass != KMF_ASYM_PRI &&
2N/A key->keyclass != KMF_SYMMETRIC)
2N/A return (KMF_ERR_BAD_KEY_CLASS);
2N/A
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2N/A (void *)&cred, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = nss_authenticate(handle, nss_slot, &cred);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A if (key->keyclass == KMF_ASYM_PUB) {
2N/A nssrv = PK11_DeleteTokenPublicKey(
2N/A (SECKEYPublicKey *)key->keyp);
2N/A } else if (key->keyclass == KMF_ASYM_PRI) {
2N/A nssrv = PK11_DeleteTokenPrivateKey(
2N/A (SECKEYPrivateKey *)key->keyp, PR_TRUE);
2N/A } else if (key->keyclass == KMF_SYMMETRIC) {
2N/A nssrv = PK11_DeleteTokenSymKey(
2N/A (PK11SymKey *) key->keyp);
2N/A if (nssrv == SECSuccess)
2N/A PK11_FreeSymKey((PK11SymKey *) key->keyp);
2N/A }
2N/A if (nssrv != SECSuccess) {
2N/A SET_ERROR(handle, PORT_GetError());
2N/A rv = KMF_ERR_INTERNAL;
2N/A }
2N/A } else {
2N/A if (key->keyclass == KMF_ASYM_PUB) {
2N/A SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp);
2N/A } else if (key->keyclass == KMF_ASYM_PRI) {
2N/A SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp);
2N/A } else if (key->keyclass == KMF_SYMMETRIC) {
2N/A PK11_FreeSymKey((PK11SymKey *) key->keyp);
2N/A } else {
2N/A return (KMF_ERR_BAD_KEY_CLASS);
2N/A }
2N/A }
2N/A key->keyp = NULL;
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A char *str;
2N/A
2N/A /* Get the error string in the default language */
2N/A str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode);
2N/A
2N/A if (str != NULL) {
2N/A *msgstr = (char *)strdup(str);
2N/A if ((*msgstr) == NULL)
2N/A ret = KMF_ERR_MEMORY;
2N/A } else {
2N/A *msgstr = NULL;
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A KMF_CREDENTIAL cred;
2N/A KMF_KEY_HANDLE *key = NULL;
2N/A KMF_DATA *cert = NULL;
2N/A CERTCertificate *nss_cert = NULL;
2N/A SECKEYPrivateKey* privkey = NULL;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A /* Get the credential */
2N/A rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2N/A (void *)&cred, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A rv = nss_authenticate(handle, nss_slot, &cred);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A /* Get the key handle */
2N/A key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2N/A if (key == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* Get the cert data and decode it */
2N/A cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2N/A if (cert == NULL || cert->Data == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2N/A cert->Length);
2N/A if (nss_cert == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A return (KMF_ERR_BAD_CERT_FORMAT);
2N/A }
2N/A
2N/A privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL);
2N/A if (privkey == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A return (KMF_ERR_KEY_NOT_FOUND);
2N/A }
2N/A
2N/A key->kstype = KMF_KEYSTORE_NSS;
2N/A key->keyclass = KMF_ASYM_PRI;
2N/A key->keyp = (void *)privkey;
2N/A key->keylabel = PK11_GetPrivateKeyNickname(privkey);
2N/A
2N/A CERT_DestroyCertificate(nss_cert);
2N/A
2N/A return (KMF_OK);
2N/A}
2N/A
2N/A
2N/AKMF_RETURN
2N/ANSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2N/A KMF_OID *AlgOID, KMF_DATA *ciphertext,
2N/A KMF_DATA *output)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A SECKEYPrivateKey *NSSprivkey = NULL;
2N/A SECStatus rv;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A unsigned int in_len = 0, out_len = 0;
2N/A unsigned int total_decrypted = 0, modulus_len = 0;
2N/A uint8_t *in_data, *out_data;
2N/A int i, blocks;
2N/A
2N/A if (key == NULL || AlgOID == NULL ||
2N/A ciphertext == NULL || output == NULL ||
2N/A ciphertext->Data == NULL ||
2N/A output->Data == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A NSSprivkey = (SECKEYPrivateKey *)key->keyp;
2N/A modulus_len = PK11_GetPrivateModulusLen(NSSprivkey);
2N/A
2N/A blocks = ciphertext->Length/modulus_len;
2N/A out_data = output->Data;
2N/A in_data = ciphertext->Data;
2N/A out_len = modulus_len - 11;
2N/A in_len = modulus_len;
2N/A
2N/A for (i = 0; i < blocks; i++) {
2N/A rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data,
2N/A &out_len, ciphertext->Length, in_data, in_len);
2N/A
2N/A if (rv != 0) {
2N/A SET_ERROR(kmfh, rv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A out_data += out_len;
2N/A total_decrypted += out_len;
2N/A in_data += in_len;
2N/A }
2N/A
2N/A output->Length = total_decrypted;
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/Astatic KMF_KEY_ALG
2N/Apk11keytype2kmf(CK_KEY_TYPE type)
2N/A{
2N/A switch (type) {
2N/A case CKK_RSA:
2N/A return (KMF_RSA);
2N/A case CKK_DSA:
2N/A return (KMF_RSA);
2N/A case CKK_AES:
2N/A return (KMF_AES);
2N/A case CKK_RC4:
2N/A return (KMF_RC4);
2N/A case CKK_DES:
2N/A return (KMF_DES);
2N/A case CKK_DES3:
2N/A return (KMF_DES3);
2N/A case CKK_EC:
2N/A return (KMF_ECDSA);
2N/A default:
2N/A /* not supported */
2N/A return (KMF_KEYALG_NONE);
2N/A }
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_FindKey(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv;
2N/A SECKEYPrivateKeyList *prilist;
2N/A SECKEYPrivateKeyListNode *prinode;
2N/A SECKEYPublicKeyList *publist;
2N/A SECKEYPublicKeyListNode *pubnode;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A PK11SymKey *symlist = NULL;
2N/A int count;
2N/A uint32_t maxkeys;
2N/A KMF_KEY_HANDLE *keys;
2N/A uint32_t *numkeys;
2N/A KMF_CREDENTIAL *cred = NULL;
2N/A KMF_KEY_CLASS keyclass;
2N/A char *findLabel;
2N/A char *nick;
2N/A int match = 0;
2N/A KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2N/A if (numkeys == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A /* It is OK if this is NULL, we dont need a cred to find public keys */
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A
2N/A if (cred != NULL) {
2N/A rv = nss_authenticate(handle, nss_slot, cred);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A }
2N/A
2N/A maxkeys = *numkeys;
2N/A if (maxkeys == 0)
2N/A maxkeys = 0xFFFFFFFF;
2N/A *numkeys = 0;
2N/A
2N/A rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2N/A (void *)&keyclass, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2N/A
2N/A if (keyclass == KMF_ASYM_PUB) {
2N/A publist = PK11_ListPublicKeysInSlot(nss_slot, findLabel);
2N/A if (publist == NULL) {
2N/A rv = KMF_ERR_KEY_NOT_FOUND;
2N/A goto cleanup;
2N/A }
2N/A } else if (keyclass == KMF_ASYM_PRI) {
2N/A prilist = PK11_ListPrivKeysInSlot(nss_slot, findLabel, NULL);
2N/A if (prilist == NULL) {
2N/A rv = KMF_ERR_KEY_NOT_FOUND;
2N/A goto cleanup;
2N/A }
2N/A } else if (keyclass == KMF_SYMMETRIC) {
2N/A symlist = PK11_ListFixedKeysInSlot(nss_slot, findLabel, NULL);
2N/A if (symlist == NULL) {
2N/A rv = KMF_ERR_KEY_NOT_FOUND;
2N/A goto cleanup;
2N/A }
2N/A } else {
2N/A rv = KMF_ERR_BAD_KEY_CLASS;
2N/A goto cleanup;
2N/A }
2N/A
2N/A keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2N/A /* it is okay to have "keys" contains NULL */
2N/A
2N/A if (keyclass == KMF_ASYM_PUB) {
2N/A for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist);
2N/A !PUBKEY_LIST_END(pubnode, publist) && count < maxkeys;
2N/A pubnode = PUBKEY_LIST_NEXT(pubnode)) {
2N/A match = 0;
2N/A /*
2N/A * Due to bug in NSS, we have to manually match
2N/A * the labels to be sure we have a match.
2N/A */
2N/A nick = PK11_GetPublicKeyNickname(pubnode->key);
2N/A if (findLabel) {
2N/A match = (nick &&
2N/A (strcmp(nick, findLabel) == 0));
2N/A } else {
2N/A /* always match if findLabel is NULL */
2N/A match = 1;
2N/A }
2N/A if (keys != NULL && match) {
2N/A keys[count].kstype = KMF_KEYSTORE_NSS;
2N/A keys[count].keyclass = KMF_ASYM_PUB;
2N/A keys[count].keyp = (void *)pubnode->key;
2N/A keys[count].keylabel = nick;
2N/A
2N/A if (pubnode->key->keyType == rsaKey)
2N/A keys[count].keyalg = KMF_RSA;
2N/A else if (pubnode->key->keyType == dsaKey)
2N/A keys[count].keyalg = KMF_DSA;
2N/A else if (pubnode->key->keyType == ecKey)
2N/A keys[count].keyalg = KMF_ECDSA;
2N/A }
2N/A if (match)
2N/A count++;
2N/A }
2N/A *numkeys = count;
2N/A } else if (keyclass == KMF_ASYM_PRI) {
2N/A for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist);
2N/A !PRIVKEY_LIST_END(prinode, prilist) && count < maxkeys;
2N/A prinode = PRIVKEY_LIST_NEXT(prinode)) {
2N/A match = 0;
2N/A /*
2N/A * Due to bug in NSS, we have to manually match
2N/A * the labels to be sure we have a match.
2N/A */
2N/A nick = PK11_GetPrivateKeyNickname(prinode->key);
2N/A if (findLabel) {
2N/A match = (nick &&
2N/A (strcmp(nick, findLabel) == 0));
2N/A } else {
2N/A /* always match if findLabel is NULL */
2N/A match = 1;
2N/A }
2N/A if (keys != NULL && match) {
2N/A keys[count].kstype = KMF_KEYSTORE_NSS;
2N/A keys[count].keyclass = KMF_ASYM_PRI;
2N/A keys[count].keyp = (void *)prinode->key;
2N/A keys[count].keylabel = nick;
2N/A
2N/A if (prinode->key->keyType == rsaKey)
2N/A keys[count].keyalg = KMF_RSA;
2N/A else if (prinode->key->keyType == dsaKey)
2N/A keys[count].keyalg = KMF_DSA;
2N/A else if (prinode->key->keyType == ecKey)
2N/A keys[count].keyalg = KMF_ECDSA;
2N/A }
2N/A if (match)
2N/A count++;
2N/A }
2N/A *numkeys = count;
2N/A } else if (keyclass == KMF_SYMMETRIC) {
2N/A count = 0;
2N/A rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
2N/A (void *)&keytype, NULL);
2N/A if (rv != KMF_OK)
2N/A rv = KMF_OK;
2N/A while (symlist && count < maxkeys) {
2N/A PK11SymKey *symkey = symlist;
2N/A CK_KEY_TYPE type;
2N/A KMF_KEY_ALG keyalg;
2N/A
2N/A match = 0;
2N/A type = PK11_GetSymKeyType(symkey);
2N/A keyalg = pk11keytype2kmf(type);
2N/A
2N/A symlist = PK11_GetNextSymKey(symkey);
2N/A
2N/A /*
2N/A * If keytype is specified in the searching parameter,
2N/A * check the keytype and skip the key if its keytype
2N/A * doesn't match.
2N/A */
2N/A if (keytype != KMF_KEYALG_NONE && keytype != keyalg) {
2N/A /* free that key since we arent using it */
2N/A PK11_FreeSymKey(symkey);
2N/A continue;
2N/A }
2N/A /*
2N/A * Due to bug in NSS, we have to manually match
2N/A * the labels to be sure we have a match.
2N/A */
2N/A nick = PK11_GetSymKeyNickname(symkey);
2N/A if (findLabel) {
2N/A match = (nick &&
2N/A (strcmp(nick, findLabel) == 0));
2N/A } else {
2N/A /* always match if findLabel is NULL */
2N/A match = 1;
2N/A }
2N/A
2N/A if (keys != NULL && match) {
2N/A keys[count].kstype = KMF_KEYSTORE_NSS;
2N/A keys[count].keyclass = KMF_SYMMETRIC;
2N/A keys[count].keyp = (void *) symkey;
2N/A keys[count].keylabel = nick;
2N/A keys[count].keyalg = keyalg;
2N/A } else {
2N/A PK11_FreeSymKey(symkey);
2N/A }
2N/A if (match)
2N/A count++;
2N/A }
2N/A /*
2N/A * Cleanup memory for unused keys.
2N/A */
2N/A while (symlist != NULL) {
2N/A PK11SymKey *symkey = symlist;
2N/A
2N/A PK11_FreeSymKey(symkey);
2N/A symlist = PK11_GetNextSymKey(symkey);
2N/A }
2N/A *numkeys = count;
2N/A }
2N/A
2N/Acleanup:
2N/A if (nss_slot != NULL) {
2N/A PK11_FreeSlot(nss_slot);
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/Astatic SECStatus
2N/Ap12u_SwapUnicodeBytes(SECItem *uniItem)
2N/A{
2N/A unsigned int i;
2N/A unsigned char a;
2N/A if ((uniItem == NULL) || (uniItem->len % 2)) {
2N/A return (SECFailure);
2N/A }
2N/A for (i = 0; i < uniItem->len; i += 2) {
2N/A a = uniItem->data[i];
2N/A uniItem->data[i] = uniItem->data[i+1];
2N/A uniItem->data[i+1] = a;
2N/A }
2N/A return (SECSuccess);
2N/A}
2N/A
2N/Astatic PRBool
2N/Ap12u_ucs2_ascii_conversion_function(
2N/A PRBool toUnicode,
2N/A unsigned char *inBuf,
2N/A unsigned int inBufLen,
2N/A unsigned char *outBuf,
2N/A unsigned int maxOutBufLen,
2N/A unsigned int *outBufLen,
2N/A PRBool swapBytes)
2N/A{
2N/A SECItem it = { 0 };
2N/A SECItem *dup = NULL;
2N/A PRBool ret;
2N/A
2N/A it.data = inBuf;
2N/A it.len = inBufLen;
2N/A dup = SECITEM_DupItem(&it);
2N/A /*
2N/A * If converting Unicode to ASCII, swap bytes before conversion
2N/A * as neccessary.
2N/A */
2N/A if (!toUnicode && swapBytes) {
2N/A if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
2N/A SECITEM_ZfreeItem(dup, PR_TRUE);
2N/A return (PR_FALSE);
2N/A }
2N/A }
2N/A /* Perform the conversion. */
2N/A ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
2N/A outBuf, maxOutBufLen, outBufLen);
2N/A if (dup)
2N/A SECITEM_ZfreeItem(dup, PR_TRUE);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/Astatic PRBool
2N/Ap12u_OpenFile(p12uContext *p12ctx, PRBool fileRead)
2N/A{
2N/A if (!p12ctx || !p12ctx->filename) {
2N/A return (PR_FALSE);
2N/A }
2N/A
2N/A if (fileRead) {
2N/A p12ctx->file = PR_Open(p12ctx->filename, PR_RDONLY, 0400);
2N/A } else {
2N/A p12ctx->file = PR_Open(p12ctx->filename,
2N/A PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600);
2N/A }
2N/A
2N/A if (!p12ctx->file) {
2N/A p12ctx->error = PR_TRUE;
2N/A return (PR_FALSE);
2N/A }
2N/A
2N/A return (PR_TRUE);
2N/A}
2N/A
2N/Astatic void
2N/Ap12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
2N/A{
2N/A if (!ppCtx || !(*ppCtx)) {
2N/A return;
2N/A }
2N/A
2N/A if ((*ppCtx)->file != NULL) {
2N/A (void) PR_Close((*ppCtx)->file);
2N/A }
2N/A
2N/A if ((*ppCtx)->filename != NULL) {
2N/A if (removeFile) {
2N/A (void) PR_Delete((*ppCtx)->filename);
2N/A }
2N/A free((*ppCtx)->filename);
2N/A }
2N/A
2N/A free(*ppCtx);
2N/A *ppCtx = NULL;
2N/A}
2N/A
2N/Astatic p12uContext *
2N/Ap12u_InitContext(PRBool fileImport, char *filename)
2N/A{
2N/A p12uContext *p12ctx;
2N/A
2N/A p12ctx = PORT_ZNew(p12uContext);
2N/A if (!p12ctx) {
2N/A return (NULL);
2N/A }
2N/A
2N/A p12ctx->error = PR_FALSE;
2N/A p12ctx->errorValue = 0;
2N/A p12ctx->filename = strdup(filename);
2N/A
2N/A if (!p12u_OpenFile(p12ctx, fileImport)) {
2N/A p12u_DestroyContext(&p12ctx, PR_FALSE);
2N/A return (NULL);
2N/A }
2N/A
2N/A return (p12ctx);
2N/A}
2N/A
2N/Astatic void
2N/Ap12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
2N/A{
2N/A p12uContext *p12cxt = arg;
2N/A int writeLen;
2N/A
2N/A if (!p12cxt || (p12cxt->error == PR_TRUE)) {
2N/A return;
2N/A }
2N/A
2N/A if (p12cxt->file == NULL) {
2N/A p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
2N/A p12cxt->error = PR_TRUE;
2N/A return;
2N/A }
2N/A
2N/A writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
2N/A
2N/A if (writeLen != (int)len) {
2N/A (void) PR_Close(p12cxt->file);
2N/A free(p12cxt->filename);
2N/A p12cxt->filename = NULL;
2N/A p12cxt->file = NULL;
2N/A p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
2N/A p12cxt->error = PR_TRUE;
2N/A }
2N/A}
2N/A
2N/A#define HANDLE_NSS_ERROR(r) {\
2N/A SET_ERROR(kmfh, PORT_GetError()); \
2N/A rv = r; \
2N/A goto out; }
2N/A
2N/Astatic KMF_RETURN
2N/Aadd_cert_to_bag(SEC_PKCS12ExportContext *p12ecx,
2N/A CERTCertificate *cert, SECItem *pwitem)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
2N/A
2N/A keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
2N/A if (PK11_IsFIPS()) {
2N/A certSafe = keySafe;
2N/A } else {
2N/A certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
2N/A SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
2N/A }
2N/A
2N/A if (!certSafe || !keySafe) {
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto out;
2N/A }
2N/A
2N/A if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
2N/A CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
2N/A SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
2N/A != SECSuccess) {
2N/A rv = KMF_ERR_INTERNAL;
2N/A }
2N/Aout:
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A SEC_PKCS12ExportContext *p12ecx = NULL;
2N/A p12uContext *p12ctx = NULL;
2N/A CERTCertList *certlist = NULL;
2N/A CERTCertificate *nsscert = NULL;
2N/A CERTCertListNode* node = NULL;
2N/A PK11SlotInfo *slot = NULL;
2N/A SECItem pwitem = {NULL, 0};
2N/A KMF_CREDENTIAL *cred = NULL;
2N/A KMF_CREDENTIAL *p12cred = NULL;
2N/A char *certlabel = NULL;
2N/A char *issuer = NULL;
2N/A char *subject = NULL;
2N/A KMF_BIGINT *serial = NULL;
2N/A char *filename = NULL;
2N/A
2N/A if (kmfh == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &slot);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (cred == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = nss_authenticate(handle, slot, cred);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
2N/A if (p12cred == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
2N/A numattr);
2N/A if (filename == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* Get optional search criteria attributes */
2N/A certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
2N/A subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
2N/A serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
2N/A
2N/A /*
2N/A * Find the certificate(s) first.
2N/A */
2N/A if (certlabel != NULL) {
2N/A nsscert = PK11_FindCertFromNickname(certlabel, NULL);
2N/A if (nsscert == NULL) {
2N/A HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND)
2N/A }
2N/A } else {
2N/A rv = nss_find_matching_certs(slot, issuer, subject, serial,
2N/A &certlist, 0);
2N/A
2N/A if (rv == KMF_OK && certlist == NULL) {
2N/A return (KMF_ERR_CERT_NOT_FOUND);
2N/A }
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A }
2N/A
2N/A /*
2N/A * The KMF_CREDENTIAL holds the password to use for
2N/A * encrypting the PKCS12 key information.
2N/A */
2N/A pwitem.data = (uchar_t *)p12cred->cred;
2N/A pwitem.len = p12cred->credlen;
2N/A
2N/A p12ctx = p12u_InitContext(PR_FALSE, filename);
2N/A if (!p12ctx) {
2N/A HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
2N/A }
2N/A
2N/A PORT_SetUCS2_ASCIIConversionFunction(
2N/A p12u_ucs2_ascii_conversion_function);
2N/A
2N/A p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, NULL);
2N/A if (!p12ecx) {
2N/A HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
2N/A }
2N/A
2N/A if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
2N/A != SECSuccess) {
2N/A HANDLE_NSS_ERROR(KMF_ERR_INTERNAL)
2N/A }
2N/A
2N/A /*
2N/A * NSS actually supports storing a list of keys and certs
2N/A * in the PKCS#12 PDU. Nice feature.
2N/A */
2N/A if (certlist != NULL) {
2N/A for (node = CERT_LIST_HEAD(certlist);
2N/A !CERT_LIST_END(node, certlist) && rv == KMF_OK;
2N/A node = CERT_LIST_NEXT(node)) {
2N/A rv = add_cert_to_bag(p12ecx, node->cert, &pwitem);
2N/A }
2N/A } else if (nsscert != NULL) {
2N/A rv = add_cert_to_bag(p12ecx, nsscert, &pwitem);
2N/A }
2N/A
2N/A if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx)
2N/A != SECSuccess) {
2N/A HANDLE_NSS_ERROR(KMF_ERR_ENCODING)
2N/A }
2N/Aout:
2N/A if (nsscert)
2N/A CERT_DestroyCertificate(nsscert);
2N/A
2N/A if (certlist)
2N/A CERT_DestroyCertList(certlist);
2N/A
2N/A if (p12ctx)
2N/A p12u_DestroyContext(&p12ctx, PR_FALSE);
2N/A
2N/A if (p12ecx)
2N/A SEC_PKCS12DestroyExportContext(p12ecx);
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/A#define SETATTR(t, n, atype, value, size) \
2N/A t[n].type = atype; \
2N/A t[n].pValue = (CK_BYTE *)value; \
2N/A t[n].ulValueLen = (CK_ULONG)size;
2N/A
2N/AKMF_RETURN
2N/ANSS_CreateSymKey(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A PK11SymKey *nsskey = NULL;
2N/A CK_MECHANISM_TYPE keyType;
2N/A SECStatus nssrv;
2N/A int keySize;
2N/A KMF_KEY_HANDLE *symkey;
2N/A KMF_CREDENTIAL cred;
2N/A uint32_t keylen;
2N/A uint32_t keylen_size = sizeof (uint32_t);
2N/A KMF_KEY_ALG keytype;
2N/A char *keylabel = NULL;
2N/A
2N/A if (kmfh == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2N/A if (symkey == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, (void *)&keytype,
2N/A NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, &keylen,
2N/A &keylen_size);
2N/A if (rv == KMF_ERR_ATTR_NOT_FOUND &&
2N/A (keytype == KMF_DES || keytype == KMF_DES3))
2N/A /* keylength is not required for DES and 3DES */
2N/A rv = KMF_OK;
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2N/A if (keylabel == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A switch (keytype) {
2N/A case KMF_AES:
2N/A keyType = CKM_AES_KEY_GEN;
2N/A keySize = keylen;
2N/A if (keySize == 0 || (keySize % 8) != 0)
2N/A return (KMF_ERR_BAD_KEY_SIZE);
2N/A break;
2N/A case KMF_RC4:
2N/A keyType = CKM_RC4_KEY_GEN;
2N/A keySize = keylen;
2N/A if (keySize == 0 || (keySize % 8) != 0)
2N/A return (KMF_ERR_BAD_KEY_SIZE);
2N/A break;
2N/A case KMF_DES:
2N/A keyType = CKM_DES_KEY_GEN;
2N/A keySize = 0; /* required by PK11_TokenKeyGen() */
2N/A break;
2N/A case KMF_DES3:
2N/A keyType = CKM_DES3_KEY_GEN;
2N/A keySize = 0; /* required by PK11_TokenKeyGen() */
2N/A break;
2N/A case KMF_GENERIC_SECRET:
2N/A keyType = CKM_GENERIC_SECRET_KEY_GEN;
2N/A keySize = keylen;
2N/A if (keySize == 0 || (keySize % 8) != 0)
2N/A return (KMF_ERR_BAD_KEY_SIZE);
2N/A break;
2N/A default:
2N/A rv = KMF_ERR_BAD_KEY_TYPE;
2N/A goto out;
2N/A }
2N/A
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2N/A (void *)&cred, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = nss_authenticate(handle, nss_slot, &cred);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A /* convert key length to bytes */
2N/A nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize / 8, NULL,
2N/A PR_TRUE, (void *)cred.cred);
2N/A if (nsskey == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_KEYGEN_FAILED;
2N/A goto out;
2N/A }
2N/A
2N/A nssrv = PK11_SetSymKeyNickname(nsskey, keylabel);
2N/A if (nssrv != SECSuccess) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_KEYGEN_FAILED;
2N/A goto out;
2N/A }
2N/A
2N/A symkey->kstype = KMF_KEYSTORE_NSS;
2N/A symkey->keyalg = keytype;
2N/A symkey->keyclass = KMF_SYMMETRIC;
2N/A symkey->israw = FALSE;
2N/A symkey->keyp = (void *)nsskey;
2N/A
2N/Aout:
2N/A if (nss_slot != NULL)
2N/A PK11_FreeSlot(nss_slot);
2N/A
2N/A if (rv != KMF_OK && nsskey != NULL) {
2N/A (void) PK11_DeleteTokenSymKey(nsskey);
2N/A PK11_FreeSymKey(nsskey);
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2N/A KMF_RAW_SYM_KEY *rkey)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A SECItem *value = NULL;
2N/A PK11SymKey *nsskey;
2N/A SECStatus nss_rv;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED);
2N/A
2N/A if (symkey == NULL || rkey == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A else if (symkey->keyclass != KMF_SYMMETRIC)
2N/A return (KMF_ERR_BAD_KEY_CLASS);
2N/A
2N/A if (symkey->israw) {
2N/A KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2N/A
2N/A if (rawkey == NULL ||
2N/A rawkey->rawdata.sym.keydata.val == NULL ||
2N/A rawkey->rawdata.sym.keydata.len == 0)
2N/A return (KMF_ERR_BAD_KEYHANDLE);
2N/A
2N/A rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2N/A if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A (void) memcpy(rkey->keydata.val,
2N/A rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2N/A } else {
2N/A nsskey = (PK11SymKey *)(symkey->keyp);
2N/A if (nsskey == NULL)
2N/A return (KMF_ERR_BAD_KEYHANDLE);
2N/A
2N/A nss_rv = PK11_ExtractKeyValue(nsskey);
2N/A if (nss_rv != SECSuccess) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_GETKEYVALUE_FAILED;
2N/A goto out;
2N/A }
2N/A
2N/A value = PK11_GetKeyData(nsskey);
2N/A if (value == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_GETKEYVALUE_FAILED;
2N/A goto out;
2N/A }
2N/A
2N/A if (value->len == 0 || value->data == NULL) {
2N/A rv = KMF_ERR_GETKEYVALUE_FAILED;
2N/A goto out;
2N/A }
2N/A
2N/A rkey->keydata.val = malloc(value->len);
2N/A if (rkey->keydata.val == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto out;
2N/A }
2N/A (void) memcpy(rkey->keydata.val, value->data, value->len);
2N/A rkey->keydata.len = value->len;
2N/A (void) memset(value->data, 0, value->len);
2N/A }
2N/Aout:
2N/A if (value != NULL)
2N/A SECITEM_FreeItem(value, PR_TRUE);
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_SetTokenPin(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A int rv;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A KMF_CREDENTIAL oldcred, newcred;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A ret = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2N/A (void *)&oldcred, NULL);
2N/A if (ret != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A ret = kmf_get_attr(KMF_NEWPIN_ATTR, attrlist, numattr,
2N/A (void *)&newcred, NULL);
2N/A if (ret != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A /* If it was uninitialized, set it */
2N/A if (ret == KMF_ERR_UNINITIALIZED_TOKEN) {
2N/A rv = PK11_InitPin(nss_slot, NULL, newcred.cred);
2N/A if (rv != SECSuccess) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A ret = KMF_ERR_AUTH_FAILED;
2N/A } else {
2N/A ret = KMF_OK;
2N/A }
2N/A } else if (ret == KMF_OK) {
2N/A ret = nss_authenticate(handle, nss_slot, &oldcred);
2N/A if (ret != KMF_OK) {
2N/A return (ret);
2N/A }
2N/A rv = PK11_ChangePW(nss_slot, oldcred.cred, newcred.cred);
2N/A if (rv != SECSuccess) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A ret = KMF_ERR_AUTH_FAILED;
2N/A }
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_StoreKey(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A KMF_CREDENTIAL cred = {NULL, 0};
2N/A KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
2N/A KMF_RAW_KEY_DATA *rawkey = NULL;
2N/A char *keylabel = NULL;
2N/A SECStatus ckrv = SECSuccess;
2N/A SECItem nickname = {NULL, 0};
2N/A CERTCertificate *nss_cert = NULL;
2N/A
2N/A if (kmfh == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2N/A (void *)&cred, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = nss_authenticate(handle, nss_slot, &cred);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
2N/A if (pubkey == NULL) {
2N/A /* look for private key */
2N/A prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist,
2N/A numattr);
2N/A if (prikey == NULL)
2N/A /* look for raw key */
2N/A rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR,
2N/A attrlist, numattr);
2N/A }
2N/A
2N/A /* If no keys were found, return error */
2N/A if (pubkey == NULL && prikey == NULL && rawkey == NULL)
2N/A return (KMF_ERR_ATTR_NOT_FOUND);
2N/A
2N/A keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2N/A if (keylabel != NULL) {
2N/A nickname.data = (uchar_t *)keylabel;
2N/A nickname.len = strlen(keylabel);
2N/A }
2N/A
2N/A if (rawkey != NULL) {
2N/A uchar_t ver = 0;
2N/A SECKEYPrivateKeyInfo rpk;
2N/A KMF_DATA derkey = {NULL, 0};
2N/A KMF_DATA *cert;
2N/A
2N/A cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2N/A if (cert == NULL)
2N/A return (rv);
2N/A /*
2N/A * Decode the cert into an NSS CERT object so we can access the
2N/A * SPKI and KeyUsage data later.
2N/A */
2N/A nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2N/A cert->Length);
2N/A
2N/A if (nss_cert == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_BAD_CERT_FORMAT;
2N/A goto cleanup;
2N/A }
2N/A
2N/A (void) memset(&rpk, 0, sizeof (rpk));
2N/A rpk.arena = NULL;
2N/A rpk.version.type = siUnsignedInteger;
2N/A rpk.version.data = &ver;
2N/A rpk.version.len = 1;
2N/A if (rawkey->keytype == KMF_RSA) {
2N/A rv = DerEncodeRSAPrivateKey(&derkey,
2N/A &rawkey->rawdata.rsa);
2N/A if (rv != KMF_OK)
2N/A goto cleanup;
2N/A } else if (rawkey->keytype == KMF_DSA) {
2N/A rv = DerEncodeDSAPrivateKey(&derkey,
2N/A &rawkey->rawdata.dsa);
2N/A if (rv != KMF_OK)
2N/A goto cleanup;
2N/A } else if (rawkey->keytype == KMF_ECDSA) {
2N/A rv = DerEncodeECPrivateKey(&derkey,
2N/A &rawkey->rawdata.ec);
2N/A if (rv != KMF_OK)
2N/A goto cleanup;
2N/A }
2N/A rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
2N/A rpk.privateKey.data = derkey.Data;
2N/A rpk.privateKey.len = derkey.Length;
2N/A rpk.attributes = NULL;
2N/A
2N/A ckrv = PK11_ImportPrivateKeyInfo(nss_slot, &rpk, &nickname,
2N/A &nss_cert->subjectPublicKeyInfo.subjectPublicKey, TRUE,
2N/A TRUE, nss_cert->keyUsage, NULL);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_INTERNAL;
2N/A }
2N/A kmf_free_data(&derkey);
2N/A } else if (pubkey != NULL && pubkey->kstype == KMF_KEYSTORE_NSS) {
2N/A CK_OBJECT_HANDLE pk;
2N/A SECKEYPublicKey *publicKey = (SECKEYPublicKey *) pubkey->keyp;
2N/A
2N/A pk = PK11_ImportPublicKey(nss_slot, publicKey, PR_TRUE);
2N/A if (pk == CK_INVALID_HANDLE) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_INTERNAL;
2N/A }
2N/A } else if (prikey != NULL && prikey->kstype == KMF_KEYSTORE_NSS) {
2N/A SECKEYPrivateKey *pk;
2N/A SECKEYPrivateKey *privKey = (SECKEYPrivateKey *) prikey->keyp;
2N/A
2N/A pk = PK11_LoadPrivKey(nss_slot, privKey, NULL, PR_TRUE,
2N/A PR_TRUE);
2N/A if (pk == CK_INVALID_HANDLE) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_INTERNAL;
2N/A }
2N/A /* We stored it, but don't need the handle anymore */
2N/A SECKEY_DestroyPrivateKey(pk);
2N/A }
2N/A
2N/Acleanup:
2N/A if (nss_cert != NULL)
2N/A CERT_DestroyCertificate(nss_cert);
2N/A PK11_FreeSlot(nss_slot);
2N/A return (rv);
2N/A}
2N/A
2N/A/*
2N/A * This function is called by NSS_StoreCert() and NSS_ImportCert().
2N/A * The "label" and "trust_flag" arguments can be NULL.
2N/A */
2N/Astatic KMF_RETURN
2N/Astore_cert(KMF_HANDLE_T handle, PK11SlotInfo *nss_slot, KMF_DATA *cert,
2N/A char *label, char *trust_flag)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A SECStatus nss_rv;
2N/A CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2N/A CERTCertificate *nss_cert = NULL;
2N/A CERTCertTrust *nss_trust = NULL;
2N/A
2N/A if (nss_slot == NULL || cert == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2N/A cert->Length);
2N/A if (nss_cert == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A ret = KMF_ERR_BAD_CERT_FORMAT;
2N/A goto out;
2N/A }
2N/A
2N/A /* Store the cert into the NSS database */
2N/A nss_rv = PK11_ImportCert(nss_slot, nss_cert, CK_INVALID_HANDLE,
2N/A label, 0);
2N/A if (nss_rv) {
2N/A SET_ERROR(kmfh, nss_rv);
2N/A ret = KMF_ERR_BAD_CERT_FORMAT;
2N/A goto out;
2N/A }
2N/A
2N/A /* If trust_flag is NULL, then we are done */
2N/A if (trust_flag == NULL)
2N/A goto out;
2N/A
2N/A nss_trust = (CERTCertTrust *) malloc(sizeof (CERTCertTrust));
2N/A if (nss_trust == NULL) {
2N/A ret = KMF_ERR_MEMORY;
2N/A goto out;
2N/A }
2N/A
2N/A nss_rv = CERT_DecodeTrustString(nss_trust, trust_flag);
2N/A if (nss_rv) {
2N/A SET_ERROR(kmfh, nss_rv);
2N/A ret = KMF_ERR_BAD_PARAMETER;
2N/A goto out;
2N/A }
2N/A
2N/A nss_rv = CERT_ChangeCertTrust(certHandle, nss_cert, nss_trust);
2N/A if (nss_rv) {
2N/A SET_ERROR(kmfh, nss_rv);
2N/A ret = KMF_ERR_BAD_PARAMETER;
2N/A }
2N/A
2N/Aout:
2N/A if (nss_cert != NULL) {
2N/A CERT_DestroyCertificate(nss_cert);
2N/A }
2N/A
2N/A if (nss_trust != NULL) {
2N/A free(nss_trust);
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A
2N/AKMF_RETURN
2N/ANSS_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A KMF_DATA *cert = NULL;
2N/A char *label = NULL;
2N/A char *trust_flag = NULL;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A /* Get the cert data */
2N/A cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2N/A if (cert == NULL || cert->Data == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* The label attribute is optional */
2N/A label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A
2N/A /* The trustflag attriburte is optional */
2N/A trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2N/A
2N/A ret = store_cert(handle, nss_slot, cert, label, trust_flag);
2N/A
2N/Aout:
2N/A if (nss_slot != NULL) {
2N/A PK11_FreeSlot(nss_slot);
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A
2N/AKMF_RETURN
2N/ANSS_ImportCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A KMF_DATA cert = {NULL, 0};
2N/A KMF_DATA cert_der = {NULL, 0};
2N/A KMF_DATA *cptr = NULL;
2N/A KMF_ENCODE_FORMAT format;
2N/A char *label = NULL;
2N/A char *trust_flag = NULL;
2N/A char *certfile = NULL;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A /* Get the input cert filename attribute */
2N/A certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
2N/A if (certfile == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* Check the cert file and auto-detect the file format of it. */
2N/A ret = kmf_is_cert_file(handle, certfile, &format);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A ret = kmf_read_input_file(handle, certfile, &cert);
2N/A if (ret != KMF_OK) {
2N/A return (ret);
2N/A }
2N/A
2N/A /*
2N/A * If the imported cert is in PEM format, convert it to
2N/A * DER format in order to store it in NSS token.
2N/A */
2N/A if (format == KMF_FORMAT_PEM) {
2N/A int derlen;
2N/A ret = kmf_pem_to_der(cert.Data, cert.Length,
2N/A &cert_der.Data, &derlen);
2N/A if (ret != KMF_OK) {
2N/A goto cleanup;
2N/A }
2N/A cert_der.Length = (size_t)derlen;
2N/A cptr = &cert_der;
2N/A } else {
2N/A cptr = &cert;
2N/A }
2N/A
2N/A label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2N/A ret = store_cert(handle, nss_slot, cptr, label, trust_flag);
2N/A
2N/Acleanup:
2N/A if (format == KMF_FORMAT_PEM) {
2N/A kmf_free_data(&cert_der);
2N/A }
2N/A
2N/A kmf_free_data(&cert);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A
2N/AKMF_RETURN
2N/ANSS_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A CERTSignedCrl *nss_crl = NULL;
2N/A KMF_ENCODE_FORMAT format;
2N/A int importOptions;
2N/A SECItem crlDER;
2N/A KMF_DATA crl1;
2N/A KMF_DATA crl2;
2N/A char *crlfilename;
2N/A boolean_t crlcheck = FALSE;
2N/A
2N/A if (attrlist == NULL || numattr == 0) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (ret != KMF_OK) {
2N/A return (ret);
2N/A }
2N/A
2N/A crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist,
2N/A numattr);
2N/A if (crlfilename == NULL)
2N/A return (KMF_ERR_BAD_CRLFILE);
2N/A
2N/A /*
2N/A * Check if the input CRL file is a valid CRL file and auto-detect
2N/A * the encoded format of the file.
2N/A */
2N/A ret = kmf_is_crl_file(handle, crlfilename, &format);
2N/A if (ret != KMF_OK)
2N/A return (ret);
2N/A
2N/A ret = kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
2N/A &crlcheck, NULL);
2N/A if (ret != KMF_OK)
2N/A ret = KMF_OK; /* CRL_CHECK is optional */
2N/A
2N/A /* set importOptions */
2N/A if (crlcheck == B_FALSE) {
2N/A importOptions = CRL_IMPORT_DEFAULT_OPTIONS |
2N/A CRL_IMPORT_BYPASS_CHECKS;
2N/A } else {
2N/A importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
2N/A }
2N/A
2N/A
2N/A /* Read in the CRL file */
2N/A crl1.Data = NULL;
2N/A crl2.Data = NULL;
2N/A ret = kmf_read_input_file(handle, crlfilename, &crl1);
2N/A if (ret != KMF_OK) {
2N/A return (ret);
2N/A }
2N/A
2N/A /* If the input CRL is in PEM format, convert it to DER first. */
2N/A if (format == KMF_FORMAT_PEM) {
2N/A int len;
2N/A ret = kmf_pem_to_der(crl1.Data, crl1.Length,
2N/A &crl2.Data, &len);
2N/A if (ret != KMF_OK) {
2N/A goto out;
2N/A }
2N/A crl2.Length = (size_t)len;
2N/A }
2N/A
2N/A crlDER.data = format == KMF_FORMAT_ASN1 ? crl1.Data : crl2.Data;
2N/A crlDER.len = format == KMF_FORMAT_ASN1 ? crl1.Length : crl2.Length;
2N/A
2N/A nss_crl = PK11_ImportCRL(nss_slot, &crlDER, NULL, SEC_CRL_TYPE,
2N/A NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
2N/A
2N/A if (nss_crl == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A ret = KMF_ERR_BAD_CRLFILE;
2N/A goto out;
2N/A }
2N/A
2N/Aout:
2N/A if (nss_slot != NULL) {
2N/A PK11_FreeSlot(nss_slot);
2N/A }
2N/A
2N/A if (crl1.Data != NULL) {
2N/A free(crl1.Data);
2N/A }
2N/A
2N/A if (crl2.Data != NULL) {
2N/A free(crl2.Data);
2N/A }
2N/A
2N/A if (nss_crl != NULL) {
2N/A (void) SEC_DestroyCrl(nss_crl);
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CERTSignedCrl *crl = NULL;
2N/A CERTCertificate *cert = NULL;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A CERTCrlHeadNode *crlList = NULL;
2N/A CERTCrlNode *crlNode = NULL;
2N/A PRArenaPool *arena = NULL;
2N/A CERTName *name = NULL;
2N/A CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2N/A char *issuername, *subjectname;
2N/A
2N/A /* check params */
2N/A if (numattr == 0 || attrlist == NULL) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A issuername = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist,
2N/A numattr);
2N/A subjectname = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist,
2N/A numattr);
2N/A
2N/A /* Caller must specify issuer or subject but not both */
2N/A if ((issuername == NULL && subjectname == NULL) ||
2N/A (issuername != NULL && subjectname != NULL))
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* Find the CRL based on the deletion criteria. */
2N/A if (issuername != NULL) {
2N/A /*
2N/A * If the deletion is based on the issuer's certificate
2N/A * nickname, we will get the issuer's cert first, then
2N/A * get the CRL from the cert.
2N/A */
2N/A cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2N/A issuername);
2N/A if (!cert) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CERT_NOT_FOUND;
2N/A goto out;
2N/A }
2N/A
2N/A crl = SEC_FindCrlByName(certHandle, &cert->derSubject,
2N/A SEC_CRL_TYPE);
2N/A if (crl == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A goto out;
2N/A }
2N/A } else {
2N/A /*
2N/A * If the deletion is based on the CRL's subject name, we will
2N/A * get all the CRLs from the internal database and search
2N/A * for the CRL with the same subject name.
2N/A */
2N/A boolean_t found = B_FALSE;
2N/A int nssrv;
2N/A
2N/A nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2N/A if (nssrv) {
2N/A SET_ERROR(kmfh, nssrv);
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A goto out;
2N/A }
2N/A
2N/A if (crlList == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A goto out;
2N/A }
2N/A
2N/A /* Allocate space for name */
2N/A arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2N/A if (arena == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto out;
2N/A }
2N/A
2N/A name = PORT_ArenaZAlloc(arena, sizeof (*name));
2N/A if (name == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto out;
2N/A }
2N/A name->arena = arena;
2N/A
2N/A crlNode = crlList->first;
2N/A while (crlNode && !found) {
2N/A char *asciiname = NULL;
2N/A SECItem* issuer;
2N/A
2N/A name = &crlNode->crl->crl.name;
2N/A if (!name) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A break;
2N/A }
2N/A
2N/A asciiname = CERT_NameToAscii(name);
2N/A if (asciiname == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A break;
2N/A }
2N/A
2N/A if (strcmp(subjectname, asciiname) == 0) {
2N/A found = B_TRUE;
2N/A issuer = &crlNode->crl->crl.derName;
2N/A crl = SEC_FindCrlByName(certHandle, issuer,
2N/A SEC_CRL_TYPE);
2N/A if (crl == NULL) {
2N/A /* We found a cert but no CRL */
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A }
2N/A }
2N/A PORT_Free(asciiname);
2N/A crlNode = crlNode->next;
2N/A }
2N/A
2N/A if (rv) {
2N/A goto out;
2N/A }
2N/A }
2N/A
2N/A if (crl) {
2N/A (void) SEC_DeletePermCRL(crl);
2N/A }
2N/A
2N/Aout:
2N/A if (nss_slot != NULL) {
2N/A PK11_FreeSlot(nss_slot);
2N/A }
2N/A
2N/A if (crlList != NULL) {
2N/A PORT_FreeArena(crlList->arena, PR_FALSE);
2N/A }
2N/A
2N/A if (arena != NULL) {
2N/A PORT_FreeArena(arena, PR_FALSE);
2N/A }
2N/A
2N/A if (cert != NULL) {
2N/A CERT_DestroyCertificate(cert);
2N/A }
2N/A
2N/A if (crl != NULL) {
2N/A (void) SEC_DestroyCrl(crl);
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_FindCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A CERTCrlHeadNode *crlList = NULL;
2N/A CERTCrlNode *crlNode = NULL;
2N/A PRArenaPool *arena = NULL;
2N/A CERTName *name = NULL;
2N/A SECStatus nssrv;
2N/A char *asciiname = NULL;
2N/A int crl_num;
2N/A int i, *CRLCount;
2N/A CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2N/A char **CRLNameList;
2N/A
2N/A if (numattr == 0 || attrlist == NULL) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A CRLCount = kmf_get_attr_ptr(KMF_CRL_COUNT_ATTR, attrlist, numattr);
2N/A if (CRLCount == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A CRLNameList = (char **)kmf_get_attr_ptr(KMF_CRL_NAMELIST_ATTR,
2N/A attrlist, numattr);
2N/A
2N/A /* Look up Crls */
2N/A nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2N/A if (nssrv) {
2N/A SET_ERROR(kmfh, rv);
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A goto out;
2N/A }
2N/A
2N/A /* Allocate space for name first */
2N/A arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2N/A if (arena == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto out;
2N/A }
2N/A
2N/A name = PORT_ArenaZAlloc(arena, sizeof (*name));
2N/A if (name == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto out;
2N/A }
2N/A name->arena = arena;
2N/A
2N/A /*
2N/A * Loop thru the crlList and create a crl list with CRL's subject name.
2N/A */
2N/A crlNode = crlList->first;
2N/A crl_num = 0;
2N/A while (crlNode) {
2N/A char *subj_name;
2N/A
2N/A /* Get the CRL subject name */
2N/A name = &crlNode->crl->crl.name;
2N/A if (!name) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A break;
2N/A }
2N/A
2N/A
2N/A if (CRLNameList != NULL) {
2N/A asciiname = CERT_NameToAscii(name);
2N/A if (asciiname == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A break;
2N/A }
2N/A subj_name = strdup(asciiname);
2N/A PORT_Free(asciiname);
2N/A if (subj_name == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A break;
2N/A }
2N/A CRLNameList[crl_num] = subj_name;
2N/A }
2N/A
2N/A crl_num++;
2N/A crlNode = crlNode->next;
2N/A }
2N/A
2N/A if (rv == KMF_OK) {
2N/A /* success */
2N/A *CRLCount = crl_num;
2N/A }
2N/A
2N/Aout:
2N/A if (nss_slot != NULL) {
2N/A PK11_FreeSlot(nss_slot);
2N/A }
2N/A
2N/A if (crlList != NULL) {
2N/A PORT_FreeArena(crlList->arena, PR_FALSE);
2N/A }
2N/A
2N/A if (arena != NULL) {
2N/A PORT_FreeArena(arena, PR_FALSE);
2N/A }
2N/A
2N/A /* If failed, free memory allocated for the returning rlist */
2N/A if (rv && (CRLNameList != NULL)) {
2N/A for (i = 0; i < crl_num; i++) {
2N/A free(CRLNameList[i]);
2N/A }
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/ANSS_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A PK11SlotInfo *nss_slot = NULL;
2N/A CERTCertificate *cert = NULL;
2N/A CERTSignedCrl *crl = NULL;
2N/A CERTCrlEntry *entry;
2N/A boolean_t match = B_FALSE;
2N/A int i;
2N/A CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2N/A char *certlabel;
2N/A KMF_DATA *certdata;
2N/A
2N/A /* check params */
2N/A if (numattr == 0 || attrlist == NULL) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A
2N/A /* Find the certificate first */
2N/A if (certlabel != NULL) {
2N/A cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2N/A certlabel);
2N/A } else {
2N/A SECItem derCert = { NULL, 0};
2N/A
2N/A certdata = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR,
2N/A attrlist, numattr);
2N/A
2N/A if (certdata == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A derCert.data = certdata->Data;
2N/A derCert.len = certdata->Length;
2N/A
2N/A cert = CERT_FindCertByDERCert(certHandle, &derCert);
2N/A }
2N/A
2N/A if (cert == NULL) {
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CERT_NOT_FOUND;
2N/A goto out;
2N/A }
2N/A
2N/A /* Find the CRL with the same issuer as the given certificate. */
2N/A crl = SEC_FindCrlByName(certHandle, &cert->derIssuer, SEC_CRL_TYPE);
2N/A if (crl == NULL) {
2N/A /*
2N/A * Could not find the CRL issued by the same issuer. This
2N/A * usually means that the CRL is not installed in the DB.
2N/A */
2N/A SET_ERROR(kmfh, PORT_GetError());
2N/A rv = KMF_ERR_CRL_NOT_FOUND;
2N/A goto out;
2N/A
2N/A }
2N/A
2N/A /* Check if the certificate's serialNumber is revoked in the CRL */
2N/A i = 0;
2N/A while ((entry = (crl->crl).entries[i++]) != NULL) {
2N/A if (SECITEM_CompareItem(&(cert->serialNumber),
2N/A &(entry->serialNumber)) == SECEqual) {
2N/A match = B_TRUE;
2N/A break;
2N/A }
2N/A }
2N/A
2N/A if (!match) {
2N/A rv = KMF_ERR_NOT_REVOKED;
2N/A }
2N/A
2N/Aout:
2N/A if (nss_slot != NULL) {
2N/A PK11_FreeSlot(nss_slot);
2N/A }
2N/A
2N/A if (cert != NULL) {
2N/A CERT_DestroyCertificate(cert);
2N/A }
2N/A
2N/A if (crl != NULL) {
2N/A (void) SEC_DestroyCrl(crl);
2N/A }
2N/A
2N/A return (rv);
2N/A}