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 /*
23*10123SValerie.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.
555194Sjohnz  */
565194Sjohnz static const char _PATH_CRYPTO_CACERT[] = CRYPTO_CERTS_DIR "/CA";
575194Sjohnz static const char _PATH_CRYPTO_OBJCACERT[] = CRYPTO_CERTS_DIR "/SUNWObjectCA";
585194Sjohnz static ELFCert_t CACERT = NULL;
595194Sjohnz static ELFCert_t OBJCACERT = NULL;
605194Sjohnz static pthread_mutex_t ca_mutex = PTHREAD_MUTEX_INITIALIZER;
615194Sjohnz 
625194Sjohnz static void elfcertlib_freecert(ELFsign_t, ELFCert_t);
635194Sjohnz static ELFCert_t elfcertlib_allocatecert(void);
645194Sjohnz 
655194Sjohnz /*
665194Sjohnz  * elfcertlib_verifycert - Verify the Cert with a Trust Anchor
675194Sjohnz  *
685194Sjohnz  * IN	ess		- elfsign context structure
695194Sjohnz  *	cert
705194Sjohnz  * OUT	NONE
715194Sjohnz  * RETURN	TRUE/FALSE
725194Sjohnz  *
735194Sjohnz  * We first setup the Trust Anchor (CA and SUNWObjectCA) certs
745194Sjohnz  * if it hasn't been done already.  We verify that the files on disk
755194Sjohnz  * are those we expected.
765194Sjohnz  *
775194Sjohnz  * We then verify the given cert using the publickey of a TA.
785194Sjohnz  * If the passed in cert is a TA or it has been verified already we
795194Sjohnz  * short cut and return TRUE without futher validation.
805194Sjohnz  */
815194Sjohnz /*ARGSUSED*/
825194Sjohnz boolean_t
835194Sjohnz elfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert)
845194Sjohnz {
855194Sjohnz 	KMF_RETURN rv;
865194Sjohnz 	if ((cert->c_verified == E_OK) || (cert->c_verified == E_IS_TA)) {
875194Sjohnz 		return (B_TRUE);
885194Sjohnz 	}
895194Sjohnz 
905194Sjohnz 	(void) pthread_mutex_lock(&ca_mutex);
915194Sjohnz 	if (CACERT == NULL) {
925194Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT,
935194Sjohnz 		    NULL, &CACERT, ES_GET);
945194Sjohnz 	}
955194Sjohnz 	if (OBJCACERT == NULL) {
965194Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT,
975194Sjohnz 		    NULL, &OBJCACERT, ES_GET);
985194Sjohnz 	}
995194Sjohnz 	(void) pthread_mutex_unlock(&ca_mutex);
1005194Sjohnz 
1015194Sjohnz 	if (CACERT != NULL) {
1025194Sjohnz 		rv = KMF_VerifyCertWithCert(ess->es_kmfhandle,
1035194Sjohnz 		    (const KMF_DATA *)&cert->c_cert,
1045194Sjohnz 		    (const KMF_DATA *)&CACERT->c_cert.certificate);
1055194Sjohnz 		if (rv == KMF_OK) {
1065194Sjohnz 			if (ess->es_certCAcallback != NULL)
1075194Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
1085194Sjohnz 				    cert, CACERT);
1095194Sjohnz 			cert->c_verified = E_OK;
1105194Sjohnz 			return (B_TRUE);
1115194Sjohnz 		}
1125194Sjohnz 	}
1135194Sjohnz 
1145194Sjohnz 	if (OBJCACERT != NULL) {
1155194Sjohnz 		rv = KMF_VerifyCertWithCert(ess->es_kmfhandle,
1165194Sjohnz 		    (const KMF_DATA *)&cert->c_cert,
1175194Sjohnz 		    (const KMF_DATA *)&OBJCACERT->c_cert.certificate);
1185194Sjohnz 		if (rv == KMF_OK) {
1195194Sjohnz 			if (ess->es_certCAcallback != NULL)
1205194Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
1215194Sjohnz 				    cert, OBJCACERT);
1225194Sjohnz 			cert->c_verified = E_OK;
1235194Sjohnz 			return (B_TRUE);
1245194Sjohnz 		}
1255194Sjohnz 	}
1265194Sjohnz 
1275194Sjohnz 	return (B_FALSE);
1285194Sjohnz }
1295194Sjohnz 
1305194Sjohnz /*
1315194Sjohnz  * elfcertlib_getcert - Get the certificate for signer_DN
1325194Sjohnz  *
1335194Sjohnz  * IN	ess		- elfsign context structure
1345194Sjohnz  *	cert_pathname	- path to cert (May be NULL)
1355194Sjohnz  *	signer_DN	- The DN we are looking for (May be NULL)
1365194Sjohnz  *      action		- indicates crypto verification call
1375194Sjohnz  * OUT  certp		- allocated/loaded ELFCert_t
1385194Sjohnz  *
1395194Sjohnz  * If the cert_pathname is passed use it and don't search.
1405194Sjohnz  * Otherwise, go looking in certificate directories
1415194Sjohnz  */
1425194Sjohnz boolean_t
1435194Sjohnz elfcertlib_getcert(ELFsign_t ess, char *cert_pathname,
1445194Sjohnz     char *signer_DN, ELFCert_t *certp, enum ES_ACTION action)
1455194Sjohnz {
1465194Sjohnz 	KMF_RETURN rv;
1475194Sjohnz 	ELFCert_t	cert = NULL;
1485194Sjohnz 	KMF_FINDCERT_PARAMS fcparams;
1495194Sjohnz 	KMF_X509_DER_CERT certbuf[2];
1505194Sjohnz 	uint32_t ncerts;
1515194Sjohnz 	boolean_t ret = B_FALSE;
1525194Sjohnz 	char	*pathlist[3], **plp;
1535194Sjohnz 
1545194Sjohnz 	cryptodebug("elfcertlib_getcert: path=%s, DN=%s",
1555194Sjohnz 	    cert_pathname ? cert_pathname : "-none-",
1565194Sjohnz 	    signer_DN ? signer_DN : "-none-");
1575194Sjohnz 	*certp = NULL;
1585194Sjohnz 	if (cert_pathname == NULL && signer_DN == NULL) {
1595194Sjohnz 		cryptodebug("elfcertlib_getcert: lack of specificity");
1605194Sjohnz 		return (ret);
1615194Sjohnz 	}
1625194Sjohnz 
1635194Sjohnz 	plp = pathlist;
1645194Sjohnz 	if (cert_pathname != NULL) {
1655194Sjohnz 		/* look in the specified object */
1665194Sjohnz 		*plp++ = cert_pathname;
1675194Sjohnz 	} else {
1685194Sjohnz 		/* look in the certificate directories */
1695194Sjohnz 		*plp++ = (char *)_PATH_ELFSIGN_CRYPTO_CERTS;
1705194Sjohnz 		/*
1715194Sjohnz 		 * crypto verifications don't search beyond
1725194Sjohnz 		 * _PATH_ELFSIGN_CRYPTO_CERTS
1735194Sjohnz 		 */
1745194Sjohnz 		if (action != ES_GET_CRYPTO)
1755194Sjohnz 			*plp++ = (char *)_PATH_ELFSIGN_ETC_CERTS;
1765194Sjohnz 	}
1775194Sjohnz 	*plp = NULL;
1785194Sjohnz 
1795194Sjohnz 	if ((cert = elfcertlib_allocatecert()) == NULL) {
1805194Sjohnz 		return (ret);
1815194Sjohnz 	}
1825194Sjohnz 
1835194Sjohnz 	for (plp = pathlist; *plp; plp++) {
1845194Sjohnz 		(void) memset(&fcparams, 0, sizeof (fcparams));
1855194Sjohnz 		fcparams.kstype = KMF_KEYSTORE_OPENSSL;
1865194Sjohnz 		fcparams.sslparms.certfile = *plp;
1875194Sjohnz 		fcparams.subject = signer_DN;
1885194Sjohnz 		ncerts = 2;
1895194Sjohnz 
1905194Sjohnz 		rv = KMF_FindCert(ess->es_kmfhandle, &fcparams, certbuf,
1915194Sjohnz 		    &ncerts);
1925194Sjohnz 		if (rv != KMF_OK)
1935194Sjohnz 			continue;
1945194Sjohnz 		if (ncerts > 1 && signer_DN == NULL) {
1955194Sjohnz 			/* There can be only one */
1965194Sjohnz 			cryptodebug("elfcertlib_getcert: "
1975194Sjohnz 			    "too many certificates found in %s",
1985194Sjohnz 			    cert_pathname);
1995194Sjohnz 			goto cleanup;
2005194Sjohnz 		}
2015194Sjohnz 		/* found it, cache subject and issuer */
2025194Sjohnz 		cert->c_cert = certbuf[0];
2035194Sjohnz 		rv = KMF_GetCertSubjectNameString(ess->es_kmfhandle,
2045194Sjohnz 		    &cert->c_cert.certificate, &cert->c_subject);
2055194Sjohnz 		if (rv != KMF_OK)
2065194Sjohnz 			goto cleanup;
2075194Sjohnz 
2085194Sjohnz 		rv = KMF_GetCertIssuerNameString(ess->es_kmfhandle,
2095194Sjohnz 		    &cert->c_cert.certificate, &cert->c_issuer);
2105194Sjohnz 		if (rv != KMF_OK)
2115194Sjohnz 			goto cleanup;
2125194Sjohnz 		break;
2135194Sjohnz 	}
2145194Sjohnz 	if (*plp == NULL) {
2155194Sjohnz 		cryptodebug("elfcertlib_getcert: no certificate found");
2165194Sjohnz 		goto cleanup;
2175194Sjohnz 	}
2185194Sjohnz 
2195194Sjohnz 	cert->c_verified = E_UNCHECKED;
2205194Sjohnz 
2215194Sjohnz 	/*
222*10123SValerie.Fenwick@Sun.COM 	 * If the cert we are loading is the trust anchor (ie the CA) then
2235194Sjohnz 	 * we mark it as such in cert.  This is so that we don't attempt
2245194Sjohnz 	 * to verify it later.  The CA is always implicitly verified.
2255194Sjohnz 	 */
2265194Sjohnz 	if (cert_pathname != NULL && (
2275194Sjohnz 	    strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 ||
2285194Sjohnz 	    strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0)) {
2295194Sjohnz 		if (ess->es_certCAcallback != NULL)
2305194Sjohnz 			(ess->es_certCAcallback)(ess->es_callbackctx, cert,
2315194Sjohnz 			    cert_pathname);
2325194Sjohnz 		cert->c_verified = E_IS_TA;
2335194Sjohnz 	}
2345194Sjohnz 
2355194Sjohnz 	ret = B_TRUE;
2365194Sjohnz 
2375194Sjohnz cleanup:
2385194Sjohnz 	if (ret) {
2395194Sjohnz 		*certp = cert;
2405194Sjohnz 	} else {
2415194Sjohnz 		if (cert != NULL)
2425194Sjohnz 			elfcertlib_freecert(ess, cert);
2435194Sjohnz 		if (signer_DN != NULL)
2445194Sjohnz 			cryptoerror(LOG_ERR, "unable to find a certificate "
2455194Sjohnz 			    "for DN: %s", signer_DN);
2465194Sjohnz 		else
2475194Sjohnz 			cryptoerror(LOG_ERR, "unable to load certificate "
2485194Sjohnz 			    "from %s", cert_pathname);
2495194Sjohnz 	}
2505194Sjohnz 	return (ret);
2515194Sjohnz }
2525194Sjohnz 
2535194Sjohnz /*
2545194Sjohnz  * elfcertlib_loadprivatekey - Load the private key from path
2555194Sjohnz  *
2565194Sjohnz  * IN	ess		- elfsign context structure
2575194Sjohnz  *	cert
2585194Sjohnz  *	pathname
2595194Sjohnz  * OUT	cert
2605194Sjohnz  * RETURNS	TRUE/FALSE
2615194Sjohnz  */
2625194Sjohnz boolean_t
2635194Sjohnz elfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname)
2645194Sjohnz {
2655194Sjohnz 	KMF_RETURN rv = KMF_OK;
2665194Sjohnz 	uint32_t nkeys = 2;
2675194Sjohnz 	KMF_FINDKEY_PARAMS fkparams;
2685194Sjohnz 	KMF_KEY_HANDLE	keybuf[2];
2695194Sjohnz 
2705194Sjohnz 	(void) memset(&fkparams, 0, sizeof (fkparams));
2715194Sjohnz 	fkparams.keyclass = KMF_ASYM_PRI;
2725194Sjohnz 	fkparams.kstype = KMF_KEYSTORE_OPENSSL;
2735194Sjohnz 	fkparams.sslparms.keyfile = (char *)pathname;
2745194Sjohnz 
2755194Sjohnz 	rv = KMF_FindKey(ess->es_kmfhandle, &fkparams, keybuf, &nkeys);
2765194Sjohnz 	if (rv != KMF_OK)
2775194Sjohnz 		return (B_FALSE);
2785194Sjohnz 	if (nkeys != 1) {
2795194Sjohnz 		/* lack of specificity */
2805194Sjohnz 		cryptodebug("found %d keys at %s", nkeys, pathname);
2815194Sjohnz 		return (B_FALSE);
2825194Sjohnz 	}
2835194Sjohnz 	cert->c_privatekey = keybuf[0];
2845194Sjohnz 	cryptodebug("key %s loaded", pathname);
2855194Sjohnz 	return (B_TRUE);
2865194Sjohnz }
2875194Sjohnz 
2885194Sjohnz /*
2895194Sjohnz  * elfcertlib_loadtokenkey - Load the private key from token
2905194Sjohnz  *
2915194Sjohnz  * IN	ess		- elfsign context structure
2925194Sjohnz  *	cert
2935194Sjohnz  *	token_label
2945194Sjohnz  *	pin
2955194Sjohnz  * OUT	cert
2965194Sjohnz  * RETURNS	TRUE/FALSE
2975194Sjohnz  */
2985194Sjohnz boolean_t
2995194Sjohnz elfcertlib_loadtokenkey(ELFsign_t ess, ELFCert_t cert,
3005194Sjohnz     const char *token_label, const char *pin)
3015194Sjohnz {
3025194Sjohnz 	KMF_RETURN rv = KMF_OK;
3035194Sjohnz 	KMF_FINDKEY_PARAMS fkparams;
3045194Sjohnz 	KMF_CONFIG_PARAMS cfgparams;
3055194Sjohnz 	uint32_t nkeys = 1;
3065194Sjohnz 	char *idstr = NULL;
3075194Sjohnz 	char *err = NULL;
3085194Sjohnz 
3095194Sjohnz 	(void) memset(&fkparams, 0, sizeof (fkparams));
3105194Sjohnz 	(void) memset(&cfgparams, 0, sizeof (cfgparams));
3115194Sjohnz 
3125194Sjohnz 	cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN;
3135194Sjohnz 	cfgparams.pkcs11config.label = (char *)token_label;
3145194Sjohnz 	cfgparams.pkcs11config.readonly = B_TRUE;
3155194Sjohnz 	rv = KMF_ConfigureKeystore(ess->es_kmfhandle, &cfgparams);
3165194Sjohnz 	if (rv != KMF_OK) {
3175194Sjohnz 		if (KMF_GetKMFErrorString(rv, &err) == KMF_OK) {
3185194Sjohnz 			cryptodebug("Error configuring token access:"
3195194Sjohnz 			    " %s\n", err);
3205194Sjohnz 			free(err);
3215194Sjohnz 		}
3225194Sjohnz 		return (B_FALSE);
3235194Sjohnz 	}
3245194Sjohnz 
3255194Sjohnz 	fkparams.idstr = idstr;
3265194Sjohnz 	fkparams.kstype = KMF_KEYSTORE_PK11TOKEN;
3275194Sjohnz 	fkparams.keyclass = KMF_ASYM_PRI;
3285194Sjohnz 	fkparams.cred.cred = (char *)pin;
3295194Sjohnz 	fkparams.cred.credlen = (pin != NULL ? strlen(pin) : 0);
3305194Sjohnz 	fkparams.pkcs11parms.private = B_TRUE;
3315194Sjohnz 
3325194Sjohnz 	/*
3335194Sjohnz 	 * We will search for the key based on the ID attribute
3345194Sjohnz 	 * which was added when the key was created.  ID is
3355194Sjohnz 	 * a SHA-1 hash of the public modulus shared by the
3365194Sjohnz 	 * key and the certificate.
3375194Sjohnz 	 */
3385194Sjohnz 	rv = KMF_GetCertIDString(&cert->c_cert.certificate, &idstr);
3395194Sjohnz 	if (rv != KMF_OK) {
3405194Sjohnz 		if (KMF_GetKMFErrorString(rv, &err) == KMF_OK) {
3415194Sjohnz 			cryptodebug("Error getting ID from cert: %s\n", err);
3425194Sjohnz 			free(err);
3435194Sjohnz 		}
3445194Sjohnz 		return (B_FALSE);
3455194Sjohnz 	}
3465194Sjohnz 	fkparams.idstr = idstr;
3475194Sjohnz 
3485194Sjohnz 	rv = KMF_FindKey(ess->es_kmfhandle, &fkparams,
3495194Sjohnz 	    &cert->c_privatekey, &nkeys);
3505194Sjohnz 	if (rv != KMF_OK || nkeys != 1) {
3515194Sjohnz 		if (KMF_GetKMFErrorString(rv, &err) == KMF_OK) {
3525194Sjohnz 			cryptodebug("Error finding private key: %s\n", err);
3535194Sjohnz 			free(err);
3545194Sjohnz 		}
3555194Sjohnz 		free(idstr);
3565194Sjohnz 		return (B_FALSE);
3575194Sjohnz 	}
3585194Sjohnz 	cryptodebug("key found in %s", token_label);
3595194Sjohnz 	cryptodebug("elfcertlib_loadprivatekey = 0x%.8X",
3605194Sjohnz 	    &cert->c_privatekey);
3615194Sjohnz 
3625194Sjohnz 	free(idstr);
3635194Sjohnz 	return (B_TRUE);
3645194Sjohnz }
3655194Sjohnz 
3665194Sjohnz static const CK_BYTE MD5_DER_PREFIX[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
3675194Sjohnz 	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
3685194Sjohnz 
3695194Sjohnz /*
3705194Sjohnz  * elfcertlib_sign - sign the given DATA using the privatekey in cert
3715194Sjohnz  *
3725194Sjohnz  * IN	ess		- elfsign context structure
3735194Sjohnz  *	cert
3745194Sjohnz  *	data
3755194Sjohnz  *	data_len
3765194Sjohnz  * OUT	sig	- must be big enough to hold the signature of data
3775194Sjohnz  *		  Caller must allocate
3785194Sjohnz  *	sig_len	- actual length used; 0 on failure.
3795194Sjohnz  * RETURNS	TRUE/FALSE
3805194Sjohnz  */
3815194Sjohnz /*ARGSUSED*/
3825194Sjohnz boolean_t
3835194Sjohnz elfcertlib_sign(ELFsign_t ess, ELFCert_t cert,
3845194Sjohnz 	const uchar_t *data, size_t data_len,
3855194Sjohnz 	uchar_t *sig, size_t *sig_len)
3865194Sjohnz {
3875194Sjohnz 	KMF_RETURN ret = KMF_OK;
3885194Sjohnz 	KMF_DATA tobesigned;
3895194Sjohnz 	KMF_DATA signature;
3905194Sjohnz 	uchar_t	 der_data[sizeof (MD5_DER_PREFIX) + MD5_DIGEST_LENGTH];
3915194Sjohnz 
3925194Sjohnz 	if (ess->es_version <= FILESIG_VERSION2) {
3935194Sjohnz 		/* compatibility: take MD5 hash of SHA1 hash */
3945194Sjohnz 		size_t	derlen = MD5_DIGEST_LENGTH;
3955194Sjohnz 		MD5_CTX ctx;
3965194Sjohnz 
3975194Sjohnz 		/*
3985194Sjohnz 		 * first: digest using software-based methods, don't
3995194Sjohnz 		 * rely on the token for hashing.
4005194Sjohnz 		 */
4015194Sjohnz 		MD5Init(&ctx);
4025194Sjohnz 		MD5Update(&ctx, data, data_len);
4035194Sjohnz 		MD5Final(&der_data[sizeof (MD5_DER_PREFIX)], &ctx);
4045194Sjohnz 
4055194Sjohnz 		/*
4065194Sjohnz 		 * second: insert prefix
4075194Sjohnz 		 */
4085194Sjohnz 		(void) memcpy(der_data, MD5_DER_PREFIX,
4095194Sjohnz 		    sizeof (MD5_DER_PREFIX));
4105194Sjohnz 		/*
4115194Sjohnz 		 * prepare to sign the local buffer
4125194Sjohnz 		 */
4135194Sjohnz 		tobesigned.Data = (uchar_t *)der_data;
4145194Sjohnz 		tobesigned.Length = sizeof (MD5_DER_PREFIX) + derlen;
4155194Sjohnz 	} else {
4165194Sjohnz 		tobesigned.Data = (uchar_t *)data;
4175194Sjohnz 		tobesigned.Length = data_len;
4185194Sjohnz 	}
4195194Sjohnz 
4205194Sjohnz 	signature.Data = (uchar_t *)sig;
4215194Sjohnz 	signature.Length = *sig_len;
4225194Sjohnz 
4235194Sjohnz 	ret = KMF_SignDataWithKey(ess->es_kmfhandle,
4245194Sjohnz 	    &cert->c_privatekey, (KMF_OID *)&KMFOID_RSA,
4255194Sjohnz 	    &tobesigned, &signature);
4265194Sjohnz 
4275194Sjohnz 	if (ret != KMF_OK) {
4285194Sjohnz 		char *err;
4295194Sjohnz 		if (KMF_GetKMFErrorString(ret, &err) == KMF_OK &&
4305194Sjohnz 		    err != NULL) {
4315194Sjohnz 			cryptodebug("Error signing data: %s\n", err);
4325194Sjohnz 			free(err);
4335194Sjohnz 		}
4345194Sjohnz 		*sig_len = 0;
4355194Sjohnz 		return (B_FALSE);
4365194Sjohnz 	}
4375194Sjohnz 	*sig_len = signature.Length;
4385194Sjohnz 	return (B_TRUE);
4395194Sjohnz }
4405194Sjohnz 
4415194Sjohnz /*
4425194Sjohnz  * elfcertlib_verifysig - verify the given DATA using the public key in cert
4435194Sjohnz  *
4445194Sjohnz  * IN	ess		- elfsign context structure
4455194Sjohnz  *	cert
4465194Sjohnz  *	signature
4475194Sjohnz  *	sig_len
4485194Sjohnz  *	data
4495194Sjohnz  *	data_len
4505194Sjohnz  * OUT	N/A
4515194Sjohnz  * RETURNS	TRUE/FALSE
4525194Sjohnz  */
4535194Sjohnz boolean_t
4545194Sjohnz elfcertlib_verifysig(ELFsign_t ess, ELFCert_t cert,
4555194Sjohnz 	const uchar_t *signature, size_t sig_len,
4565194Sjohnz 	const uchar_t *data, size_t data_len)
4575194Sjohnz {
4585194Sjohnz 	KMF_RETURN	rv;
4595194Sjohnz 	KMF_DATA	indata;
4605194Sjohnz 	KMF_DATA	insig;
4615194Sjohnz 	KMF_ALGORITHM_INDEX algid;
4625194Sjohnz 
4635194Sjohnz 	indata.Data = (uchar_t *)data;
4645194Sjohnz 	indata.Length = data_len;
4655194Sjohnz 	insig.Data = (uchar_t *)signature;
4665194Sjohnz 	insig.Length = sig_len;
4675194Sjohnz 
4685194Sjohnz 	if (ess->es_version <= FILESIG_VERSION2)
4695194Sjohnz 		algid = KMF_ALGID_MD5WithRSA;
4705194Sjohnz 	else
4715194Sjohnz 		algid = KMF_ALGID_RSA;
4725194Sjohnz 
4735194Sjohnz 	/*
474*10123SValerie.Fenwick@Sun.COM 	 * We tell KMF to use the PKCS11 verification APIs
475*10123SValerie.Fenwick@Sun.COM 	 * here to prevent the use of OpenSSL and to keep
476*10123SValerie.Fenwick@Sun.COM 	 * all validation within the FIPS-140 boundary for
477*10123SValerie.Fenwick@Sun.COM 	 * the Cryptographic Framework.
4785194Sjohnz 	 */
4795194Sjohnz 	rv = KMF_VerifyDataWithCert(ess->es_kmfhandle,
480*10123SValerie.Fenwick@Sun.COM 	    KMF_KEYSTORE_PK11TOKEN, algid,
4815194Sjohnz 	    &indata, &insig, &cert->c_cert.certificate);
4825194Sjohnz 
4835194Sjohnz 	return ((rv == KMF_OK));
4845194Sjohnz }
4855194Sjohnz 
4865194Sjohnz /*
4875194Sjohnz  * elfcertlib_getdn
4885194Sjohnz  *
4895194Sjohnz  * IN	cert
4905194Sjohnz  * OUT	NONE
4915194Sjohnz  * RETURN 	dn or NULL
4925194Sjohnz  */
4935194Sjohnz char *
4945194Sjohnz elfcertlib_getdn(ELFCert_t cert)
4955194Sjohnz {
4965194Sjohnz 	cryptodebug("elfcertlib_getdn");
4975194Sjohnz 
4985194Sjohnz 	return (cert->c_subject);
4995194Sjohnz }
5005194Sjohnz 
5015194Sjohnz /*
5025194Sjohnz  * elfcertlib_getissuer
5035194Sjohnz  *
5045194Sjohnz  * IN	cert
5055194Sjohnz  * OUT	NONE
5065194Sjohnz  * RETURN 	dn or NULL
5075194Sjohnz  */
5085194Sjohnz char *
5095194Sjohnz elfcertlib_getissuer(ELFCert_t cert)
5105194Sjohnz {
5115194Sjohnz 	cryptodebug("elfcertlib_issuer");
5125194Sjohnz 
5135194Sjohnz 	return (cert->c_issuer);
5145194Sjohnz }
5155194Sjohnz 
5165194Sjohnz boolean_t
5175194Sjohnz elfcertlib_init(ELFsign_t ess)
5185194Sjohnz {
5195194Sjohnz 	boolean_t rc = B_TRUE;
5205194Sjohnz 	KMF_RETURN rv;
5215194Sjohnz 	if (ess->es_kmfhandle == NULL) {
5225194Sjohnz 		rv = KMF_Initialize(&ess->es_kmfhandle, NULL, NULL);
5235194Sjohnz 		if (rv != KMF_OK) {
5245194Sjohnz 			cryptoerror(LOG_ERR,
5255194Sjohnz 			    "unable to initialize KMF library");
5265194Sjohnz 			rc = B_FALSE;
5275194Sjohnz 		}
5285194Sjohnz 	}
5295194Sjohnz 	return (rc);
5305194Sjohnz }
5315194Sjohnz 
5325194Sjohnz void
5335194Sjohnz elfcertlib_fini(ELFsign_t ess)
5345194Sjohnz {
5355194Sjohnz 	(void) KMF_Finalize(ess->es_kmfhandle);
5365194Sjohnz }
5375194Sjohnz 
5385194Sjohnz /*
5395194Sjohnz  * set the token device
5405194Sjohnz  */
5415194Sjohnz boolean_t
5425194Sjohnz elfcertlib_settoken(ELFsign_t ess, char *token)
5435194Sjohnz {
5445194Sjohnz 	boolean_t rc = B_TRUE;
5455194Sjohnz 	KMF_RETURN rv;
5465194Sjohnz 	KMF_CONFIG_PARAMS cfgparams;
5475194Sjohnz 
5485194Sjohnz 	(void) memset(&cfgparams, 0, sizeof (cfgparams));
5495194Sjohnz 	cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN;
5505194Sjohnz 	cfgparams.pkcs11config.label = token;
5515194Sjohnz 	cfgparams.pkcs11config.readonly = B_TRUE;
5525194Sjohnz 	rv = KMF_ConfigureKeystore(ess->es_kmfhandle, &cfgparams);
5535194Sjohnz 	if (rv != KMF_OK) {
5545194Sjohnz 		cryptoerror(LOG_ERR, "unable to select token\n");
5555194Sjohnz 		rc = B_FALSE;
5565194Sjohnz 	}
5575194Sjohnz 
5585194Sjohnz 	return (rc);
5595194Sjohnz }
5605194Sjohnz 
5615194Sjohnz /*
5625194Sjohnz  * set the certificate CA identification callback
5635194Sjohnz  */
5645194Sjohnz void
5655194Sjohnz elfcertlib_setcertCAcallback(ELFsign_t ess,
5665194Sjohnz     void (*cb)(void *, ELFCert_t, char *))
5675194Sjohnz {
5685194Sjohnz 	ess->es_certCAcallback = cb;
5695194Sjohnz }
5705194Sjohnz 
5715194Sjohnz /*
5725194Sjohnz  * set the certificate verification callback
5735194Sjohnz  */
5745194Sjohnz void
5755194Sjohnz elfcertlib_setcertvercallback(ELFsign_t ess,
5765194Sjohnz     void (*cb)(void *, ELFCert_t, ELFCert_t))
5775194Sjohnz {
5785194Sjohnz 	ess->es_certvercallback = cb;
5795194Sjohnz }
5805194Sjohnz 
5815194Sjohnz 
5825194Sjohnz /*
5835194Sjohnz  * elfcertlib_releasecert - release a cert
5845194Sjohnz  *
5855194Sjohnz  * IN cert
5865194Sjohnz  * OUT cert
5875194Sjohnz  * RETURN	N/A
5885194Sjohnz  *
5895194Sjohnz  */
5905194Sjohnz void
5915194Sjohnz elfcertlib_releasecert(ELFsign_t ess, ELFCert_t cert)
5925194Sjohnz {
5935194Sjohnz 	elfcertlib_freecert(ess, cert);
5945194Sjohnz }
5955194Sjohnz 
5965194Sjohnz /*
5975194Sjohnz  * elfcertlib_allocatecert - create a new ELFCert_t
5985194Sjohnz  *
5995194Sjohnz  * IN N/A
6005194Sjohnz  * OUT	N/A
6015194Sjohnz  * RETURN 	ELFCert_t, NULL on failure.
6025194Sjohnz  */
6035194Sjohnz static ELFCert_t
6045194Sjohnz elfcertlib_allocatecert(void)
6055194Sjohnz {
6065194Sjohnz 	ELFCert_t cert = NULL;
6075194Sjohnz 
6085194Sjohnz 	cert = malloc(sizeof (struct ELFCert_s));
6095194Sjohnz 	if (cert == NULL) {
6105194Sjohnz 		cryptoerror(LOG_ERR,
6115194Sjohnz 		    "elfcertlib_allocatecert: malloc failed %s",
6125194Sjohnz 		    strerror(errno));
6135194Sjohnz 		return (NULL);
6145194Sjohnz 	}
6155194Sjohnz 	(void) memset(cert, 0, sizeof (struct ELFCert_s));
6165194Sjohnz 	cert->c_verified = E_UNCHECKED;
6175194Sjohnz 	cert->c_subject = NULL;
6185194Sjohnz 	cert->c_issuer = NULL;
6195194Sjohnz 	return (cert);
6205194Sjohnz }
6215194Sjohnz 
6225194Sjohnz /*
6235194Sjohnz  * elfcertlib_freecert - freeup the memory of a cert
6245194Sjohnz  *
6255194Sjohnz  * IN cert
6265194Sjohnz  * OUT cert
6275194Sjohnz  * RETURN	N/A
6285194Sjohnz  *
6295194Sjohnz  */
6305194Sjohnz static void
6315194Sjohnz elfcertlib_freecert(ELFsign_t ess, ELFCert_t cert)
6325194Sjohnz {
6335194Sjohnz 	if (cert == NULL)
6345194Sjohnz 		return;
6355194Sjohnz 
6365194Sjohnz 	free(cert->c_subject);
6375194Sjohnz 	free(cert->c_issuer);
6385194Sjohnz 
6395194Sjohnz 	KMF_FreeKMFCert(ess->es_kmfhandle, &cert->c_cert);
6405194Sjohnz 	KMF_FreeKMFKey(ess->es_kmfhandle, &cert->c_privatekey);
6415194Sjohnz 
6425194Sjohnz 	free(cert);
6435194Sjohnz }
644