1df8bdeb3Sjohnz /*
2df8bdeb3Sjohnz  * CDDL HEADER START
3df8bdeb3Sjohnz  *
4df8bdeb3Sjohnz  * The contents of this file are subject to the terms of the
5df8bdeb3Sjohnz  * Common Development and Distribution License (the "License").
6df8bdeb3Sjohnz  * You may not use this file except in compliance with the License.
7df8bdeb3Sjohnz  *
8df8bdeb3Sjohnz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9df8bdeb3Sjohnz  * or http://www.opensolaris.org/os/licensing.
10df8bdeb3Sjohnz  * See the License for the specific language governing permissions
11df8bdeb3Sjohnz  * and limitations under the License.
12df8bdeb3Sjohnz  *
13df8bdeb3Sjohnz  * When distributing Covered Code, include this CDDL HEADER in each
14df8bdeb3Sjohnz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15df8bdeb3Sjohnz  * If applicable, add the following below this CDDL HEADER, with the
16df8bdeb3Sjohnz  * fields enclosed by brackets "[]" replaced with your own identifying
17df8bdeb3Sjohnz  * information: Portions Copyright [yyyy] [name of copyright owner]
18df8bdeb3Sjohnz  *
19df8bdeb3Sjohnz  * CDDL HEADER END
20df8bdeb3Sjohnz  */
21df8bdeb3Sjohnz 
22df8bdeb3Sjohnz /*
23*9f0bc604SWyllys Ingersoll  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24df8bdeb3Sjohnz  * Use is subject to license terms.
25df8bdeb3Sjohnz  */
26df8bdeb3Sjohnz 
27df8bdeb3Sjohnz #include <limits.h>
28df8bdeb3Sjohnz #include <sys/types.h>
29df8bdeb3Sjohnz #include <sys/stat.h>
30df8bdeb3Sjohnz #include <fcntl.h>
31df8bdeb3Sjohnz #include <unistd.h>
32df8bdeb3Sjohnz #include <dirent.h>
33df8bdeb3Sjohnz #include <strings.h>
34df8bdeb3Sjohnz #include <stdio.h>
35df8bdeb3Sjohnz #include <stdlib.h>
36df8bdeb3Sjohnz #include <errno.h>
37df8bdeb3Sjohnz #include <sys/mman.h>
38df8bdeb3Sjohnz #include <md5.h>
39df8bdeb3Sjohnz #include <pthread.h>
40df8bdeb3Sjohnz 
41df8bdeb3Sjohnz #include <cryptoutil.h>
42df8bdeb3Sjohnz 
43df8bdeb3Sjohnz #include <kmfapi.h>
44df8bdeb3Sjohnz #include <sys/crypto/elfsign.h>
45df8bdeb3Sjohnz #include <libelfsign.h>
46df8bdeb3Sjohnz 
47df8bdeb3Sjohnz #include <synch.h>
48df8bdeb3Sjohnz 
49df8bdeb3Sjohnz const char _PATH_ELFSIGN_CRYPTO_CERTS[] = CRYPTO_CERTS_DIR;
50df8bdeb3Sjohnz const char _PATH_ELFSIGN_ETC_CERTS[] = ETC_CERTS_DIR;
51df8bdeb3Sjohnz 
52df8bdeb3Sjohnz /*
53df8bdeb3Sjohnz  * The CACERT and OBJCACERT are the Cryptographic Trust Anchors
54df8bdeb3Sjohnz  * for the Solaris Cryptographic Framework.
5573556491SAnthony Scarpino  *
5673556491SAnthony Scarpino  * The SECACERT is the Signed Execution Trust Anchor that the
5773556491SAnthony Scarpino  * Cryptographic Framework uses for FIPS-140 validation of non-crypto
5873556491SAnthony Scarpino  * binaries
59df8bdeb3Sjohnz  */
60df8bdeb3Sjohnz static const char _PATH_CRYPTO_CACERT[] = CRYPTO_CERTS_DIR "/CA";
61df8bdeb3Sjohnz static const char _PATH_CRYPTO_OBJCACERT[] = CRYPTO_CERTS_DIR "/SUNWObjectCA";
6273556491SAnthony Scarpino static const char _PATH_CRYPTO_SECACERT[] = ETC_CERTS_DIR "/SUNWSolarisCA";
63df8bdeb3Sjohnz static ELFCert_t CACERT = NULL;
64df8bdeb3Sjohnz static ELFCert_t OBJCACERT = NULL;
6573556491SAnthony Scarpino static ELFCert_t SECACERT = NULL;
66df8bdeb3Sjohnz static pthread_mutex_t ca_mutex = PTHREAD_MUTEX_INITIALIZER;
67df8bdeb3Sjohnz 
68df8bdeb3Sjohnz static void elfcertlib_freecert(ELFsign_t, ELFCert_t);
69df8bdeb3Sjohnz static ELFCert_t elfcertlib_allocatecert(void);
70df8bdeb3Sjohnz 
71df8bdeb3Sjohnz /*
72df8bdeb3Sjohnz  * elfcertlib_verifycert - Verify the Cert with a Trust Anchor
73df8bdeb3Sjohnz  *
74df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
75df8bdeb3Sjohnz  *	cert
76df8bdeb3Sjohnz  * OUT	NONE
77df8bdeb3Sjohnz  * RETURN	TRUE/FALSE
78df8bdeb3Sjohnz  *
79df8bdeb3Sjohnz  * We first setup the Trust Anchor (CA and SUNWObjectCA) certs
80df8bdeb3Sjohnz  * if it hasn't been done already.  We verify that the files on disk
81df8bdeb3Sjohnz  * are those we expected.
82df8bdeb3Sjohnz  *
83df8bdeb3Sjohnz  * We then verify the given cert using the publickey of a TA.
84df8bdeb3Sjohnz  * If the passed in cert is a TA or it has been verified already we
85df8bdeb3Sjohnz  * short cut and return TRUE without futher validation.
86df8bdeb3Sjohnz  */
87df8bdeb3Sjohnz /*ARGSUSED*/
88df8bdeb3Sjohnz boolean_t
elfcertlib_verifycert(ELFsign_t ess,ELFCert_t cert)89df8bdeb3Sjohnz elfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert)
90df8bdeb3Sjohnz {
918bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
928bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
938bab47abSJohn.Zolnowsky@Sun.COM 
94df8bdeb3Sjohnz 	KMF_RETURN rv;
95df8bdeb3Sjohnz 	if ((cert->c_verified == E_OK) || (cert->c_verified == E_IS_TA)) {
96df8bdeb3Sjohnz 		return (B_TRUE);
97df8bdeb3Sjohnz 	}
98df8bdeb3Sjohnz 
99df8bdeb3Sjohnz 	(void) pthread_mutex_lock(&ca_mutex);
100df8bdeb3Sjohnz 	if (CACERT == NULL) {
101df8bdeb3Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT,
102df8bdeb3Sjohnz 		    NULL, &CACERT, ES_GET);
103df8bdeb3Sjohnz 	}
10473556491SAnthony Scarpino 
105df8bdeb3Sjohnz 	if (OBJCACERT == NULL) {
106df8bdeb3Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT,
107df8bdeb3Sjohnz 		    NULL, &OBJCACERT, ES_GET);
108df8bdeb3Sjohnz 	}
10973556491SAnthony Scarpino 
11073556491SAnthony Scarpino 	if (SECACERT == NULL) {
11173556491SAnthony Scarpino 		(void) elfcertlib_getcert(ess,
11273556491SAnthony Scarpino 		    (char *)_PATH_CRYPTO_SECACERT, NULL, &SECACERT,
11373556491SAnthony Scarpino 		    ES_GET_FIPS140);
11473556491SAnthony Scarpino 	}
11573556491SAnthony Scarpino 
116df8bdeb3Sjohnz 	(void) pthread_mutex_unlock(&ca_mutex);
117df8bdeb3Sjohnz 
118df8bdeb3Sjohnz 	if (CACERT != NULL) {
1198bab47abSJohn.Zolnowsky@Sun.COM 		numattr = 0;
1208bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
1218bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
1228bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
1238bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
1248bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_SIGNER_CERT_DATA_ATTR, &CACERT->c_cert.certificate,
1258bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
1268bab47abSJohn.Zolnowsky@Sun.COM 
1278bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
128df8bdeb3Sjohnz 		if (rv == KMF_OK) {
129df8bdeb3Sjohnz 			if (ess->es_certCAcallback != NULL)
130df8bdeb3Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
131df8bdeb3Sjohnz 				    cert, CACERT);
132df8bdeb3Sjohnz 			cert->c_verified = E_OK;
133df8bdeb3Sjohnz 			return (B_TRUE);
134df8bdeb3Sjohnz 		}
135df8bdeb3Sjohnz 	}
136df8bdeb3Sjohnz 
137df8bdeb3Sjohnz 	if (OBJCACERT != NULL) {
1388bab47abSJohn.Zolnowsky@Sun.COM 		numattr = 0;
1398bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
1408bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
1418bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
1428bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
1438bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_SIGNER_CERT_DATA_ATTR, &OBJCACERT->c_cert.certificate,
1448bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
1458bab47abSJohn.Zolnowsky@Sun.COM 
1468bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
147df8bdeb3Sjohnz 		if (rv == KMF_OK) {
148df8bdeb3Sjohnz 			if (ess->es_certCAcallback != NULL)
149df8bdeb3Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
150df8bdeb3Sjohnz 				    cert, OBJCACERT);
151df8bdeb3Sjohnz 			cert->c_verified = E_OK;
152df8bdeb3Sjohnz 			return (B_TRUE);
153df8bdeb3Sjohnz 		}
154df8bdeb3Sjohnz 	}
155df8bdeb3Sjohnz 
15673556491SAnthony Scarpino 	if (SECACERT != NULL) {
157*9f0bc604SWyllys Ingersoll 		numattr = 0;
158*9f0bc604SWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr++,
159*9f0bc604SWyllys Ingersoll 		    KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
160*9f0bc604SWyllys Ingersoll 		    sizeof (KMF_DATA));
161*9f0bc604SWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr++,
162*9f0bc604SWyllys Ingersoll 		    KMF_SIGNER_CERT_DATA_ATTR, &SECACERT->c_cert.certificate,
163*9f0bc604SWyllys Ingersoll 		    sizeof (KMF_DATA));
164*9f0bc604SWyllys Ingersoll 
165*9f0bc604SWyllys Ingersoll 		rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
16673556491SAnthony Scarpino 		if (rv == KMF_OK) {
16773556491SAnthony Scarpino 			if (ess->es_certCAcallback != NULL)
16873556491SAnthony Scarpino 				(ess->es_certvercallback)(ess->es_callbackctx,
16973556491SAnthony Scarpino 				    cert, SECACERT);
17073556491SAnthony Scarpino 			cert->c_verified = E_OK;
17173556491SAnthony Scarpino 			return (B_TRUE);
17273556491SAnthony Scarpino 		}
17373556491SAnthony Scarpino 	}
17473556491SAnthony Scarpino 
175df8bdeb3Sjohnz 	return (B_FALSE);
176df8bdeb3Sjohnz }
177df8bdeb3Sjohnz 
178df8bdeb3Sjohnz /*
179df8bdeb3Sjohnz  * elfcertlib_getcert - Get the certificate for signer_DN
180df8bdeb3Sjohnz  *
181df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
182df8bdeb3Sjohnz  *	cert_pathname	- path to cert (May be NULL)
183df8bdeb3Sjohnz  *	signer_DN	- The DN we are looking for (May be NULL)
184df8bdeb3Sjohnz  *      action		- indicates crypto verification call
185df8bdeb3Sjohnz  * OUT  certp		- allocated/loaded ELFCert_t
186df8bdeb3Sjohnz  *
187df8bdeb3Sjohnz  * If the cert_pathname is passed use it and don't search.
188df8bdeb3Sjohnz  * Otherwise, go looking in certificate directories
189df8bdeb3Sjohnz  */
190df8bdeb3Sjohnz boolean_t
elfcertlib_getcert(ELFsign_t ess,char * cert_pathname,char * signer_DN,ELFCert_t * certp,enum ES_ACTION action)191df8bdeb3Sjohnz elfcertlib_getcert(ELFsign_t ess, char *cert_pathname,
192df8bdeb3Sjohnz     char *signer_DN, ELFCert_t *certp, enum ES_ACTION action)
193df8bdeb3Sjohnz {
194df8bdeb3Sjohnz 	KMF_RETURN rv;
195df8bdeb3Sjohnz 	ELFCert_t	cert = NULL;
196df8bdeb3Sjohnz 	KMF_X509_DER_CERT certbuf[2];
197df8bdeb3Sjohnz 	uint32_t ncerts;
198df8bdeb3Sjohnz 	boolean_t ret = B_FALSE;
199df8bdeb3Sjohnz 	char	*pathlist[3], **plp;
200df8bdeb3Sjohnz 
201df8bdeb3Sjohnz 	cryptodebug("elfcertlib_getcert: path=%s, DN=%s",
202df8bdeb3Sjohnz 	    cert_pathname ? cert_pathname : "-none-",
203df8bdeb3Sjohnz 	    signer_DN ? signer_DN : "-none-");
204df8bdeb3Sjohnz 	*certp = NULL;
205df8bdeb3Sjohnz 	if (cert_pathname == NULL && signer_DN == NULL) {
206df8bdeb3Sjohnz 		cryptodebug("elfcertlib_getcert: lack of specificity");
207df8bdeb3Sjohnz 		return (ret);
208df8bdeb3Sjohnz 	}
209df8bdeb3Sjohnz 
210df8bdeb3Sjohnz 	plp = pathlist;
211df8bdeb3Sjohnz 	if (cert_pathname != NULL) {
212df8bdeb3Sjohnz 		/* look in the specified object */
213df8bdeb3Sjohnz 		*plp++ = cert_pathname;
214df8bdeb3Sjohnz 	} else {
215df8bdeb3Sjohnz 		/* look in the certificate directories */
216df8bdeb3Sjohnz 		*plp++ = (char *)_PATH_ELFSIGN_CRYPTO_CERTS;
217df8bdeb3Sjohnz 		/*
218df8bdeb3Sjohnz 		 * crypto verifications don't search beyond
219df8bdeb3Sjohnz 		 * _PATH_ELFSIGN_CRYPTO_CERTS
220df8bdeb3Sjohnz 		 */
221df8bdeb3Sjohnz 		if (action != ES_GET_CRYPTO)
222df8bdeb3Sjohnz 			*plp++ = (char *)_PATH_ELFSIGN_ETC_CERTS;
223df8bdeb3Sjohnz 	}
224df8bdeb3Sjohnz 	*plp = NULL;
225df8bdeb3Sjohnz 
226df8bdeb3Sjohnz 	if ((cert = elfcertlib_allocatecert()) == NULL) {
227df8bdeb3Sjohnz 		return (ret);
228df8bdeb3Sjohnz 	}
229df8bdeb3Sjohnz 
230df8bdeb3Sjohnz 	for (plp = pathlist; *plp; plp++) {
2318bab47abSJohn.Zolnowsky@Sun.COM 		KMF_ATTRIBUTE	attrlist[8];
2328bab47abSJohn.Zolnowsky@Sun.COM 		KMF_KEYSTORE_TYPE	kstype;
2338bab47abSJohn.Zolnowsky@Sun.COM 		KMF_CERT_VALIDITY	certvalidity;
2348bab47abSJohn.Zolnowsky@Sun.COM 		int		numattr;
2358bab47abSJohn.Zolnowsky@Sun.COM 
2368bab47abSJohn.Zolnowsky@Sun.COM 		kstype = KMF_KEYSTORE_OPENSSL;
2378bab47abSJohn.Zolnowsky@Sun.COM 		certvalidity = KMF_ALL_CERTS;
238df8bdeb3Sjohnz 		ncerts = 2;
239df8bdeb3Sjohnz 
2408bab47abSJohn.Zolnowsky@Sun.COM 		numattr = 0;
2418bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
2428bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2438bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
2448bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_X509_DER_CERT_ATTR, certbuf,
2458bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_X509_DER_CERT));
2468bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
2478bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_COUNT_ATTR, &ncerts, sizeof (uint32_t));
2488bab47abSJohn.Zolnowsky@Sun.COM 		if (signer_DN != NULL) {
2498bab47abSJohn.Zolnowsky@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr++,
2508bab47abSJohn.Zolnowsky@Sun.COM 			    KMF_SUBJECT_NAME_ATTR, signer_DN,
2518bab47abSJohn.Zolnowsky@Sun.COM 			    strlen(signer_DN));
2528bab47abSJohn.Zolnowsky@Sun.COM 		}
2538bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
2548bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_CERT_VALIDITY_ATTR, &certvalidity,
2558bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_CERT_VALIDITY));
2568bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
2578bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_CERT_FILENAME_ATTR, *plp, strlen (*plp));
2588bab47abSJohn.Zolnowsky@Sun.COM 
2598bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_find_cert(ess->es_kmfhandle, numattr, attrlist);
2608bab47abSJohn.Zolnowsky@Sun.COM 
261df8bdeb3Sjohnz 		if (rv != KMF_OK)
262df8bdeb3Sjohnz 			continue;
2638bab47abSJohn.Zolnowsky@Sun.COM 		/* found one */
264df8bdeb3Sjohnz 		cert->c_cert = certbuf[0];
2658bab47abSJohn.Zolnowsky@Sun.COM 		if (ncerts > 1) {
2668bab47abSJohn.Zolnowsky@Sun.COM 			/* release any extras */
2678bab47abSJohn.Zolnowsky@Sun.COM 			kmf_free_kmf_cert(ess->es_kmfhandle, &certbuf[1]);
2688bab47abSJohn.Zolnowsky@Sun.COM 			if (signer_DN == NULL) {
2698bab47abSJohn.Zolnowsky@Sun.COM 				/* There can be only one */
2708bab47abSJohn.Zolnowsky@Sun.COM 				cryptodebug("elfcertlib_getcert: "
2718bab47abSJohn.Zolnowsky@Sun.COM 				    "too many certificates found in %s",
2728bab47abSJohn.Zolnowsky@Sun.COM 				    cert_pathname);
2738bab47abSJohn.Zolnowsky@Sun.COM 				goto cleanup;
2748bab47abSJohn.Zolnowsky@Sun.COM 			}
2758bab47abSJohn.Zolnowsky@Sun.COM 		}
2768bab47abSJohn.Zolnowsky@Sun.COM 		/* cache subject and issuer */
2778bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_get_cert_subject_str(ess->es_kmfhandle,
278df8bdeb3Sjohnz 		    &cert->c_cert.certificate, &cert->c_subject);
279df8bdeb3Sjohnz 		if (rv != KMF_OK)
280df8bdeb3Sjohnz 			goto cleanup;
281df8bdeb3Sjohnz 
2828bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_get_cert_issuer_str(ess->es_kmfhandle,
283df8bdeb3Sjohnz 		    &cert->c_cert.certificate, &cert->c_issuer);
284df8bdeb3Sjohnz 		if (rv != KMF_OK)
285df8bdeb3Sjohnz 			goto cleanup;
286df8bdeb3Sjohnz 		break;
287df8bdeb3Sjohnz 	}
288df8bdeb3Sjohnz 	if (*plp == NULL) {
289df8bdeb3Sjohnz 		cryptodebug("elfcertlib_getcert: no certificate found");
290df8bdeb3Sjohnz 		goto cleanup;
291df8bdeb3Sjohnz 	}
292df8bdeb3Sjohnz 
293df8bdeb3Sjohnz 	cert->c_verified = E_UNCHECKED;
294df8bdeb3Sjohnz 
295df8bdeb3Sjohnz 	/*
2962225707cSValerie Bubb Fenwick 	 * If the cert we are loading is the trust anchor (ie the CA) then
297df8bdeb3Sjohnz 	 * we mark it as such in cert.  This is so that we don't attempt
298df8bdeb3Sjohnz 	 * to verify it later.  The CA is always implicitly verified.
299df8bdeb3Sjohnz 	 */
300df8bdeb3Sjohnz 	if (cert_pathname != NULL && (
301df8bdeb3Sjohnz 	    strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 ||
30273556491SAnthony Scarpino 	    strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0 ||
30373556491SAnthony Scarpino 	    strcmp(cert_pathname, _PATH_CRYPTO_SECACERT) == 0)) {
304df8bdeb3Sjohnz 		if (ess->es_certCAcallback != NULL)
305df8bdeb3Sjohnz 			(ess->es_certCAcallback)(ess->es_callbackctx, cert,
306df8bdeb3Sjohnz 			    cert_pathname);
307df8bdeb3Sjohnz 		cert->c_verified = E_IS_TA;
308df8bdeb3Sjohnz 	}
309df8bdeb3Sjohnz 
310df8bdeb3Sjohnz 	ret = B_TRUE;
311df8bdeb3Sjohnz 
312df8bdeb3Sjohnz cleanup:
313df8bdeb3Sjohnz 	if (ret) {
314df8bdeb3Sjohnz 		*certp = cert;
315df8bdeb3Sjohnz 	} else {
316df8bdeb3Sjohnz 		if (cert != NULL)
317df8bdeb3Sjohnz 			elfcertlib_freecert(ess, cert);
318df8bdeb3Sjohnz 		if (signer_DN != NULL)
319df8bdeb3Sjohnz 			cryptoerror(LOG_ERR, "unable to find a certificate "
320df8bdeb3Sjohnz 			    "for DN: %s", signer_DN);
321df8bdeb3Sjohnz 		else
322df8bdeb3Sjohnz 			cryptoerror(LOG_ERR, "unable to load certificate "
323df8bdeb3Sjohnz 			    "from %s", cert_pathname);
324df8bdeb3Sjohnz 	}
325df8bdeb3Sjohnz 	return (ret);
326df8bdeb3Sjohnz }
327df8bdeb3Sjohnz 
328df8bdeb3Sjohnz /*
329df8bdeb3Sjohnz  * elfcertlib_loadprivatekey - Load the private key from path
330df8bdeb3Sjohnz  *
331df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
332df8bdeb3Sjohnz  *	cert
333df8bdeb3Sjohnz  *	pathname
334df8bdeb3Sjohnz  * OUT	cert
335df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
336df8bdeb3Sjohnz  */
337df8bdeb3Sjohnz boolean_t
elfcertlib_loadprivatekey(ELFsign_t ess,ELFCert_t cert,const char * pathname)338df8bdeb3Sjohnz elfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname)
339df8bdeb3Sjohnz {
3408bab47abSJohn.Zolnowsky@Sun.COM 	KMF_RETURN	rv = KMF_OK;
341df8bdeb3Sjohnz 	KMF_KEY_HANDLE	keybuf[2];
3428bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[16];
3438bab47abSJohn.Zolnowsky@Sun.COM 	uint32_t	nkeys;
3448bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
3458bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEY_ALG	keytype;
3468bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEY_CLASS	keyclass;
3478bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ENCODE_FORMAT	format;
3488bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
3498bab47abSJohn.Zolnowsky@Sun.COM 
3508bab47abSJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_OPENSSL;
3518bab47abSJohn.Zolnowsky@Sun.COM 	nkeys = 2;
3528bab47abSJohn.Zolnowsky@Sun.COM 	keytype = KMF_KEYALG_NONE;
3538bab47abSJohn.Zolnowsky@Sun.COM 	keyclass = KMF_ASYM_PRI;
3548bab47abSJohn.Zolnowsky@Sun.COM 	format = KMF_FORMAT_UNDEF;
3558bab47abSJohn.Zolnowsky@Sun.COM 
3568bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
3578bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
3588bab47abSJohn.Zolnowsky@Sun.COM 	    &kstype, sizeof (kstype));
3598bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
3608bab47abSJohn.Zolnowsky@Sun.COM 	    keybuf, sizeof (KMF_KEY_HANDLE));
3618bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
3628bab47abSJohn.Zolnowsky@Sun.COM 	    &nkeys, sizeof (uint32_t));
3638bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
3648bab47abSJohn.Zolnowsky@Sun.COM 	    &keytype, sizeof (keytype));
3658bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
3668bab47abSJohn.Zolnowsky@Sun.COM 	    &keyclass, sizeof (keyclass));
3678bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
3688bab47abSJohn.Zolnowsky@Sun.COM 	    &format, sizeof (format));
3698bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_FILENAME_ATTR,
3708bab47abSJohn.Zolnowsky@Sun.COM 	    (char *)pathname, strlen(pathname));
3718bab47abSJohn.Zolnowsky@Sun.COM 
3728bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
373df8bdeb3Sjohnz 	if (rv != KMF_OK)
374df8bdeb3Sjohnz 		return (B_FALSE);
375df8bdeb3Sjohnz 	if (nkeys != 1) {
376df8bdeb3Sjohnz 		/* lack of specificity */
377df8bdeb3Sjohnz 		cryptodebug("found %d keys at %s", nkeys, pathname);
378df8bdeb3Sjohnz 		return (B_FALSE);
379df8bdeb3Sjohnz 	}
380df8bdeb3Sjohnz 	cert->c_privatekey = keybuf[0];
381df8bdeb3Sjohnz 	cryptodebug("key %s loaded", pathname);
382df8bdeb3Sjohnz 	return (B_TRUE);
383df8bdeb3Sjohnz }
384df8bdeb3Sjohnz 
385df8bdeb3Sjohnz /*
386df8bdeb3Sjohnz  * elfcertlib_loadtokenkey - Load the private key from token
387df8bdeb3Sjohnz  *
388df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
389df8bdeb3Sjohnz  *	cert
390df8bdeb3Sjohnz  *	token_label
391df8bdeb3Sjohnz  *	pin
392df8bdeb3Sjohnz  * OUT	cert
393df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
394df8bdeb3Sjohnz  */
395df8bdeb3Sjohnz boolean_t
elfcertlib_loadtokenkey(ELFsign_t ess,ELFCert_t cert,const char * token_label,const char * pin)396df8bdeb3Sjohnz elfcertlib_loadtokenkey(ELFsign_t ess, ELFCert_t cert,
397df8bdeb3Sjohnz     const char *token_label, const char *pin)
398df8bdeb3Sjohnz {
3998bab47abSJohn.Zolnowsky@Sun.COM 	KMF_RETURN	rv;
4008bab47abSJohn.Zolnowsky@Sun.COM 	char		*idstr = NULL;
4018bab47abSJohn.Zolnowsky@Sun.COM 	char		*kmferr;
4028bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[16];
4038bab47abSJohn.Zolnowsky@Sun.COM 	uint32_t	nkeys;
4048bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
4058bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEY_ALG	keytype;
4068bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEY_CLASS	keyclass;
4078bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ENCODE_FORMAT	format;
4088bab47abSJohn.Zolnowsky@Sun.COM 	KMF_CREDENTIAL	pincred;
4098bab47abSJohn.Zolnowsky@Sun.COM 	boolean_t	tokenbool, privatebool;
4108bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
411df8bdeb3Sjohnz 
412df8bdeb3Sjohnz 	/*
413df8bdeb3Sjohnz 	 * We will search for the key based on the ID attribute
414df8bdeb3Sjohnz 	 * which was added when the key was created.  ID is
415df8bdeb3Sjohnz 	 * a SHA-1 hash of the public modulus shared by the
416df8bdeb3Sjohnz 	 * key and the certificate.
417df8bdeb3Sjohnz 	 */
4188bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_get_cert_id_str(&cert->c_cert.certificate, &idstr);
419df8bdeb3Sjohnz 	if (rv != KMF_OK) {
4208bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(rv, &kmferr);
4218bab47abSJohn.Zolnowsky@Sun.COM 		cryptodebug("Error getting ID from cert: %s\n",
4228bab47abSJohn.Zolnowsky@Sun.COM 		    (kmferr ? kmferr : "Unrecognized KMF error"));
4238bab47abSJohn.Zolnowsky@Sun.COM 		free(kmferr);
424df8bdeb3Sjohnz 		return (B_FALSE);
425df8bdeb3Sjohnz 	}
4268bab47abSJohn.Zolnowsky@Sun.COM 
4278bab47abSJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_PK11TOKEN;
4288bab47abSJohn.Zolnowsky@Sun.COM 	nkeys = 1;
4298bab47abSJohn.Zolnowsky@Sun.COM 	keytype = KMF_KEYALG_NONE;
4308bab47abSJohn.Zolnowsky@Sun.COM 	keyclass = KMF_ASYM_PRI;
4318bab47abSJohn.Zolnowsky@Sun.COM 	format = KMF_FORMAT_UNDEF;
4328bab47abSJohn.Zolnowsky@Sun.COM 	pincred.cred = (char *)pin;
4338bab47abSJohn.Zolnowsky@Sun.COM 	pincred.credlen = strlen(pin);
4348bab47abSJohn.Zolnowsky@Sun.COM 	tokenbool = B_FALSE;
4358bab47abSJohn.Zolnowsky@Sun.COM 	privatebool = B_TRUE;
4368bab47abSJohn.Zolnowsky@Sun.COM 
4378bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
4388bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
4398bab47abSJohn.Zolnowsky@Sun.COM 	    &kstype, sizeof (kstype));
4408bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
4418bab47abSJohn.Zolnowsky@Sun.COM 	    &cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
4428bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
4438bab47abSJohn.Zolnowsky@Sun.COM 	    &nkeys, sizeof (uint32_t));
4448bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
4458bab47abSJohn.Zolnowsky@Sun.COM 	    &keytype, sizeof (keytype));
4468bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
4478bab47abSJohn.Zolnowsky@Sun.COM 	    &keyclass, sizeof (keyclass));
4488bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
4498bab47abSJohn.Zolnowsky@Sun.COM 	    &format, sizeof (format));
4508bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_IDSTR_ATTR,
4518bab47abSJohn.Zolnowsky@Sun.COM 	    idstr, strlen(idstr));
4528bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_CREDENTIAL_ATTR,
4538bab47abSJohn.Zolnowsky@Sun.COM 	    &pincred, sizeof (KMF_CREDENTIAL));
4548bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_TOKEN_BOOL_ATTR,
4558bab47abSJohn.Zolnowsky@Sun.COM 	    &tokenbool, sizeof (tokenbool));
4568bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_PRIVATE_BOOL_ATTR,
4578bab47abSJohn.Zolnowsky@Sun.COM 	    &privatebool, sizeof (privatebool));
4588bab47abSJohn.Zolnowsky@Sun.COM 
4598bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
4608bab47abSJohn.Zolnowsky@Sun.COM 	free(idstr);
4618bab47abSJohn.Zolnowsky@Sun.COM 	if (rv != KMF_OK) {
4628bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(rv, &kmferr);
4638bab47abSJohn.Zolnowsky@Sun.COM 		cryptodebug("Error finding private key: %s\n",
4648bab47abSJohn.Zolnowsky@Sun.COM 		    (kmferr ? kmferr : "Unrecognized KMF error"));
4658bab47abSJohn.Zolnowsky@Sun.COM 		free(kmferr);
4668bab47abSJohn.Zolnowsky@Sun.COM 		return (B_FALSE);
4678bab47abSJohn.Zolnowsky@Sun.COM 	}
4688bab47abSJohn.Zolnowsky@Sun.COM 	if (nkeys != 1) {
4698bab47abSJohn.Zolnowsky@Sun.COM 		cryptodebug("Error finding private key: No key found\n");
470df8bdeb3Sjohnz 		return (B_FALSE);
471df8bdeb3Sjohnz 	}
472df8bdeb3Sjohnz 	cryptodebug("key found in %s", token_label);
473df8bdeb3Sjohnz 	cryptodebug("elfcertlib_loadprivatekey = 0x%.8X",
474df8bdeb3Sjohnz 	    &cert->c_privatekey);
475df8bdeb3Sjohnz 
476df8bdeb3Sjohnz 	return (B_TRUE);
477df8bdeb3Sjohnz }
478df8bdeb3Sjohnz 
479df8bdeb3Sjohnz static const CK_BYTE MD5_DER_PREFIX[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
480df8bdeb3Sjohnz 	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
481df8bdeb3Sjohnz 
482df8bdeb3Sjohnz /*
483df8bdeb3Sjohnz  * elfcertlib_sign - sign the given DATA using the privatekey in cert
484df8bdeb3Sjohnz  *
485df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
486df8bdeb3Sjohnz  *	cert
487df8bdeb3Sjohnz  *	data
488df8bdeb3Sjohnz  *	data_len
489df8bdeb3Sjohnz  * OUT	sig	- must be big enough to hold the signature of data
490df8bdeb3Sjohnz  *		  Caller must allocate
491df8bdeb3Sjohnz  *	sig_len	- actual length used; 0 on failure.
492df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
493df8bdeb3Sjohnz  */
494df8bdeb3Sjohnz /*ARGSUSED*/
495df8bdeb3Sjohnz 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)496df8bdeb3Sjohnz elfcertlib_sign(ELFsign_t ess, ELFCert_t cert,
497df8bdeb3Sjohnz 	const uchar_t *data, size_t data_len,
498df8bdeb3Sjohnz 	uchar_t *sig, size_t *sig_len)
499df8bdeb3Sjohnz {
5008bab47abSJohn.Zolnowsky@Sun.COM 	KMF_RETURN	ret;
5018bab47abSJohn.Zolnowsky@Sun.COM 	KMF_DATA	tobesigned;
5028bab47abSJohn.Zolnowsky@Sun.COM 	KMF_DATA	signature;
5038bab47abSJohn.Zolnowsky@Sun.COM 	uchar_t		der_data[sizeof (MD5_DER_PREFIX) + MD5_DIGEST_LENGTH];
5048bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
5058bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
506df8bdeb3Sjohnz 
507df8bdeb3Sjohnz 	if (ess->es_version <= FILESIG_VERSION2) {
508df8bdeb3Sjohnz 		/* compatibility: take MD5 hash of SHA1 hash */
509df8bdeb3Sjohnz 		size_t	derlen = MD5_DIGEST_LENGTH;
510df8bdeb3Sjohnz 		MD5_CTX ctx;
511df8bdeb3Sjohnz 
512df8bdeb3Sjohnz 		/*
513df8bdeb3Sjohnz 		 * first: digest using software-based methods, don't
514df8bdeb3Sjohnz 		 * rely on the token for hashing.
515df8bdeb3Sjohnz 		 */
516df8bdeb3Sjohnz 		MD5Init(&ctx);
517df8bdeb3Sjohnz 		MD5Update(&ctx, data, data_len);
518df8bdeb3Sjohnz 		MD5Final(&der_data[sizeof (MD5_DER_PREFIX)], &ctx);
519df8bdeb3Sjohnz 
520df8bdeb3Sjohnz 		/*
521df8bdeb3Sjohnz 		 * second: insert prefix
522df8bdeb3Sjohnz 		 */
523df8bdeb3Sjohnz 		(void) memcpy(der_data, MD5_DER_PREFIX,
524df8bdeb3Sjohnz 		    sizeof (MD5_DER_PREFIX));
525df8bdeb3Sjohnz 		/*
526df8bdeb3Sjohnz 		 * prepare to sign the local buffer
527df8bdeb3Sjohnz 		 */
528df8bdeb3Sjohnz 		tobesigned.Data = (uchar_t *)der_data;
529df8bdeb3Sjohnz 		tobesigned.Length = sizeof (MD5_DER_PREFIX) + derlen;
530df8bdeb3Sjohnz 	} else {
531df8bdeb3Sjohnz 		tobesigned.Data = (uchar_t *)data;
532df8bdeb3Sjohnz 		tobesigned.Length = data_len;
533df8bdeb3Sjohnz 	}
534df8bdeb3Sjohnz 
535df8bdeb3Sjohnz 	signature.Data = (uchar_t *)sig;
536df8bdeb3Sjohnz 	signature.Length = *sig_len;
537df8bdeb3Sjohnz 
5388bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
5398bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
5408bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_KEYSTORE_TYPE_ATTR, &(cert->c_privatekey.kstype),
5418bab47abSJohn.Zolnowsky@Sun.COM 	    sizeof (KMF_KEYSTORE_TYPE));
5428bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
5438bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_KEY_HANDLE_ATTR, &cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
5448bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
5458bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_OID_ATTR, (KMF_OID *)&KMFOID_RSA, sizeof (KMF_OID));
5468bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
5478bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_DATA_ATTR, &tobesigned, sizeof (KMF_DATA));
5488bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
5498bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_OUT_DATA_ATTR, &signature, sizeof (KMF_DATA));
5508bab47abSJohn.Zolnowsky@Sun.COM 
5518bab47abSJohn.Zolnowsky@Sun.COM 	ret = kmf_sign_data(ess->es_kmfhandle, numattr, attrlist);
552df8bdeb3Sjohnz 
553df8bdeb3Sjohnz 	if (ret != KMF_OK) {
5548bab47abSJohn.Zolnowsky@Sun.COM 		char	*kmferr;
5558bab47abSJohn.Zolnowsky@Sun.COM 
5568bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(ret, &kmferr);
5578bab47abSJohn.Zolnowsky@Sun.COM 		cryptodebug("Error signing data: %s\n",
5588bab47abSJohn.Zolnowsky@Sun.COM 		    (kmferr ? kmferr : "Unrecognized KMF error"));
5598bab47abSJohn.Zolnowsky@Sun.COM 		free(kmferr);
560df8bdeb3Sjohnz 		*sig_len = 0;
561df8bdeb3Sjohnz 		return (B_FALSE);
562df8bdeb3Sjohnz 	}
563df8bdeb3Sjohnz 	*sig_len = signature.Length;
564df8bdeb3Sjohnz 	return (B_TRUE);
565df8bdeb3Sjohnz }
566df8bdeb3Sjohnz 
567df8bdeb3Sjohnz /*
568df8bdeb3Sjohnz  * elfcertlib_verifysig - verify the given DATA using the public key in cert
569df8bdeb3Sjohnz  *
570df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
571df8bdeb3Sjohnz  *	cert
572df8bdeb3Sjohnz  *	signature
573df8bdeb3Sjohnz  *	sig_len
574df8bdeb3Sjohnz  *	data
575df8bdeb3Sjohnz  *	data_len
576df8bdeb3Sjohnz  * OUT	N/A
577df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
578df8bdeb3Sjohnz  */
579df8bdeb3Sjohnz 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)580df8bdeb3Sjohnz elfcertlib_verifysig(ELFsign_t ess, ELFCert_t cert,
581df8bdeb3Sjohnz 	const uchar_t *signature, size_t sig_len,
582df8bdeb3Sjohnz 	const uchar_t *data, size_t data_len)
583df8bdeb3Sjohnz {
584df8bdeb3Sjohnz 	KMF_RETURN	rv;
585df8bdeb3Sjohnz 	KMF_DATA	indata;
586df8bdeb3Sjohnz 	KMF_DATA	insig;
587df8bdeb3Sjohnz 	KMF_ALGORITHM_INDEX algid;
5888bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
5898bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
5908bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
591df8bdeb3Sjohnz 
592df8bdeb3Sjohnz 	indata.Data = (uchar_t *)data;
593df8bdeb3Sjohnz 	indata.Length = data_len;
594df8bdeb3Sjohnz 	insig.Data = (uchar_t *)signature;
595df8bdeb3Sjohnz 	insig.Length = sig_len;
596df8bdeb3Sjohnz 
597df8bdeb3Sjohnz 	if (ess->es_version <= FILESIG_VERSION2)
598df8bdeb3Sjohnz 		algid = KMF_ALGID_MD5WithRSA;
599df8bdeb3Sjohnz 	else
600df8bdeb3Sjohnz 		algid = KMF_ALGID_RSA;
601df8bdeb3Sjohnz 
602df8bdeb3Sjohnz 	/*
6032225707cSValerie Bubb Fenwick 	 * We tell KMF to use the PKCS11 verification APIs
6042225707cSValerie Bubb Fenwick 	 * here to prevent the use of OpenSSL and to keep
6052225707cSValerie Bubb Fenwick 	 * all validation within the FIPS-140 boundary for
6062225707cSValerie Bubb Fenwick 	 * the Cryptographic Framework.
607df8bdeb3Sjohnz 	 */
6088bab47abSJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_PK11TOKEN;
6098bab47abSJohn.Zolnowsky@Sun.COM 
6108bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
6118bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
6128bab47abSJohn.Zolnowsky@Sun.COM 	    &kstype,  sizeof (kstype));
6138bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_DATA_ATTR,
6148bab47abSJohn.Zolnowsky@Sun.COM 	    &indata, sizeof (KMF_DATA));
6158bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_IN_SIGN_ATTR,
6168bab47abSJohn.Zolnowsky@Sun.COM 	    &insig, sizeof (KMF_DATA));
6178bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_SIGNER_CERT_DATA_ATTR,
6188bab47abSJohn.Zolnowsky@Sun.COM 	    (KMF_DATA *)(&cert->c_cert.certificate), sizeof (KMF_DATA));
6198bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_ALGORITHM_INDEX_ATTR,
6208bab47abSJohn.Zolnowsky@Sun.COM 	    &algid, sizeof (algid));
6218bab47abSJohn.Zolnowsky@Sun.COM 
6228bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_verify_data(ess->es_kmfhandle, numattr, attrlist);
623df8bdeb3Sjohnz 
624df8bdeb3Sjohnz 	return ((rv == KMF_OK));
625df8bdeb3Sjohnz }
626df8bdeb3Sjohnz 
627df8bdeb3Sjohnz /*
628df8bdeb3Sjohnz  * elfcertlib_getdn
629df8bdeb3Sjohnz  *
630df8bdeb3Sjohnz  * IN	cert
631df8bdeb3Sjohnz  * OUT	NONE
632df8bdeb3Sjohnz  * RETURN 	dn or NULL
633df8bdeb3Sjohnz  */
634df8bdeb3Sjohnz char *
elfcertlib_getdn(ELFCert_t cert)635df8bdeb3Sjohnz elfcertlib_getdn(ELFCert_t cert)
636df8bdeb3Sjohnz {
637df8bdeb3Sjohnz 	cryptodebug("elfcertlib_getdn");
638df8bdeb3Sjohnz 
639df8bdeb3Sjohnz 	return (cert->c_subject);
640df8bdeb3Sjohnz }
641df8bdeb3Sjohnz 
642df8bdeb3Sjohnz /*
643df8bdeb3Sjohnz  * elfcertlib_getissuer
644df8bdeb3Sjohnz  *
645df8bdeb3Sjohnz  * IN	cert
646df8bdeb3Sjohnz  * OUT	NONE
647df8bdeb3Sjohnz  * RETURN 	dn or NULL
648df8bdeb3Sjohnz  */
649df8bdeb3Sjohnz char *
elfcertlib_getissuer(ELFCert_t cert)650df8bdeb3Sjohnz elfcertlib_getissuer(ELFCert_t cert)
651df8bdeb3Sjohnz {
652df8bdeb3Sjohnz 	cryptodebug("elfcertlib_issuer");
653df8bdeb3Sjohnz 
654df8bdeb3Sjohnz 	return (cert->c_issuer);
655df8bdeb3Sjohnz }
656df8bdeb3Sjohnz 
657df8bdeb3Sjohnz boolean_t
elfcertlib_init(ELFsign_t ess)658df8bdeb3Sjohnz elfcertlib_init(ELFsign_t ess)
659df8bdeb3Sjohnz {
660df8bdeb3Sjohnz 	boolean_t rc = B_TRUE;
661df8bdeb3Sjohnz 	KMF_RETURN rv;
662df8bdeb3Sjohnz 	if (ess->es_kmfhandle == NULL) {
6638bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_initialize(&ess->es_kmfhandle, NULL, NULL);
664df8bdeb3Sjohnz 		if (rv != KMF_OK) {
665df8bdeb3Sjohnz 			cryptoerror(LOG_ERR,
666df8bdeb3Sjohnz 			    "unable to initialize KMF library");
667df8bdeb3Sjohnz 			rc = B_FALSE;
668df8bdeb3Sjohnz 		}
669df8bdeb3Sjohnz 	}
670df8bdeb3Sjohnz 	return (rc);
671df8bdeb3Sjohnz }
672df8bdeb3Sjohnz 
673df8bdeb3Sjohnz void
elfcertlib_fini(ELFsign_t ess)674df8bdeb3Sjohnz elfcertlib_fini(ELFsign_t ess)
675df8bdeb3Sjohnz {
6768bab47abSJohn.Zolnowsky@Sun.COM 	(void) kmf_finalize(ess->es_kmfhandle);
677df8bdeb3Sjohnz }
678df8bdeb3Sjohnz 
679df8bdeb3Sjohnz /*
680df8bdeb3Sjohnz  * set the token device
681df8bdeb3Sjohnz  */
682df8bdeb3Sjohnz boolean_t
elfcertlib_settoken(ELFsign_t ess,char * token)683df8bdeb3Sjohnz elfcertlib_settoken(ELFsign_t ess, char *token)
684df8bdeb3Sjohnz {
6858bab47abSJohn.Zolnowsky@Sun.COM 	boolean_t	rc = B_TRUE;
6868bab47abSJohn.Zolnowsky@Sun.COM 	KMF_RETURN	rv;
6878bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
6888bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
6898bab47abSJohn.Zolnowsky@Sun.COM 	boolean_t	readonly;
6908bab47abSJohn.Zolnowsky@Sun.COM 	int	numattr;
6918bab47abSJohn.Zolnowsky@Sun.COM 
6928bab47abSJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_PK11TOKEN;
6938bab47abSJohn.Zolnowsky@Sun.COM 	readonly = B_TRUE;
6948bab47abSJohn.Zolnowsky@Sun.COM 
6958bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
6968bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
6978bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
6988bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
6998bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_TOKEN_LABEL_ATTR, token, strlen(token));
7008bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
7018bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_READONLY_ATTR, &readonly, sizeof (readonly));
7028bab47abSJohn.Zolnowsky@Sun.COM 
7038bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_configure_keystore(ess->es_kmfhandle, numattr, attrlist);
704df8bdeb3Sjohnz 	if (rv != KMF_OK) {
705df8bdeb3Sjohnz 		cryptoerror(LOG_ERR, "unable to select token\n");
706df8bdeb3Sjohnz 		rc = B_FALSE;
707df8bdeb3Sjohnz 	}
708df8bdeb3Sjohnz 
709df8bdeb3Sjohnz 	return (rc);
710df8bdeb3Sjohnz }
711df8bdeb3Sjohnz 
712df8bdeb3Sjohnz /*
713df8bdeb3Sjohnz  * set the certificate CA identification callback
714df8bdeb3Sjohnz  */
715df8bdeb3Sjohnz void
elfcertlib_setcertCAcallback(ELFsign_t ess,void (* cb)(void *,ELFCert_t,char *))716df8bdeb3Sjohnz elfcertlib_setcertCAcallback(ELFsign_t ess,
717df8bdeb3Sjohnz     void (*cb)(void *, ELFCert_t, char *))
718df8bdeb3Sjohnz {
719df8bdeb3Sjohnz 	ess->es_certCAcallback = cb;
720df8bdeb3Sjohnz }
721df8bdeb3Sjohnz 
722df8bdeb3Sjohnz /*
723df8bdeb3Sjohnz  * set the certificate verification callback
724df8bdeb3Sjohnz  */
725df8bdeb3Sjohnz void
elfcertlib_setcertvercallback(ELFsign_t ess,void (* cb)(void *,ELFCert_t,ELFCert_t))726df8bdeb3Sjohnz elfcertlib_setcertvercallback(ELFsign_t ess,
727df8bdeb3Sjohnz     void (*cb)(void *, ELFCert_t, ELFCert_t))
728df8bdeb3Sjohnz {
729df8bdeb3Sjohnz 	ess->es_certvercallback = cb;
730df8bdeb3Sjohnz }
731df8bdeb3Sjohnz 
732df8bdeb3Sjohnz 
733df8bdeb3Sjohnz /*
734df8bdeb3Sjohnz  * elfcertlib_releasecert - release a cert
735df8bdeb3Sjohnz  *
736df8bdeb3Sjohnz  * IN cert
737df8bdeb3Sjohnz  * OUT cert
738df8bdeb3Sjohnz  * RETURN	N/A
739df8bdeb3Sjohnz  *
740df8bdeb3Sjohnz  */
741df8bdeb3Sjohnz void
elfcertlib_releasecert(ELFsign_t ess,ELFCert_t cert)742df8bdeb3Sjohnz elfcertlib_releasecert(ELFsign_t ess, ELFCert_t cert)
743df8bdeb3Sjohnz {
744df8bdeb3Sjohnz 	elfcertlib_freecert(ess, cert);
745df8bdeb3Sjohnz }
746df8bdeb3Sjohnz 
747df8bdeb3Sjohnz /*
748df8bdeb3Sjohnz  * elfcertlib_allocatecert - create a new ELFCert_t
749df8bdeb3Sjohnz  *
750df8bdeb3Sjohnz  * IN N/A
751df8bdeb3Sjohnz  * OUT	N/A
752df8bdeb3Sjohnz  * RETURN 	ELFCert_t, NULL on failure.
753df8bdeb3Sjohnz  */
754df8bdeb3Sjohnz static ELFCert_t
elfcertlib_allocatecert(void)755df8bdeb3Sjohnz elfcertlib_allocatecert(void)
756df8bdeb3Sjohnz {
757df8bdeb3Sjohnz 	ELFCert_t cert = NULL;
758df8bdeb3Sjohnz 
759df8bdeb3Sjohnz 	cert = malloc(sizeof (struct ELFCert_s));
760df8bdeb3Sjohnz 	if (cert == NULL) {
761df8bdeb3Sjohnz 		cryptoerror(LOG_ERR,
762df8bdeb3Sjohnz 		    "elfcertlib_allocatecert: malloc failed %s",
763df8bdeb3Sjohnz 		    strerror(errno));
764df8bdeb3Sjohnz 		return (NULL);
765df8bdeb3Sjohnz 	}
766df8bdeb3Sjohnz 	(void) memset(cert, 0, sizeof (struct ELFCert_s));
767df8bdeb3Sjohnz 	cert->c_verified = E_UNCHECKED;
768df8bdeb3Sjohnz 	cert->c_subject = NULL;
769df8bdeb3Sjohnz 	cert->c_issuer = NULL;
770df8bdeb3Sjohnz 	return (cert);
771df8bdeb3Sjohnz }
772df8bdeb3Sjohnz 
773df8bdeb3Sjohnz /*
774df8bdeb3Sjohnz  * elfcertlib_freecert - freeup the memory of a cert
775df8bdeb3Sjohnz  *
776df8bdeb3Sjohnz  * IN cert
777df8bdeb3Sjohnz  * OUT cert
778df8bdeb3Sjohnz  * RETURN	N/A
779df8bdeb3Sjohnz  *
780df8bdeb3Sjohnz  */
781df8bdeb3Sjohnz static void
elfcertlib_freecert(ELFsign_t ess,ELFCert_t cert)782df8bdeb3Sjohnz elfcertlib_freecert(ELFsign_t ess, ELFCert_t cert)
783df8bdeb3Sjohnz {
784df8bdeb3Sjohnz 	if (cert == NULL)
785df8bdeb3Sjohnz 		return;
786df8bdeb3Sjohnz 
787df8bdeb3Sjohnz 	free(cert->c_subject);
788df8bdeb3Sjohnz 	free(cert->c_issuer);
789df8bdeb3Sjohnz 
7908bab47abSJohn.Zolnowsky@Sun.COM 	kmf_free_kmf_cert(ess->es_kmfhandle, &cert->c_cert);
7918bab47abSJohn.Zolnowsky@Sun.COM 	kmf_free_kmf_key(ess->es_kmfhandle, &cert->c_privatekey);
792df8bdeb3Sjohnz 
793df8bdeb3Sjohnz 	free(cert);
794df8bdeb3Sjohnz }
795