15194Sjohnz /*
25194Sjohnz  * CDDL HEADER START
35194Sjohnz  *
45194Sjohnz  * The contents of this file are subject to the terms of the
55194Sjohnz  * Common Development and Distribution License (the "License").
65194Sjohnz  * You may not use this file except in compliance with the License.
75194Sjohnz  *
85194Sjohnz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95194Sjohnz  * or http://www.opensolaris.org/os/licensing.
105194Sjohnz  * See the License for the specific language governing permissions
115194Sjohnz  * and limitations under the License.
125194Sjohnz  *
135194Sjohnz  * When distributing Covered Code, include this CDDL HEADER in each
145194Sjohnz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155194Sjohnz  * If applicable, add the following below this CDDL HEADER, with the
165194Sjohnz  * fields enclosed by brackets "[]" replaced with your own identifying
175194Sjohnz  * information: Portions Copyright [yyyy] [name of copyright owner]
185194Sjohnz  *
195194Sjohnz  * CDDL HEADER END
205194Sjohnz  */
215194Sjohnz 
225194Sjohnz /*
2310123SValerie.Fenwick@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245194Sjohnz  * Use is subject to license terms.
255194Sjohnz  */
265194Sjohnz 
275194Sjohnz #include <limits.h>
285194Sjohnz #include <sys/types.h>
295194Sjohnz #include <sys/stat.h>
305194Sjohnz #include <fcntl.h>
315194Sjohnz #include <unistd.h>
325194Sjohnz #include <dirent.h>
335194Sjohnz #include <strings.h>
345194Sjohnz #include <stdio.h>
355194Sjohnz #include <stdlib.h>
365194Sjohnz #include <errno.h>
375194Sjohnz #include <sys/mman.h>
385194Sjohnz #include <md5.h>
395194Sjohnz #include <pthread.h>
405194Sjohnz 
415194Sjohnz #include <cryptoutil.h>
425194Sjohnz 
435194Sjohnz #include <kmfapi.h>
445194Sjohnz #include <sys/crypto/elfsign.h>
455194Sjohnz #include <libelfsign.h>
465194Sjohnz 
475194Sjohnz #include <synch.h>
485194Sjohnz 
495194Sjohnz const char _PATH_ELFSIGN_CRYPTO_CERTS[] = CRYPTO_CERTS_DIR;
505194Sjohnz const char _PATH_ELFSIGN_ETC_CERTS[] = ETC_CERTS_DIR;
515194Sjohnz 
525194Sjohnz /*
535194Sjohnz  * The CACERT and OBJCACERT are the Cryptographic Trust Anchors
545194Sjohnz  * for the Solaris Cryptographic Framework.
55*10732SAnthony.Scarpino@Sun.COM  *
56*10732SAnthony.Scarpino@Sun.COM  * The SECACERT is the Signed Execution Trust Anchor that the
57*10732SAnthony.Scarpino@Sun.COM  * Cryptographic Framework uses for FIPS-140 validation of non-crypto
58*10732SAnthony.Scarpino@Sun.COM  * binaries
595194Sjohnz  */
605194Sjohnz static const char _PATH_CRYPTO_CACERT[] = CRYPTO_CERTS_DIR "/CA";
615194Sjohnz static const char _PATH_CRYPTO_OBJCACERT[] = CRYPTO_CERTS_DIR "/SUNWObjectCA";
62*10732SAnthony.Scarpino@Sun.COM static const char _PATH_CRYPTO_SECACERT[] = ETC_CERTS_DIR "/SUNWSolarisCA";
635194Sjohnz static ELFCert_t CACERT = NULL;
645194Sjohnz static ELFCert_t OBJCACERT = NULL;
65*10732SAnthony.Scarpino@Sun.COM static ELFCert_t SECACERT = NULL;
665194Sjohnz static pthread_mutex_t ca_mutex = PTHREAD_MUTEX_INITIALIZER;
675194Sjohnz 
685194Sjohnz static void elfcertlib_freecert(ELFsign_t, ELFCert_t);
695194Sjohnz static ELFCert_t elfcertlib_allocatecert(void);
705194Sjohnz 
715194Sjohnz /*
725194Sjohnz  * elfcertlib_verifycert - Verify the Cert with a Trust Anchor
735194Sjohnz  *
745194Sjohnz  * IN	ess		- elfsign context structure
755194Sjohnz  *	cert
765194Sjohnz  * OUT	NONE
775194Sjohnz  * RETURN	TRUE/FALSE
785194Sjohnz  *
795194Sjohnz  * We first setup the Trust Anchor (CA and SUNWObjectCA) certs
805194Sjohnz  * if it hasn't been done already.  We verify that the files on disk
815194Sjohnz  * are those we expected.
825194Sjohnz  *
835194Sjohnz  * We then verify the given cert using the publickey of a TA.
845194Sjohnz  * If the passed in cert is a TA or it has been verified already we
855194Sjohnz  * short cut and return TRUE without futher validation.
865194Sjohnz  */
875194Sjohnz /*ARGSUSED*/
885194Sjohnz boolean_t
895194Sjohnz elfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert)
905194Sjohnz {
9110671SJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
9210671SJohn.Zolnowsky@Sun.COM 	int		numattr;
9310671SJohn.Zolnowsky@Sun.COM 
945194Sjohnz 	KMF_RETURN rv;
955194Sjohnz 	if ((cert->c_verified == E_OK) || (cert->c_verified == E_IS_TA)) {
965194Sjohnz 		return (B_TRUE);
975194Sjohnz 	}
985194Sjohnz 
995194Sjohnz 	(void) pthread_mutex_lock(&ca_mutex);
1005194Sjohnz 	if (CACERT == NULL) {
1015194Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT,
1025194Sjohnz 		    NULL, &CACERT, ES_GET);
1035194Sjohnz 	}
104*10732SAnthony.Scarpino@Sun.COM 
1055194Sjohnz 	if (OBJCACERT == NULL) {
1065194Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT,
1075194Sjohnz 		    NULL, &OBJCACERT, ES_GET);
1085194Sjohnz 	}
109*10732SAnthony.Scarpino@Sun.COM 
110*10732SAnthony.Scarpino@Sun.COM 	if (SECACERT == NULL) {
111*10732SAnthony.Scarpino@Sun.COM 		(void) elfcertlib_getcert(ess,
112*10732SAnthony.Scarpino@Sun.COM 		    (char *)_PATH_CRYPTO_SECACERT, NULL, &SECACERT,
113*10732SAnthony.Scarpino@Sun.COM 		    ES_GET_FIPS140);
114*10732SAnthony.Scarpino@Sun.COM 	}
115*10732SAnthony.Scarpino@Sun.COM 
1165194Sjohnz 	(void) pthread_mutex_unlock(&ca_mutex);
1175194Sjohnz 
1185194Sjohnz 	if (CACERT != NULL) {
11910671SJohn.Zolnowsky@Sun.COM 		numattr = 0;
12010671SJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
12110671SJohn.Zolnowsky@Sun.COM 		    KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
12210671SJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
12310671SJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
12410671SJohn.Zolnowsky@Sun.COM 		    KMF_SIGNER_CERT_DATA_ATTR, &CACERT->c_cert.certificate,
12510671SJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
12610671SJohn.Zolnowsky@Sun.COM 
12710671SJohn.Zolnowsky@Sun.COM 		rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
1285194Sjohnz 		if (rv == KMF_OK) {
1295194Sjohnz 			if (ess->es_certCAcallback != NULL)
1305194Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
1315194Sjohnz 				    cert, CACERT);
1325194Sjohnz 			cert->c_verified = E_OK;
1335194Sjohnz 			return (B_TRUE);
1345194Sjohnz 		}
1355194Sjohnz 	}
1365194Sjohnz 
1375194Sjohnz 	if (OBJCACERT != NULL) {
13810671SJohn.Zolnowsky@Sun.COM 		numattr = 0;
13910671SJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
14010671SJohn.Zolnowsky@Sun.COM 		    KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
14110671SJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
14210671SJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
14310671SJohn.Zolnowsky@Sun.COM 		    KMF_SIGNER_CERT_DATA_ATTR, &OBJCACERT->c_cert.certificate,
14410671SJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
14510671SJohn.Zolnowsky@Sun.COM 
14610671SJohn.Zolnowsky@Sun.COM 		rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
1475194Sjohnz 		if (rv == KMF_OK) {
1485194Sjohnz 			if (ess->es_certCAcallback != NULL)
1495194Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
1505194Sjohnz 				    cert, OBJCACERT);
1515194Sjohnz 			cert->c_verified = E_OK;
1525194Sjohnz 			return (B_TRUE);
1535194Sjohnz 		}
1545194Sjohnz 	}
1555194Sjohnz 
156*10732SAnthony.Scarpino@Sun.COM 	if (SECACERT != NULL) {
157*10732SAnthony.Scarpino@Sun.COM 		rv = KMF_VerifyCertWithCert(ess->es_kmfhandle,
158*10732SAnthony.Scarpino@Sun.COM 		    (const KMF_DATA *)&cert->c_cert,
159*10732SAnthony.Scarpino@Sun.COM 		    (const KMF_DATA *)&SECACERT->c_cert.certificate);
160*10732SAnthony.Scarpino@Sun.COM 		if (rv == KMF_OK) {
161*10732SAnthony.Scarpino@Sun.COM 			if (ess->es_certCAcallback != NULL)
162*10732SAnthony.Scarpino@Sun.COM 				(ess->es_certvercallback)(ess->es_callbackctx,
163*10732SAnthony.Scarpino@Sun.COM 				    cert, SECACERT);
164*10732SAnthony.Scarpino@Sun.COM 			cert->c_verified = E_OK;
165*10732SAnthony.Scarpino@Sun.COM 			return (B_TRUE);
166*10732SAnthony.Scarpino@Sun.COM 		}
167*10732SAnthony.Scarpino@Sun.COM 	}
168*10732SAnthony.Scarpino@Sun.COM 
1695194Sjohnz 	return (B_FALSE);
1705194Sjohnz }
1715194Sjohnz 
1725194Sjohnz /*
1735194Sjohnz  * elfcertlib_getcert - Get the certificate for signer_DN
1745194Sjohnz  *
1755194Sjohnz  * IN	ess		- elfsign context structure
1765194Sjohnz  *	cert_pathname	- path to cert (May be NULL)
1775194Sjohnz  *	signer_DN	- The DN we are looking for (May be NULL)
1785194Sjohnz  *      action		- indicates crypto verification call
1795194Sjohnz  * OUT  certp		- allocated/loaded ELFCert_t
1805194Sjohnz  *
1815194Sjohnz  * If the cert_pathname is passed use it and don't search.
1825194Sjohnz  * Otherwise, go looking in certificate directories
1835194Sjohnz  */
1845194Sjohnz boolean_t
1855194Sjohnz elfcertlib_getcert(ELFsign_t ess, char *cert_pathname,
1865194Sjohnz     char *signer_DN, ELFCert_t *certp, enum ES_ACTION action)
1875194Sjohnz {
1885194Sjohnz 	KMF_RETURN rv;
1895194Sjohnz 	ELFCert_t	cert = NULL;
1905194Sjohnz 	KMF_X509_DER_CERT certbuf[2];
1915194Sjohnz 	uint32_t ncerts;
1925194Sjohnz 	boolean_t ret = B_FALSE;
1935194Sjohnz 	char	*pathlist[3], **plp;
1945194Sjohnz 
1955194Sjohnz 	cryptodebug("elfcertlib_getcert: path=%s, DN=%s",
1965194Sjohnz 	    cert_pathname ? cert_pathname : "-none-",
1975194Sjohnz 	    signer_DN ? signer_DN : "-none-");
1985194Sjohnz 	*certp = NULL;
1995194Sjohnz 	if (cert_pathname == NULL && signer_DN == NULL) {
2005194Sjohnz 		cryptodebug("elfcertlib_getcert: lack of specificity");
2015194Sjohnz 		return (ret);
2025194Sjohnz 	}
2035194Sjohnz 
2045194Sjohnz 	plp = pathlist;
2055194Sjohnz 	if (cert_pathname != NULL) {
2065194Sjohnz 		/* look in the specified object */
2075194Sjohnz 		*plp++ = cert_pathname;
2085194Sjohnz 	} else {
2095194Sjohnz 		/* look in the certificate directories */
2105194Sjohnz 		*plp++ = (char *)_PATH_ELFSIGN_CRYPTO_CERTS;
2115194Sjohnz 		/*
2125194Sjohnz 		 * crypto verifications don't search beyond
2135194Sjohnz 		 * _PATH_ELFSIGN_CRYPTO_CERTS
2145194Sjohnz 		 */
2155194Sjohnz 		if (action != ES_GET_CRYPTO)
2165194Sjohnz 			*plp++ = (char *)_PATH_ELFSIGN_ETC_CERTS;
2175194Sjohnz 	}
2185194Sjohnz 	*plp = NULL;
2195194Sjohnz 
2205194Sjohnz 	if ((cert = elfcertlib_allocatecert()) == NULL) {
2215194Sjohnz 		return (ret);
2225194Sjohnz 	}
2235194Sjohnz 
2245194Sjohnz 	for (plp = pathlist; *plp; plp++) {
22510671SJohn.Zolnowsky@Sun.COM 		KMF_ATTRIBUTE	attrlist[8];
22610671SJohn.Zolnowsky@Sun.COM 		KMF_KEYSTORE_TYPE	kstype;
22710671SJohn.Zolnowsky@Sun.COM 		KMF_CERT_VALIDITY	certvalidity;
22810671SJohn.Zolnowsky@Sun.COM 		int		numattr;
22910671SJohn.Zolnowsky@Sun.COM 
23010671SJohn.Zolnowsky@Sun.COM 		kstype = KMF_KEYSTORE_OPENSSL;
23110671SJohn.Zolnowsky@Sun.COM 		certvalidity = KMF_ALL_CERTS;
2325194Sjohnz 		ncerts = 2;
2335194Sjohnz 
23410671SJohn.Zolnowsky@Sun.COM 		numattr = 0;
23510671SJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
23610671SJohn.Zolnowsky@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
23710671SJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
23810671SJohn.Zolnowsky@Sun.COM 		    KMF_X509_DER_CERT_ATTR, certbuf,
23910671SJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_X509_DER_CERT));
24010671SJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
24110671SJohn.Zolnowsky@Sun.COM 		    KMF_COUNT_ATTR, &ncerts, sizeof (uint32_t));
24210671SJohn.Zolnowsky@Sun.COM 		if (signer_DN != NULL) {
24310671SJohn.Zolnowsky@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr++,
24410671SJohn.Zolnowsky@Sun.COM 			    KMF_SUBJECT_NAME_ATTR, signer_DN,
24510671SJohn.Zolnowsky@Sun.COM 			    strlen(signer_DN));
24610671SJohn.Zolnowsky@Sun.COM 		}
24710671SJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
24810671SJohn.Zolnowsky@Sun.COM 		    KMF_CERT_VALIDITY_ATTR, &certvalidity,
24910671SJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_CERT_VALIDITY));
25010671SJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
25110671SJohn.Zolnowsky@Sun.COM 		    KMF_CERT_FILENAME_ATTR, *plp, strlen (*plp));
25210671SJohn.Zolnowsky@Sun.COM 
25310671SJohn.Zolnowsky@Sun.COM 		rv = kmf_find_cert(ess->es_kmfhandle, numattr, attrlist);
25410671SJohn.Zolnowsky@Sun.COM 
2555194Sjohnz 		if (rv != KMF_OK)
2565194Sjohnz 			continue;
25710671SJohn.Zolnowsky@Sun.COM 		/* found one */
25810671SJohn.Zolnowsky@Sun.COM 		cert->c_cert = certbuf[0];
25910671SJohn.Zolnowsky@Sun.COM 		if (ncerts > 1) {
26010671SJohn.Zolnowsky@Sun.COM 			/* release any extras */
26110671SJohn.Zolnowsky@Sun.COM 			kmf_free_kmf_cert(ess->es_kmfhandle, &certbuf[1]);
26210671SJohn.Zolnowsky@Sun.COM 			if (signer_DN == NULL) {
26310671SJohn.Zolnowsky@Sun.COM 				/* There can be only one */
26410671SJohn.Zolnowsky@Sun.COM 				cryptodebug("elfcertlib_getcert: "
26510671SJohn.Zolnowsky@Sun.COM 				    "too many certificates found in %s",
26610671SJohn.Zolnowsky@Sun.COM 				    cert_pathname);
26710671SJohn.Zolnowsky@Sun.COM 				goto cleanup;
26810671SJohn.Zolnowsky@Sun.COM 			}
2695194Sjohnz 		}
27010671SJohn.Zolnowsky@Sun.COM 		/* cache subject and issuer */
27110671SJohn.Zolnowsky@Sun.COM 		rv = kmf_get_cert_subject_str(ess->es_kmfhandle,
2725194Sjohnz 		    &cert->c_cert.certificate, &cert->c_subject);
2735194Sjohnz 		if (rv != KMF_OK)
2745194Sjohnz 			goto cleanup;
2755194Sjohnz 
27610671SJohn.Zolnowsky@Sun.COM 		rv = kmf_get_cert_issuer_str(ess->es_kmfhandle,
2775194Sjohnz 		    &cert->c_cert.certificate, &cert->c_issuer);
2785194Sjohnz 		if (rv != KMF_OK)
2795194Sjohnz 			goto cleanup;
2805194Sjohnz 		break;
2815194Sjohnz 	}
2825194Sjohnz 	if (*plp == NULL) {
2835194Sjohnz 		cryptodebug("elfcertlib_getcert: no certificate found");
2845194Sjohnz 		goto cleanup;
2855194Sjohnz 	}
2865194Sjohnz 
2875194Sjohnz 	cert->c_verified = E_UNCHECKED;
2885194Sjohnz 
2895194Sjohnz 	/*
29010123SValerie.Fenwick@Sun.COM 	 * If the cert we are loading is the trust anchor (ie the CA) then
2915194Sjohnz 	 * we mark it as such in cert.  This is so that we don't attempt
2925194Sjohnz 	 * to verify it later.  The CA is always implicitly verified.
2935194Sjohnz 	 */
2945194Sjohnz 	if (cert_pathname != NULL && (
2955194Sjohnz 	    strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 ||
296*10732SAnthony.Scarpino@Sun.COM 	    strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0 ||
297*10732SAnthony.Scarpino@Sun.COM 	    strcmp(cert_pathname, _PATH_CRYPTO_SECACERT) == 0)) {
2985194Sjohnz 		if (ess->es_certCAcallback != NULL)
2995194Sjohnz 			(ess->es_certCAcallback)(ess->es_callbackctx, cert,
3005194Sjohnz 			    cert_pathname);
3015194Sjohnz 		cert->c_verified = E_IS_TA;
3025194Sjohnz 	}
3035194Sjohnz 
3045194Sjohnz 	ret = B_TRUE;
3055194Sjohnz 
3065194Sjohnz cleanup:
3075194Sjohnz 	if (ret) {
3085194Sjohnz 		*certp = cert;
3095194Sjohnz 	} else {
3105194Sjohnz 		if (cert != NULL)
3115194Sjohnz 			elfcertlib_freecert(ess, cert);
3125194Sjohnz 		if (signer_DN != NULL)
3135194Sjohnz 			cryptoerror(LOG_ERR, "unable to find a certificate "
3145194Sjohnz 			    "for DN: %s", signer_DN);
3155194Sjohnz 		else
3165194Sjohnz 			cryptoerror(LOG_ERR, "unable to load certificate "
3175194Sjohnz 			    "from %s", cert_pathname);
3185194Sjohnz 	}
3195194Sjohnz 	return (ret);
3205194Sjohnz }
3215194Sjohnz 
3225194Sjohnz /*
3235194Sjohnz  * elfcertlib_loadprivatekey - Load the private key from path
3245194Sjohnz  *
3255194Sjohnz  * IN	ess		- elfsign context structure
3265194Sjohnz  *	cert
3275194Sjohnz  *	pathname
3285194Sjohnz  * OUT	cert
3295194Sjohnz  * RETURNS	TRUE/FALSE
3305194Sjohnz  */
3315194Sjohnz boolean_t
3325194Sjohnz elfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname)
3335194Sjohnz {
33410671SJohn.Zolnowsky@Sun.COM 	KMF_RETURN	rv = KMF_OK;
3355194Sjohnz 	KMF_KEY_HANDLE	keybuf[2];
33610671SJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[16];
33710671SJohn.Zolnowsky@Sun.COM 	uint32_t	nkeys;
33810671SJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
33910671SJohn.Zolnowsky@Sun.COM 	KMF_KEY_ALG	keytype;
34010671SJohn.Zolnowsky@Sun.COM 	KMF_KEY_CLASS	keyclass;
34110671SJohn.Zolnowsky@Sun.COM 	KMF_ENCODE_FORMAT	format;
34210671SJohn.Zolnowsky@Sun.COM 	int		numattr;
34310671SJohn.Zolnowsky@Sun.COM 
34410671SJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_OPENSSL;
34510671SJohn.Zolnowsky@Sun.COM 	nkeys = 2;
34610671SJohn.Zolnowsky@Sun.COM 	keytype = KMF_KEYALG_NONE;
34710671SJohn.Zolnowsky@Sun.COM 	keyclass = KMF_ASYM_PRI;
34810671SJohn.Zolnowsky@Sun.COM 	format = KMF_FORMAT_UNDEF;
3495194Sjohnz 
35010671SJohn.Zolnowsky@Sun.COM 	numattr = 0;
35110671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
35210671SJohn.Zolnowsky@Sun.COM 	    &kstype, sizeof (kstype));
35310671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
35410671SJohn.Zolnowsky@Sun.COM 	    keybuf, sizeof (KMF_KEY_HANDLE));
35510671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
35610671SJohn.Zolnowsky@Sun.COM 	    &nkeys, sizeof (uint32_t));
35710671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
35810671SJohn.Zolnowsky@Sun.COM 	    &keytype, sizeof (keytype));
35910671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
36010671SJohn.Zolnowsky@Sun.COM 	    &keyclass, sizeof (keyclass));
36110671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
36210671SJohn.Zolnowsky@Sun.COM 	    &format, sizeof (format));
36310671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_FILENAME_ATTR,
36410671SJohn.Zolnowsky@Sun.COM 	    (char *)pathname, strlen(pathname));
3655194Sjohnz 
36610671SJohn.Zolnowsky@Sun.COM 	rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
3675194Sjohnz 	if (rv != KMF_OK)
3685194Sjohnz 		return (B_FALSE);
3695194Sjohnz 	if (nkeys != 1) {
3705194Sjohnz 		/* lack of specificity */
3715194Sjohnz 		cryptodebug("found %d keys at %s", nkeys, pathname);
3725194Sjohnz 		return (B_FALSE);
3735194Sjohnz 	}
3745194Sjohnz 	cert->c_privatekey = keybuf[0];
3755194Sjohnz 	cryptodebug("key %s loaded", pathname);
3765194Sjohnz 	return (B_TRUE);
3775194Sjohnz }
3785194Sjohnz 
3795194Sjohnz /*
3805194Sjohnz  * elfcertlib_loadtokenkey - Load the private key from token
3815194Sjohnz  *
3825194Sjohnz  * IN	ess		- elfsign context structure
3835194Sjohnz  *	cert
3845194Sjohnz  *	token_label
3855194Sjohnz  *	pin
3865194Sjohnz  * OUT	cert
3875194Sjohnz  * RETURNS	TRUE/FALSE
3885194Sjohnz  */
3895194Sjohnz boolean_t
3905194Sjohnz elfcertlib_loadtokenkey(ELFsign_t ess, ELFCert_t cert,
3915194Sjohnz     const char *token_label, const char *pin)
3925194Sjohnz {
39310671SJohn.Zolnowsky@Sun.COM 	KMF_RETURN	rv;
39410671SJohn.Zolnowsky@Sun.COM 	char		*idstr = NULL;
39510671SJohn.Zolnowsky@Sun.COM 	char		*kmferr;
39610671SJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[16];
39710671SJohn.Zolnowsky@Sun.COM 	uint32_t	nkeys;
39810671SJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
39910671SJohn.Zolnowsky@Sun.COM 	KMF_KEY_ALG	keytype;
40010671SJohn.Zolnowsky@Sun.COM 	KMF_KEY_CLASS	keyclass;
40110671SJohn.Zolnowsky@Sun.COM 	KMF_ENCODE_FORMAT	format;
40210671SJohn.Zolnowsky@Sun.COM 	KMF_CREDENTIAL	pincred;
40310671SJohn.Zolnowsky@Sun.COM 	boolean_t	tokenbool, privatebool;
40410671SJohn.Zolnowsky@Sun.COM 	int		numattr;
4055194Sjohnz 
4065194Sjohnz 	/*
4075194Sjohnz 	 * We will search for the key based on the ID attribute
4085194Sjohnz 	 * which was added when the key was created.  ID is
4095194Sjohnz 	 * a SHA-1 hash of the public modulus shared by the
4105194Sjohnz 	 * key and the certificate.
4115194Sjohnz 	 */
41210671SJohn.Zolnowsky@Sun.COM 	rv = kmf_get_cert_id_str(&cert->c_cert.certificate, &idstr);
4135194Sjohnz 	if (rv != KMF_OK) {
41410671SJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(rv, &kmferr);
41510671SJohn.Zolnowsky@Sun.COM 		cryptodebug("Error getting ID from cert: %s\n",
41610671SJohn.Zolnowsky@Sun.COM 		    (kmferr ? kmferr : "Unrecognized KMF error"));
41710671SJohn.Zolnowsky@Sun.COM 		free(kmferr);
4185194Sjohnz 		return (B_FALSE);
4195194Sjohnz 	}
42010671SJohn.Zolnowsky@Sun.COM 
42110671SJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_PK11TOKEN;
42210671SJohn.Zolnowsky@Sun.COM 	nkeys = 1;
42310671SJohn.Zolnowsky@Sun.COM 	keytype = KMF_KEYALG_NONE;
42410671SJohn.Zolnowsky@Sun.COM 	keyclass = KMF_ASYM_PRI;
42510671SJohn.Zolnowsky@Sun.COM 	format = KMF_FORMAT_UNDEF;
42610671SJohn.Zolnowsky@Sun.COM 	pincred.cred = (char *)pin;
42710671SJohn.Zolnowsky@Sun.COM 	pincred.credlen = strlen(pin);
42810671SJohn.Zolnowsky@Sun.COM 	tokenbool = B_FALSE;
42910671SJohn.Zolnowsky@Sun.COM 	privatebool = B_TRUE;
4305194Sjohnz 
43110671SJohn.Zolnowsky@Sun.COM 	numattr = 0;
43210671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
43310671SJohn.Zolnowsky@Sun.COM 	    &kstype, sizeof (kstype));
43410671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
43510671SJohn.Zolnowsky@Sun.COM 	    &cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
43610671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
43710671SJohn.Zolnowsky@Sun.COM 	    &nkeys, sizeof (uint32_t));
43810671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
43910671SJohn.Zolnowsky@Sun.COM 	    &keytype, sizeof (keytype));
44010671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
44110671SJohn.Zolnowsky@Sun.COM 	    &keyclass, sizeof (keyclass));
44210671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
44310671SJohn.Zolnowsky@Sun.COM 	    &format, sizeof (format));
44410671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_IDSTR_ATTR,
44510671SJohn.Zolnowsky@Sun.COM 	    idstr, strlen(idstr));
44610671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_CREDENTIAL_ATTR,
44710671SJohn.Zolnowsky@Sun.COM 	    &pincred, sizeof (KMF_CREDENTIAL));
44810671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_TOKEN_BOOL_ATTR,
44910671SJohn.Zolnowsky@Sun.COM 	    &tokenbool, sizeof (tokenbool));
45010671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_PRIVATE_BOOL_ATTR,
45110671SJohn.Zolnowsky@Sun.COM 	    &privatebool, sizeof (privatebool));
45210671SJohn.Zolnowsky@Sun.COM 
45310671SJohn.Zolnowsky@Sun.COM 	rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
45410671SJohn.Zolnowsky@Sun.COM 	free(idstr);
45510671SJohn.Zolnowsky@Sun.COM 	if (rv != KMF_OK) {
45610671SJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(rv, &kmferr);
45710671SJohn.Zolnowsky@Sun.COM 		cryptodebug("Error finding private key: %s\n",
45810671SJohn.Zolnowsky@Sun.COM 		    (kmferr ? kmferr : "Unrecognized KMF error"));
45910671SJohn.Zolnowsky@Sun.COM 		free(kmferr);
46010671SJohn.Zolnowsky@Sun.COM 		return (B_FALSE);
46110671SJohn.Zolnowsky@Sun.COM 	}
46210671SJohn.Zolnowsky@Sun.COM 	if (nkeys != 1) {
46310671SJohn.Zolnowsky@Sun.COM 		cryptodebug("Error finding private key: No key found\n");
4645194Sjohnz 		return (B_FALSE);
4655194Sjohnz 	}
4665194Sjohnz 	cryptodebug("key found in %s", token_label);
4675194Sjohnz 	cryptodebug("elfcertlib_loadprivatekey = 0x%.8X",
4685194Sjohnz 	    &cert->c_privatekey);
4695194Sjohnz 
4705194Sjohnz 	return (B_TRUE);
4715194Sjohnz }
4725194Sjohnz 
4735194Sjohnz static const CK_BYTE MD5_DER_PREFIX[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
4745194Sjohnz 	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
4755194Sjohnz 
4765194Sjohnz /*
4775194Sjohnz  * elfcertlib_sign - sign the given DATA using the privatekey in cert
4785194Sjohnz  *
4795194Sjohnz  * IN	ess		- elfsign context structure
4805194Sjohnz  *	cert
4815194Sjohnz  *	data
4825194Sjohnz  *	data_len
4835194Sjohnz  * OUT	sig	- must be big enough to hold the signature of data
4845194Sjohnz  *		  Caller must allocate
4855194Sjohnz  *	sig_len	- actual length used; 0 on failure.
4865194Sjohnz  * RETURNS	TRUE/FALSE
4875194Sjohnz  */
4885194Sjohnz /*ARGSUSED*/
4895194Sjohnz boolean_t
4905194Sjohnz elfcertlib_sign(ELFsign_t ess, ELFCert_t cert,
4915194Sjohnz 	const uchar_t *data, size_t data_len,
4925194Sjohnz 	uchar_t *sig, size_t *sig_len)
4935194Sjohnz {
49410671SJohn.Zolnowsky@Sun.COM 	KMF_RETURN	ret;
49510671SJohn.Zolnowsky@Sun.COM 	KMF_DATA	tobesigned;
49610671SJohn.Zolnowsky@Sun.COM 	KMF_DATA	signature;
49710671SJohn.Zolnowsky@Sun.COM 	uchar_t		der_data[sizeof (MD5_DER_PREFIX) + MD5_DIGEST_LENGTH];
49810671SJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
49910671SJohn.Zolnowsky@Sun.COM 	int		numattr;
5005194Sjohnz 
5015194Sjohnz 	if (ess->es_version <= FILESIG_VERSION2) {
5025194Sjohnz 		/* compatibility: take MD5 hash of SHA1 hash */
5035194Sjohnz 		size_t	derlen = MD5_DIGEST_LENGTH;
5045194Sjohnz 		MD5_CTX ctx;
5055194Sjohnz 
5065194Sjohnz 		/*
5075194Sjohnz 		 * first: digest using software-based methods, don't
5085194Sjohnz 		 * rely on the token for hashing.
5095194Sjohnz 		 */
5105194Sjohnz 		MD5Init(&ctx);
5115194Sjohnz 		MD5Update(&ctx, data, data_len);
5125194Sjohnz 		MD5Final(&der_data[sizeof (MD5_DER_PREFIX)], &ctx);
5135194Sjohnz 
5145194Sjohnz 		/*
5155194Sjohnz 		 * second: insert prefix
5165194Sjohnz 		 */
5175194Sjohnz 		(void) memcpy(der_data, MD5_DER_PREFIX,
5185194Sjohnz 		    sizeof (MD5_DER_PREFIX));
5195194Sjohnz 		/*
5205194Sjohnz 		 * prepare to sign the local buffer
5215194Sjohnz 		 */
5225194Sjohnz 		tobesigned.Data = (uchar_t *)der_data;
5235194Sjohnz 		tobesigned.Length = sizeof (MD5_DER_PREFIX) + derlen;
5245194Sjohnz 	} else {
5255194Sjohnz 		tobesigned.Data = (uchar_t *)data;
5265194Sjohnz 		tobesigned.Length = data_len;
5275194Sjohnz 	}
5285194Sjohnz 
5295194Sjohnz 	signature.Data = (uchar_t *)sig;
5305194Sjohnz 	signature.Length = *sig_len;
5315194Sjohnz 
53210671SJohn.Zolnowsky@Sun.COM 	numattr = 0;
53310671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
53410671SJohn.Zolnowsky@Sun.COM 	    KMF_KEYSTORE_TYPE_ATTR, &(cert->c_privatekey.kstype),
53510671SJohn.Zolnowsky@Sun.COM 	    sizeof (KMF_KEYSTORE_TYPE));
53610671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
53710671SJohn.Zolnowsky@Sun.COM 	    KMF_KEY_HANDLE_ATTR, &cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
53810671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
53910671SJohn.Zolnowsky@Sun.COM 	    KMF_OID_ATTR, (KMF_OID *)&KMFOID_RSA, sizeof (KMF_OID));
54010671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
54110671SJohn.Zolnowsky@Sun.COM 	    KMF_DATA_ATTR, &tobesigned, sizeof (KMF_DATA));
54210671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
54310671SJohn.Zolnowsky@Sun.COM 	    KMF_OUT_DATA_ATTR, &signature, sizeof (KMF_DATA));
54410671SJohn.Zolnowsky@Sun.COM 
54510671SJohn.Zolnowsky@Sun.COM 	ret = kmf_sign_data(ess->es_kmfhandle, numattr, attrlist);
5465194Sjohnz 
5475194Sjohnz 	if (ret != KMF_OK) {
54810671SJohn.Zolnowsky@Sun.COM 		char	*kmferr;
54910671SJohn.Zolnowsky@Sun.COM 
55010671SJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(ret, &kmferr);
55110671SJohn.Zolnowsky@Sun.COM 		cryptodebug("Error signing data: %s\n",
55210671SJohn.Zolnowsky@Sun.COM 		    (kmferr ? kmferr : "Unrecognized KMF error"));
55310671SJohn.Zolnowsky@Sun.COM 		free(kmferr);
5545194Sjohnz 		*sig_len = 0;
5555194Sjohnz 		return (B_FALSE);
5565194Sjohnz 	}
5575194Sjohnz 	*sig_len = signature.Length;
5585194Sjohnz 	return (B_TRUE);
5595194Sjohnz }
5605194Sjohnz 
5615194Sjohnz /*
5625194Sjohnz  * elfcertlib_verifysig - verify the given DATA using the public key in cert
5635194Sjohnz  *
5645194Sjohnz  * IN	ess		- elfsign context structure
5655194Sjohnz  *	cert
5665194Sjohnz  *	signature
5675194Sjohnz  *	sig_len
5685194Sjohnz  *	data
5695194Sjohnz  *	data_len
5705194Sjohnz  * OUT	N/A
5715194Sjohnz  * RETURNS	TRUE/FALSE
5725194Sjohnz  */
5735194Sjohnz boolean_t
5745194Sjohnz elfcertlib_verifysig(ELFsign_t ess, ELFCert_t cert,
5755194Sjohnz 	const uchar_t *signature, size_t sig_len,
5765194Sjohnz 	const uchar_t *data, size_t data_len)
5775194Sjohnz {
5785194Sjohnz 	KMF_RETURN	rv;
5795194Sjohnz 	KMF_DATA	indata;
5805194Sjohnz 	KMF_DATA	insig;
5815194Sjohnz 	KMF_ALGORITHM_INDEX algid;
58210671SJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
58310671SJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
58410671SJohn.Zolnowsky@Sun.COM 	int		numattr;
5855194Sjohnz 
5865194Sjohnz 	indata.Data = (uchar_t *)data;
5875194Sjohnz 	indata.Length = data_len;
5885194Sjohnz 	insig.Data = (uchar_t *)signature;
5895194Sjohnz 	insig.Length = sig_len;
5905194Sjohnz 
5915194Sjohnz 	if (ess->es_version <= FILESIG_VERSION2)
5925194Sjohnz 		algid = KMF_ALGID_MD5WithRSA;
5935194Sjohnz 	else
5945194Sjohnz 		algid = KMF_ALGID_RSA;
5955194Sjohnz 
5965194Sjohnz 	/*
59710123SValerie.Fenwick@Sun.COM 	 * We tell KMF to use the PKCS11 verification APIs
59810123SValerie.Fenwick@Sun.COM 	 * here to prevent the use of OpenSSL and to keep
59910123SValerie.Fenwick@Sun.COM 	 * all validation within the FIPS-140 boundary for
60010123SValerie.Fenwick@Sun.COM 	 * the Cryptographic Framework.
6015194Sjohnz 	 */
60210671SJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_PK11TOKEN;
60310671SJohn.Zolnowsky@Sun.COM 
60410671SJohn.Zolnowsky@Sun.COM 	numattr = 0;
60510671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
60610671SJohn.Zolnowsky@Sun.COM 	    &kstype,  sizeof (kstype));
60710671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_DATA_ATTR,
60810671SJohn.Zolnowsky@Sun.COM 	    &indata, sizeof (KMF_DATA));
60910671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_IN_SIGN_ATTR,
61010671SJohn.Zolnowsky@Sun.COM 	    &insig, sizeof (KMF_DATA));
61110671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_SIGNER_CERT_DATA_ATTR,
61210671SJohn.Zolnowsky@Sun.COM 	    (KMF_DATA *)(&cert->c_cert.certificate), sizeof (KMF_DATA));
61310671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_ALGORITHM_INDEX_ATTR,
61410671SJohn.Zolnowsky@Sun.COM 	    &algid, sizeof (algid));
61510671SJohn.Zolnowsky@Sun.COM 
61610671SJohn.Zolnowsky@Sun.COM 	rv = kmf_verify_data(ess->es_kmfhandle, numattr, attrlist);
6175194Sjohnz 
6185194Sjohnz 	return ((rv == KMF_OK));
6195194Sjohnz }
6205194Sjohnz 
6215194Sjohnz /*
6225194Sjohnz  * elfcertlib_getdn
6235194Sjohnz  *
6245194Sjohnz  * IN	cert
6255194Sjohnz  * OUT	NONE
6265194Sjohnz  * RETURN 	dn or NULL
6275194Sjohnz  */
6285194Sjohnz char *
6295194Sjohnz elfcertlib_getdn(ELFCert_t cert)
6305194Sjohnz {
6315194Sjohnz 	cryptodebug("elfcertlib_getdn");
6325194Sjohnz 
6335194Sjohnz 	return (cert->c_subject);
6345194Sjohnz }
6355194Sjohnz 
6365194Sjohnz /*
6375194Sjohnz  * elfcertlib_getissuer
6385194Sjohnz  *
6395194Sjohnz  * IN	cert
6405194Sjohnz  * OUT	NONE
6415194Sjohnz  * RETURN 	dn or NULL
6425194Sjohnz  */
6435194Sjohnz char *
6445194Sjohnz elfcertlib_getissuer(ELFCert_t cert)
6455194Sjohnz {
6465194Sjohnz 	cryptodebug("elfcertlib_issuer");
6475194Sjohnz 
6485194Sjohnz 	return (cert->c_issuer);
6495194Sjohnz }
6505194Sjohnz 
6515194Sjohnz boolean_t
6525194Sjohnz elfcertlib_init(ELFsign_t ess)
6535194Sjohnz {
6545194Sjohnz 	boolean_t rc = B_TRUE;
6555194Sjohnz 	KMF_RETURN rv;
6565194Sjohnz 	if (ess->es_kmfhandle == NULL) {
65710671SJohn.Zolnowsky@Sun.COM 		rv = kmf_initialize(&ess->es_kmfhandle, NULL, NULL);
6585194Sjohnz 		if (rv != KMF_OK) {
6595194Sjohnz 			cryptoerror(LOG_ERR,
6605194Sjohnz 			    "unable to initialize KMF library");
6615194Sjohnz 			rc = B_FALSE;
6625194Sjohnz 		}
6635194Sjohnz 	}
6645194Sjohnz 	return (rc);
6655194Sjohnz }
6665194Sjohnz 
6675194Sjohnz void
6685194Sjohnz elfcertlib_fini(ELFsign_t ess)
6695194Sjohnz {
67010671SJohn.Zolnowsky@Sun.COM 	(void) kmf_finalize(ess->es_kmfhandle);
6715194Sjohnz }
6725194Sjohnz 
6735194Sjohnz /*
6745194Sjohnz  * set the token device
6755194Sjohnz  */
6765194Sjohnz boolean_t
6775194Sjohnz elfcertlib_settoken(ELFsign_t ess, char *token)
6785194Sjohnz {
67910671SJohn.Zolnowsky@Sun.COM 	boolean_t	rc = B_TRUE;
68010671SJohn.Zolnowsky@Sun.COM 	KMF_RETURN	rv;
68110671SJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
68210671SJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
68310671SJohn.Zolnowsky@Sun.COM 	boolean_t	readonly;
68410671SJohn.Zolnowsky@Sun.COM 	int	numattr;
68510671SJohn.Zolnowsky@Sun.COM 
68610671SJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_PK11TOKEN;
68710671SJohn.Zolnowsky@Sun.COM 	readonly = B_TRUE;
6885194Sjohnz 
68910671SJohn.Zolnowsky@Sun.COM 	numattr = 0;
69010671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
69110671SJohn.Zolnowsky@Sun.COM 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
69210671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
69310671SJohn.Zolnowsky@Sun.COM 	    KMF_TOKEN_LABEL_ATTR, token, strlen(token));
69410671SJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
69510671SJohn.Zolnowsky@Sun.COM 	    KMF_READONLY_ATTR, &readonly, sizeof (readonly));
69610671SJohn.Zolnowsky@Sun.COM 
69710671SJohn.Zolnowsky@Sun.COM 	rv = kmf_configure_keystore(ess->es_kmfhandle, numattr, attrlist);
6985194Sjohnz 	if (rv != KMF_OK) {
6995194Sjohnz 		cryptoerror(LOG_ERR, "unable to select token\n");
7005194Sjohnz 		rc = B_FALSE;
7015194Sjohnz 	}
7025194Sjohnz 
7035194Sjohnz 	return (rc);
7045194Sjohnz }
7055194Sjohnz 
7065194Sjohnz /*
7075194Sjohnz  * set the certificate CA identification callback
7085194Sjohnz  */
7095194Sjohnz void
7105194Sjohnz elfcertlib_setcertCAcallback(ELFsign_t ess,
7115194Sjohnz     void (*cb)(void *, ELFCert_t, char *))
7125194Sjohnz {
7135194Sjohnz 	ess->es_certCAcallback = cb;
7145194Sjohnz }
7155194Sjohnz 
7165194Sjohnz /*
7175194Sjohnz  * set the certificate verification callback
7185194Sjohnz  */
7195194Sjohnz void
7205194Sjohnz elfcertlib_setcertvercallback(ELFsign_t ess,
7215194Sjohnz     void (*cb)(void *, ELFCert_t, ELFCert_t))
7225194Sjohnz {
7235194Sjohnz 	ess->es_certvercallback = cb;
7245194Sjohnz }
7255194Sjohnz 
7265194Sjohnz 
7275194Sjohnz /*
7285194Sjohnz  * elfcertlib_releasecert - release a cert
7295194Sjohnz  *
7305194Sjohnz  * IN cert
7315194Sjohnz  * OUT cert
7325194Sjohnz  * RETURN	N/A
7335194Sjohnz  *
7345194Sjohnz  */
7355194Sjohnz void
7365194Sjohnz elfcertlib_releasecert(ELFsign_t ess, ELFCert_t cert)
7375194Sjohnz {
7385194Sjohnz 	elfcertlib_freecert(ess, cert);
7395194Sjohnz }
7405194Sjohnz 
7415194Sjohnz /*
7425194Sjohnz  * elfcertlib_allocatecert - create a new ELFCert_t
7435194Sjohnz  *
7445194Sjohnz  * IN N/A
7455194Sjohnz  * OUT	N/A
7465194Sjohnz  * RETURN 	ELFCert_t, NULL on failure.
7475194Sjohnz  */
7485194Sjohnz static ELFCert_t
7495194Sjohnz elfcertlib_allocatecert(void)
7505194Sjohnz {
7515194Sjohnz 	ELFCert_t cert = NULL;
7525194Sjohnz 
7535194Sjohnz 	cert = malloc(sizeof (struct ELFCert_s));
7545194Sjohnz 	if (cert == NULL) {
7555194Sjohnz 		cryptoerror(LOG_ERR,
7565194Sjohnz 		    "elfcertlib_allocatecert: malloc failed %s",
7575194Sjohnz 		    strerror(errno));
7585194Sjohnz 		return (NULL);
7595194Sjohnz 	}
7605194Sjohnz 	(void) memset(cert, 0, sizeof (struct ELFCert_s));
7615194Sjohnz 	cert->c_verified = E_UNCHECKED;
7625194Sjohnz 	cert->c_subject = NULL;
7635194Sjohnz 	cert->c_issuer = NULL;
7645194Sjohnz 	return (cert);
7655194Sjohnz }
7665194Sjohnz 
7675194Sjohnz /*
7685194Sjohnz  * elfcertlib_freecert - freeup the memory of a cert
7695194Sjohnz  *
7705194Sjohnz  * IN cert
7715194Sjohnz  * OUT cert
7725194Sjohnz  * RETURN	N/A
7735194Sjohnz  *
7745194Sjohnz  */
7755194Sjohnz static void
7765194Sjohnz elfcertlib_freecert(ELFsign_t ess, ELFCert_t cert)
7775194Sjohnz {
7785194Sjohnz 	if (cert == NULL)
7795194Sjohnz 		return;
7805194Sjohnz 
7815194Sjohnz 	free(cert->c_subject);
7825194Sjohnz 	free(cert->c_issuer);
7835194Sjohnz 
78410671SJohn.Zolnowsky@Sun.COM 	kmf_free_kmf_cert(ess->es_kmfhandle, &cert->c_cert);
78510671SJohn.Zolnowsky@Sun.COM 	kmf_free_kmf_key(ess->es_kmfhandle, &cert->c_privatekey);
7865194Sjohnz 
7875194Sjohnz 	free(cert);
7885194Sjohnz }
789