elfcertlib.c revision 8bab47abcb471dffa36ddbf409a8ef5303398ddf
1N/A/*
1N/A * CDDL HEADER START
1N/A *
1N/A * The contents of this file are subject to the terms of the
1N/A * Common Development and Distribution License (the "License").
1N/A * You may not use this file except in compliance with the License.
1N/A *
1N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1N/A * or http://www.opensolaris.org/os/licensing.
1N/A * See the License for the specific language governing permissions
1N/A * and limitations under the License.
1N/A *
1N/A * When distributing Covered Code, include this CDDL HEADER in each
1N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1N/A * If applicable, add the following below this CDDL HEADER, with the
1N/A * fields enclosed by brackets "[]" replaced with your own identifying
1N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1N/A *
1N/A * CDDL HEADER END
1N/A */
1N/A
1N/A/*
1N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
1N/A * Use is subject to license terms.
1N/A */
1N/A
1N/A#include <limits.h>
1N/A#include <sys/types.h>
1N/A#include <sys/stat.h>
1N/A#include <fcntl.h>
1N/A#include <unistd.h>
1N/A#include <dirent.h>
1N/A#include <strings.h>
1N/A#include <stdio.h>
1N/A#include <stdlib.h>
1N/A#include <errno.h>
1N/A#include <sys/mman.h>
1N/A#include <md5.h>
1N/A#include <pthread.h>
1N/A
1N/A#include <cryptoutil.h>
1N/A
1N/A#include <kmfapi.h>
1N/A#include <sys/crypto/elfsign.h>
1N/A#include <libelfsign.h>
1N/A
1N/A#include <synch.h>
1N/A
1N/Aconst char _PATH_ELFSIGN_CRYPTO_CERTS[] = CRYPTO_CERTS_DIR;
1N/Aconst char _PATH_ELFSIGN_ETC_CERTS[] = ETC_CERTS_DIR;
1N/A
1N/A/*
1N/A * The CACERT and OBJCACERT are the Cryptographic Trust Anchors
1N/A * for the Solaris Cryptographic Framework.
1N/A */
1N/Astatic const char _PATH_CRYPTO_CACERT[] = CRYPTO_CERTS_DIR "/CA";
1N/Astatic const char _PATH_CRYPTO_OBJCACERT[] = CRYPTO_CERTS_DIR "/SUNWObjectCA";
1N/Astatic ELFCert_t CACERT = NULL;
1N/Astatic ELFCert_t OBJCACERT = NULL;
1N/Astatic pthread_mutex_t ca_mutex = PTHREAD_MUTEX_INITIALIZER;
1N/A
1N/Astatic void elfcertlib_freecert(ELFsign_t, ELFCert_t);
1N/Astatic ELFCert_t elfcertlib_allocatecert(void);
1N/A
1N/A/*
1N/A * elfcertlib_verifycert - Verify the Cert with a Trust Anchor
1N/A *
1N/A * IN ess - elfsign context structure
1N/A * cert
1N/A * OUT NONE
1N/A * RETURN TRUE/FALSE
1N/A *
1N/A * We first setup the Trust Anchor (CA and SUNWObjectCA) certs
1N/A * if it hasn't been done already. We verify that the files on disk
1N/A * are those we expected.
1N/A *
1N/A * We then verify the given cert using the publickey of a TA.
1N/A * If the passed in cert is a TA or it has been verified already we
1N/A * short cut and return TRUE without futher validation.
1N/A */
1N/A/*ARGSUSED*/
1N/Aboolean_t
1N/Aelfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert)
1N/A{
1N/A KMF_ATTRIBUTE attrlist[8];
1N/A int numattr;
1N/A
1N/A KMF_RETURN rv;
1N/A if ((cert->c_verified == E_OK) || (cert->c_verified == E_IS_TA)) {
1N/A return (B_TRUE);
1N/A }
1N/A
1N/A (void) pthread_mutex_lock(&ca_mutex);
1N/A if (CACERT == NULL) {
1N/A (void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT,
1N/A NULL, &CACERT, ES_GET);
1N/A }
1N/A if (OBJCACERT == NULL) {
1N/A (void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT,
1N/A NULL, &OBJCACERT, ES_GET);
1N/A }
1N/A (void) pthread_mutex_unlock(&ca_mutex);
1N/A
1N/A if (CACERT != NULL) {
1N/A numattr = 0;
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
1N/A sizeof (KMF_DATA));
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_SIGNER_CERT_DATA_ATTR, &CACERT->c_cert.certificate,
1N/A sizeof (KMF_DATA));
1N/A
1N/A rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
1N/A if (rv == KMF_OK) {
1N/A if (ess->es_certCAcallback != NULL)
1N/A (ess->es_certvercallback)(ess->es_callbackctx,
1N/A cert, CACERT);
1N/A cert->c_verified = E_OK;
1N/A return (B_TRUE);
1N/A }
1N/A }
1N/A
1N/A if (OBJCACERT != NULL) {
1N/A numattr = 0;
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
1N/A sizeof (KMF_DATA));
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_SIGNER_CERT_DATA_ATTR, &OBJCACERT->c_cert.certificate,
1N/A sizeof (KMF_DATA));
1N/A
1N/A rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
1N/A if (rv == KMF_OK) {
1N/A if (ess->es_certCAcallback != NULL)
1N/A (ess->es_certvercallback)(ess->es_callbackctx,
1N/A cert, OBJCACERT);
1N/A cert->c_verified = E_OK;
1N/A return (B_TRUE);
1N/A }
1N/A }
1N/A
1N/A return (B_FALSE);
1N/A}
1N/A
1N/A/*
1N/A * elfcertlib_getcert - Get the certificate for signer_DN
1N/A *
1N/A * IN ess - elfsign context structure
1N/A * cert_pathname - path to cert (May be NULL)
1N/A * signer_DN - The DN we are looking for (May be NULL)
1N/A * action - indicates crypto verification call
1N/A * OUT certp - allocated/loaded ELFCert_t
1N/A *
1N/A * If the cert_pathname is passed use it and don't search.
1N/A * Otherwise, go looking in certificate directories
1N/A */
1N/Aboolean_t
1N/Aelfcertlib_getcert(ELFsign_t ess, char *cert_pathname,
1N/A char *signer_DN, ELFCert_t *certp, enum ES_ACTION action)
1N/A{
1N/A KMF_RETURN rv;
1N/A ELFCert_t cert = NULL;
1N/A KMF_X509_DER_CERT certbuf[2];
1N/A uint32_t ncerts;
1N/A boolean_t ret = B_FALSE;
1N/A char *pathlist[3], **plp;
1N/A
1N/A cryptodebug("elfcertlib_getcert: path=%s, DN=%s",
1N/A cert_pathname ? cert_pathname : "-none-",
1N/A signer_DN ? signer_DN : "-none-");
1N/A *certp = NULL;
1N/A if (cert_pathname == NULL && signer_DN == NULL) {
1N/A cryptodebug("elfcertlib_getcert: lack of specificity");
1N/A return (ret);
1N/A }
1N/A
1N/A plp = pathlist;
1N/A if (cert_pathname != NULL) {
1N/A /* look in the specified object */
1N/A *plp++ = cert_pathname;
1N/A } else {
1N/A /* look in the certificate directories */
1N/A *plp++ = (char *)_PATH_ELFSIGN_CRYPTO_CERTS;
1N/A /*
1N/A * crypto verifications don't search beyond
1N/A * _PATH_ELFSIGN_CRYPTO_CERTS
1N/A */
1N/A if (action != ES_GET_CRYPTO)
1N/A *plp++ = (char *)_PATH_ELFSIGN_ETC_CERTS;
1N/A }
1N/A *plp = NULL;
1N/A
1N/A if ((cert = elfcertlib_allocatecert()) == NULL) {
1N/A return (ret);
1N/A }
1N/A
1N/A for (plp = pathlist; *plp; plp++) {
1N/A KMF_ATTRIBUTE attrlist[8];
1N/A KMF_KEYSTORE_TYPE kstype;
1N/A KMF_CERT_VALIDITY certvalidity;
1N/A int numattr;
1N/A
1N/A kstype = KMF_KEYSTORE_OPENSSL;
1N/A certvalidity = KMF_ALL_CERTS;
1N/A ncerts = 2;
1N/A
1N/A numattr = 0;
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_X509_DER_CERT_ATTR, certbuf,
1N/A sizeof (KMF_X509_DER_CERT));
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_COUNT_ATTR, &ncerts, sizeof (uint32_t));
1N/A if (signer_DN != NULL) {
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_SUBJECT_NAME_ATTR, signer_DN,
1N/A strlen(signer_DN));
1N/A }
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_CERT_VALIDITY_ATTR, &certvalidity,
1N/A sizeof (KMF_CERT_VALIDITY));
1N/A kmf_set_attr_at_index(attrlist, numattr++,
1N/A KMF_CERT_FILENAME_ATTR, *plp, strlen (*plp));
1N/A
1N/A rv = kmf_find_cert(ess->es_kmfhandle, numattr, attrlist);
1N/A
1N/A if (rv != KMF_OK)
1N/A continue;
1N/A /* found one */
1N/A cert->c_cert = certbuf[0];
1N/A if (ncerts > 1) {
1N/A /* release any extras */
1N/A kmf_free_kmf_cert(ess->es_kmfhandle, &certbuf[1]);
1N/A if (signer_DN == NULL) {
1N/A /* There can be only one */
1N/A cryptodebug("elfcertlib_getcert: "
1N/A "too many certificates found in %s",
1N/A cert_pathname);
1N/A goto cleanup;
1N/A }
1N/A }
1N/A /* cache subject and issuer */
1N/A rv = kmf_get_cert_subject_str(ess->es_kmfhandle,
1N/A &cert->c_cert.certificate, &cert->c_subject);
1N/A if (rv != KMF_OK)
1N/A goto cleanup;
1N/A
1N/A rv = kmf_get_cert_issuer_str(ess->es_kmfhandle,
1N/A &cert->c_cert.certificate, &cert->c_issuer);
1N/A if (rv != KMF_OK)
1N/A goto cleanup;
1N/A break;
1N/A }
1N/A if (*plp == NULL) {
1N/A cryptodebug("elfcertlib_getcert: no certificate found");
1N/A goto cleanup;
1N/A }
1N/A
1N/A cert->c_verified = E_UNCHECKED;
1N/A
1N/A /*
1N/A * If the cert we are loading is the trust anchor (ie the CA) then
1N/A * we mark it as such in cert. This is so that we don't attempt
1N/A * to verify it later. The CA is always implicitly verified.
1N/A */
1N/A if (cert_pathname != NULL && (
1N/A strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 ||
1N/A strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0)) {
1N/A if (ess->es_certCAcallback != NULL)
1N/A (ess->es_certCAcallback)(ess->es_callbackctx, cert,
1N/A cert_pathname);
1N/A cert->c_verified = E_IS_TA;
1N/A }
1N/A
1N/A ret = B_TRUE;
1N/A
1N/Acleanup:
1N/A if (ret) {
1N/A *certp = cert;
1N/A } else {
1N/A if (cert != NULL)
1N/A elfcertlib_freecert(ess, cert);
1N/A if (signer_DN != NULL)
1N/A cryptoerror(LOG_ERR, "unable to find a certificate "
1N/A "for DN: %s", signer_DN);
1N/A else
1N/A cryptoerror(LOG_ERR, "unable to load certificate "
1N/A "from %s", cert_pathname);
1N/A }
1N/A return (ret);
1N/A}
1N/A
1N/A/*
1N/A * elfcertlib_loadprivatekey - Load the private key from path
1N/A *
1N/A * IN ess - elfsign context structure
1N/A * cert
1N/A * pathname
1N/A * OUT cert
1N/A * RETURNS TRUE/FALSE
1N/A */
1N/Aboolean_t
1N/Aelfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname)
1N/A{
1N/A KMF_RETURN rv = KMF_OK;
1N/A KMF_KEY_HANDLE keybuf[2];
1N/A KMF_ATTRIBUTE attrlist[16];
1N/A uint32_t nkeys;
1N/A KMF_KEYSTORE_TYPE kstype;
1N/A KMF_KEY_ALG keytype;
1N/A KMF_KEY_CLASS keyclass;
1N/A KMF_ENCODE_FORMAT format;
1N/A int numattr;
1N/A
1N/A kstype = KMF_KEYSTORE_OPENSSL;
1N/A nkeys = 2;
1N/A keytype = KMF_KEYALG_NONE;
1N/A keyclass = KMF_ASYM_PRI;
1N/A format = KMF_FORMAT_UNDEF;
1N/A
1N/A numattr = 0;
1N/A kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
&kstype, sizeof (kstype));
kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
keybuf, sizeof (KMF_KEY_HANDLE));
kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
&nkeys, sizeof (uint32_t));
kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
&keytype, sizeof (keytype));
kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
&keyclass, sizeof (keyclass));
kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
&format, sizeof (format));
kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_FILENAME_ATTR,
(char *)pathname, strlen(pathname));
rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
if (rv != KMF_OK)
return (B_FALSE);
if (nkeys != 1) {
/* lack of specificity */
cryptodebug("found %d keys at %s", nkeys, pathname);
return (B_FALSE);
}
cert->c_privatekey = keybuf[0];
cryptodebug("key %s loaded", pathname);
return (B_TRUE);
}
/*
* elfcertlib_loadtokenkey - Load the private key from token
*
* IN ess - elfsign context structure
* cert
* token_label
* pin
* OUT cert
* RETURNS TRUE/FALSE
*/
boolean_t
elfcertlib_loadtokenkey(ELFsign_t ess, ELFCert_t cert,
const char *token_label, const char *pin)
{
KMF_RETURN rv;
char *idstr = NULL;
char *kmferr;
KMF_ATTRIBUTE attrlist[16];
uint32_t nkeys;
KMF_KEYSTORE_TYPE kstype;
KMF_KEY_ALG keytype;
KMF_KEY_CLASS keyclass;
KMF_ENCODE_FORMAT format;
KMF_CREDENTIAL pincred;
boolean_t tokenbool, privatebool;
int numattr;
/*
* We will search for the key based on the ID attribute
* which was added when the key was created. ID is
* a SHA-1 hash of the public modulus shared by the
* key and the certificate.
*/
rv = kmf_get_cert_id_str(&cert->c_cert.certificate, &idstr);
if (rv != KMF_OK) {
(void) kmf_get_kmf_error_str(rv, &kmferr);
cryptodebug("Error getting ID from cert: %s\n",
(kmferr ? kmferr : "Unrecognized KMF error"));
free(kmferr);
return (B_FALSE);
}
kstype = KMF_KEYSTORE_PK11TOKEN;
nkeys = 1;
keytype = KMF_KEYALG_NONE;
keyclass = KMF_ASYM_PRI;
format = KMF_FORMAT_UNDEF;
pincred.cred = (char *)pin;
pincred.credlen = strlen(pin);
tokenbool = B_FALSE;
privatebool = B_TRUE;
numattr = 0;
kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
&kstype, sizeof (kstype));
kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
&cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
&nkeys, sizeof (uint32_t));
kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
&keytype, sizeof (keytype));
kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
&keyclass, sizeof (keyclass));
kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
&format, sizeof (format));
kmf_set_attr_at_index(attrlist, numattr++, KMF_IDSTR_ATTR,
idstr, strlen(idstr));
kmf_set_attr_at_index(attrlist, numattr++, KMF_CREDENTIAL_ATTR,
&pincred, sizeof (KMF_CREDENTIAL));
kmf_set_attr_at_index(attrlist, numattr++, KMF_TOKEN_BOOL_ATTR,
&tokenbool, sizeof (tokenbool));
kmf_set_attr_at_index(attrlist, numattr++, KMF_PRIVATE_BOOL_ATTR,
&privatebool, sizeof (privatebool));
rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
free(idstr);
if (rv != KMF_OK) {
(void) kmf_get_kmf_error_str(rv, &kmferr);
cryptodebug("Error finding private key: %s\n",
(kmferr ? kmferr : "Unrecognized KMF error"));
free(kmferr);
return (B_FALSE);
}
if (nkeys != 1) {
cryptodebug("Error finding private key: No key found\n");
return (B_FALSE);
}
cryptodebug("key found in %s", token_label);
cryptodebug("elfcertlib_loadprivatekey = 0x%.8X",
&cert->c_privatekey);
return (B_TRUE);
}
static const CK_BYTE MD5_DER_PREFIX[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
/*
* elfcertlib_sign - sign the given DATA using the privatekey in cert
*
* IN ess - elfsign context structure
* cert
* data
* data_len
* OUT sig - must be big enough to hold the signature of data
* Caller must allocate
* sig_len - actual length used; 0 on failure.
* RETURNS TRUE/FALSE
*/
/*ARGSUSED*/
boolean_t
elfcertlib_sign(ELFsign_t ess, ELFCert_t cert,
const uchar_t *data, size_t data_len,
uchar_t *sig, size_t *sig_len)
{
KMF_RETURN ret;
KMF_DATA tobesigned;
KMF_DATA signature;
uchar_t der_data[sizeof (MD5_DER_PREFIX) + MD5_DIGEST_LENGTH];
KMF_ATTRIBUTE attrlist[8];
int numattr;
if (ess->es_version <= FILESIG_VERSION2) {
/* compatibility: take MD5 hash of SHA1 hash */
size_t derlen = MD5_DIGEST_LENGTH;
MD5_CTX ctx;
/*
* first: digest using software-based methods, don't
* rely on the token for hashing.
*/
MD5Init(&ctx);
MD5Update(&ctx, data, data_len);
MD5Final(&der_data[sizeof (MD5_DER_PREFIX)], &ctx);
/*
* second: insert prefix
*/
(void) memcpy(der_data, MD5_DER_PREFIX,
sizeof (MD5_DER_PREFIX));
/*
* prepare to sign the local buffer
*/
tobesigned.Data = (uchar_t *)der_data;
tobesigned.Length = sizeof (MD5_DER_PREFIX) + derlen;
} else {
tobesigned.Data = (uchar_t *)data;
tobesigned.Length = data_len;
}
signature.Data = (uchar_t *)sig;
signature.Length = *sig_len;
numattr = 0;
kmf_set_attr_at_index(attrlist, numattr++,
KMF_KEYSTORE_TYPE_ATTR, &(cert->c_privatekey.kstype),
sizeof (KMF_KEYSTORE_TYPE));
kmf_set_attr_at_index(attrlist, numattr++,
KMF_KEY_HANDLE_ATTR, &cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
kmf_set_attr_at_index(attrlist, numattr++,
KMF_OID_ATTR, (KMF_OID *)&KMFOID_RSA, sizeof (KMF_OID));
kmf_set_attr_at_index(attrlist, numattr++,
KMF_DATA_ATTR, &tobesigned, sizeof (KMF_DATA));
kmf_set_attr_at_index(attrlist, numattr++,
KMF_OUT_DATA_ATTR, &signature, sizeof (KMF_DATA));
ret = kmf_sign_data(ess->es_kmfhandle, numattr, attrlist);
if (ret != KMF_OK) {
char *kmferr;
(void) kmf_get_kmf_error_str(ret, &kmferr);
cryptodebug("Error signing data: %s\n",
(kmferr ? kmferr : "Unrecognized KMF error"));
free(kmferr);
*sig_len = 0;
return (B_FALSE);
}
*sig_len = signature.Length;
return (B_TRUE);
}
/*
* elfcertlib_verifysig - verify the given DATA using the public key in cert
*
* IN ess - elfsign context structure
* cert
* signature
* sig_len
* data
* data_len
* OUT N/A
* RETURNS TRUE/FALSE
*/
boolean_t
elfcertlib_verifysig(ELFsign_t ess, ELFCert_t cert,
const uchar_t *signature, size_t sig_len,
const uchar_t *data, size_t data_len)
{
KMF_RETURN rv;
KMF_DATA indata;
KMF_DATA insig;
KMF_ALGORITHM_INDEX algid;
KMF_ATTRIBUTE attrlist[8];
KMF_KEYSTORE_TYPE kstype;
int numattr;
indata.Data = (uchar_t *)data;
indata.Length = data_len;
insig.Data = (uchar_t *)signature;
insig.Length = sig_len;
if (ess->es_version <= FILESIG_VERSION2)
algid = KMF_ALGID_MD5WithRSA;
else
algid = KMF_ALGID_RSA;
/*
* We tell KMF to use the PKCS11 verification APIs
* here to prevent the use of OpenSSL and to keep
* all validation within the FIPS-140 boundary for
* the Cryptographic Framework.
*/
kstype = KMF_KEYSTORE_PK11TOKEN;
numattr = 0;
kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
&kstype, sizeof (kstype));
kmf_set_attr_at_index(attrlist, numattr++, KMF_DATA_ATTR,
&indata, sizeof (KMF_DATA));
kmf_set_attr_at_index(attrlist, numattr++, KMF_IN_SIGN_ATTR,
&insig, sizeof (KMF_DATA));
kmf_set_attr_at_index(attrlist, numattr++, KMF_SIGNER_CERT_DATA_ATTR,
(KMF_DATA *)(&cert->c_cert.certificate), sizeof (KMF_DATA));
kmf_set_attr_at_index(attrlist, numattr++, KMF_ALGORITHM_INDEX_ATTR,
&algid, sizeof (algid));
rv = kmf_verify_data(ess->es_kmfhandle, numattr, attrlist);
return ((rv == KMF_OK));
}
/*
* elfcertlib_getdn
*
* IN cert
* OUT NONE
* RETURN dn or NULL
*/
char *
elfcertlib_getdn(ELFCert_t cert)
{
cryptodebug("elfcertlib_getdn");
return (cert->c_subject);
}
/*
* elfcertlib_getissuer
*
* IN cert
* OUT NONE
* RETURN dn or NULL
*/
char *
elfcertlib_getissuer(ELFCert_t cert)
{
cryptodebug("elfcertlib_issuer");
return (cert->c_issuer);
}
boolean_t
elfcertlib_init(ELFsign_t ess)
{
boolean_t rc = B_TRUE;
KMF_RETURN rv;
if (ess->es_kmfhandle == NULL) {
rv = kmf_initialize(&ess->es_kmfhandle, NULL, NULL);
if (rv != KMF_OK) {
cryptoerror(LOG_ERR,
"unable to initialize KMF library");
rc = B_FALSE;
}
}
return (rc);
}
void
elfcertlib_fini(ELFsign_t ess)
{
(void) kmf_finalize(ess->es_kmfhandle);
}
/*
* set the token device
*/
boolean_t
elfcertlib_settoken(ELFsign_t ess, char *token)
{
boolean_t rc = B_TRUE;
KMF_RETURN rv;
KMF_ATTRIBUTE attrlist[8];
KMF_KEYSTORE_TYPE kstype;
boolean_t readonly;
int numattr;
kstype = KMF_KEYSTORE_PK11TOKEN;
readonly = B_TRUE;
numattr = 0;
kmf_set_attr_at_index(attrlist, numattr++,
KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
kmf_set_attr_at_index(attrlist, numattr++,
KMF_TOKEN_LABEL_ATTR, token, strlen(token));
kmf_set_attr_at_index(attrlist, numattr++,
KMF_READONLY_ATTR, &readonly, sizeof (readonly));
rv = kmf_configure_keystore(ess->es_kmfhandle, numattr, attrlist);
if (rv != KMF_OK) {
cryptoerror(LOG_ERR, "unable to select token\n");
rc = B_FALSE;
}
return (rc);
}
/*
* set the certificate CA identification callback
*/
void
elfcertlib_setcertCAcallback(ELFsign_t ess,
void (*cb)(void *, ELFCert_t, char *))
{
ess->es_certCAcallback = cb;
}
/*
* set the certificate verification callback
*/
void
elfcertlib_setcertvercallback(ELFsign_t ess,
void (*cb)(void *, ELFCert_t, ELFCert_t))
{
ess->es_certvercallback = cb;
}
/*
* elfcertlib_releasecert - release a cert
*
* IN cert
* OUT cert
* RETURN N/A
*
*/
void
elfcertlib_releasecert(ELFsign_t ess, ELFCert_t cert)
{
elfcertlib_freecert(ess, cert);
}
/*
* elfcertlib_allocatecert - create a new ELFCert_t
*
* IN N/A
* OUT N/A
* RETURN ELFCert_t, NULL on failure.
*/
static ELFCert_t
elfcertlib_allocatecert(void)
{
ELFCert_t cert = NULL;
cert = malloc(sizeof (struct ELFCert_s));
if (cert == NULL) {
cryptoerror(LOG_ERR,
"elfcertlib_allocatecert: malloc failed %s",
strerror(errno));
return (NULL);
}
(void) memset(cert, 0, sizeof (struct ELFCert_s));
cert->c_verified = E_UNCHECKED;
cert->c_subject = NULL;
cert->c_issuer = NULL;
return (cert);
}
/*
* elfcertlib_freecert - freeup the memory of a cert
*
* IN cert
* OUT cert
* RETURN N/A
*
*/
static void
elfcertlib_freecert(ELFsign_t ess, ELFCert_t cert)
{
if (cert == NULL)
return;
free(cert->c_subject);
free(cert->c_issuer);
kmf_free_kmf_cert(ess->es_kmfhandle, &cert->c_cert);
kmf_free_kmf_key(ess->es_kmfhandle, &cert->c_privatekey);
free(cert);
}