xref: /titanic_52/usr/src/lib/libelfsign/common/elfcertlib.c (revision 8bab47abcb471dffa36ddbf409a8ef5303398ddf)
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 /*
232225707cSValerie Bubb Fenwick  * Copyright 2009 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.
55df8bdeb3Sjohnz  */
56df8bdeb3Sjohnz static const char _PATH_CRYPTO_CACERT[] = CRYPTO_CERTS_DIR "/CA";
57df8bdeb3Sjohnz static const char _PATH_CRYPTO_OBJCACERT[] = CRYPTO_CERTS_DIR "/SUNWObjectCA";
58df8bdeb3Sjohnz static ELFCert_t CACERT = NULL;
59df8bdeb3Sjohnz static ELFCert_t OBJCACERT = NULL;
60df8bdeb3Sjohnz static pthread_mutex_t ca_mutex = PTHREAD_MUTEX_INITIALIZER;
61df8bdeb3Sjohnz 
62df8bdeb3Sjohnz static void elfcertlib_freecert(ELFsign_t, ELFCert_t);
63df8bdeb3Sjohnz static ELFCert_t elfcertlib_allocatecert(void);
64df8bdeb3Sjohnz 
65df8bdeb3Sjohnz /*
66df8bdeb3Sjohnz  * elfcertlib_verifycert - Verify the Cert with a Trust Anchor
67df8bdeb3Sjohnz  *
68df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
69df8bdeb3Sjohnz  *	cert
70df8bdeb3Sjohnz  * OUT	NONE
71df8bdeb3Sjohnz  * RETURN	TRUE/FALSE
72df8bdeb3Sjohnz  *
73df8bdeb3Sjohnz  * We first setup the Trust Anchor (CA and SUNWObjectCA) certs
74df8bdeb3Sjohnz  * if it hasn't been done already.  We verify that the files on disk
75df8bdeb3Sjohnz  * are those we expected.
76df8bdeb3Sjohnz  *
77df8bdeb3Sjohnz  * We then verify the given cert using the publickey of a TA.
78df8bdeb3Sjohnz  * If the passed in cert is a TA or it has been verified already we
79df8bdeb3Sjohnz  * short cut and return TRUE without futher validation.
80df8bdeb3Sjohnz  */
81df8bdeb3Sjohnz /*ARGSUSED*/
82df8bdeb3Sjohnz boolean_t
83df8bdeb3Sjohnz elfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert)
84df8bdeb3Sjohnz {
85*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
86*8bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
87*8bab47abSJohn.Zolnowsky@Sun.COM 
88df8bdeb3Sjohnz 	KMF_RETURN rv;
89df8bdeb3Sjohnz 	if ((cert->c_verified == E_OK) || (cert->c_verified == E_IS_TA)) {
90df8bdeb3Sjohnz 		return (B_TRUE);
91df8bdeb3Sjohnz 	}
92df8bdeb3Sjohnz 
93df8bdeb3Sjohnz 	(void) pthread_mutex_lock(&ca_mutex);
94df8bdeb3Sjohnz 	if (CACERT == NULL) {
95df8bdeb3Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT,
96df8bdeb3Sjohnz 		    NULL, &CACERT, ES_GET);
97df8bdeb3Sjohnz 	}
98df8bdeb3Sjohnz 	if (OBJCACERT == NULL) {
99df8bdeb3Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT,
100df8bdeb3Sjohnz 		    NULL, &OBJCACERT, ES_GET);
101df8bdeb3Sjohnz 	}
102df8bdeb3Sjohnz 	(void) pthread_mutex_unlock(&ca_mutex);
103df8bdeb3Sjohnz 
104df8bdeb3Sjohnz 	if (CACERT != NULL) {
105*8bab47abSJohn.Zolnowsky@Sun.COM 		numattr = 0;
106*8bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
107*8bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
108*8bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
109*8bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
110*8bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_SIGNER_CERT_DATA_ATTR, &CACERT->c_cert.certificate,
111*8bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
112*8bab47abSJohn.Zolnowsky@Sun.COM 
113*8bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
114df8bdeb3Sjohnz 		if (rv == KMF_OK) {
115df8bdeb3Sjohnz 			if (ess->es_certCAcallback != NULL)
116df8bdeb3Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
117df8bdeb3Sjohnz 				    cert, CACERT);
118df8bdeb3Sjohnz 			cert->c_verified = E_OK;
119df8bdeb3Sjohnz 			return (B_TRUE);
120df8bdeb3Sjohnz 		}
121df8bdeb3Sjohnz 	}
122df8bdeb3Sjohnz 
123df8bdeb3Sjohnz 	if (OBJCACERT != NULL) {
124*8bab47abSJohn.Zolnowsky@Sun.COM 		numattr = 0;
125*8bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
126*8bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_CERT_DATA_ATTR, &cert->c_cert.certificate,
127*8bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
128*8bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
129*8bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_SIGNER_CERT_DATA_ATTR, &OBJCACERT->c_cert.certificate,
130*8bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_DATA));
131*8bab47abSJohn.Zolnowsky@Sun.COM 
132*8bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist);
133df8bdeb3Sjohnz 		if (rv == KMF_OK) {
134df8bdeb3Sjohnz 			if (ess->es_certCAcallback != NULL)
135df8bdeb3Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
136df8bdeb3Sjohnz 				    cert, OBJCACERT);
137df8bdeb3Sjohnz 			cert->c_verified = E_OK;
138df8bdeb3Sjohnz 			return (B_TRUE);
139df8bdeb3Sjohnz 		}
140df8bdeb3Sjohnz 	}
141df8bdeb3Sjohnz 
142df8bdeb3Sjohnz 	return (B_FALSE);
143df8bdeb3Sjohnz }
144df8bdeb3Sjohnz 
145df8bdeb3Sjohnz /*
146df8bdeb3Sjohnz  * elfcertlib_getcert - Get the certificate for signer_DN
147df8bdeb3Sjohnz  *
148df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
149df8bdeb3Sjohnz  *	cert_pathname	- path to cert (May be NULL)
150df8bdeb3Sjohnz  *	signer_DN	- The DN we are looking for (May be NULL)
151df8bdeb3Sjohnz  *      action		- indicates crypto verification call
152df8bdeb3Sjohnz  * OUT  certp		- allocated/loaded ELFCert_t
153df8bdeb3Sjohnz  *
154df8bdeb3Sjohnz  * If the cert_pathname is passed use it and don't search.
155df8bdeb3Sjohnz  * Otherwise, go looking in certificate directories
156df8bdeb3Sjohnz  */
157df8bdeb3Sjohnz boolean_t
158df8bdeb3Sjohnz elfcertlib_getcert(ELFsign_t ess, char *cert_pathname,
159df8bdeb3Sjohnz     char *signer_DN, ELFCert_t *certp, enum ES_ACTION action)
160df8bdeb3Sjohnz {
161df8bdeb3Sjohnz 	KMF_RETURN rv;
162df8bdeb3Sjohnz 	ELFCert_t	cert = NULL;
163df8bdeb3Sjohnz 	KMF_X509_DER_CERT certbuf[2];
164df8bdeb3Sjohnz 	uint32_t ncerts;
165df8bdeb3Sjohnz 	boolean_t ret = B_FALSE;
166df8bdeb3Sjohnz 	char	*pathlist[3], **plp;
167df8bdeb3Sjohnz 
168df8bdeb3Sjohnz 	cryptodebug("elfcertlib_getcert: path=%s, DN=%s",
169df8bdeb3Sjohnz 	    cert_pathname ? cert_pathname : "-none-",
170df8bdeb3Sjohnz 	    signer_DN ? signer_DN : "-none-");
171df8bdeb3Sjohnz 	*certp = NULL;
172df8bdeb3Sjohnz 	if (cert_pathname == NULL && signer_DN == NULL) {
173df8bdeb3Sjohnz 		cryptodebug("elfcertlib_getcert: lack of specificity");
174df8bdeb3Sjohnz 		return (ret);
175df8bdeb3Sjohnz 	}
176df8bdeb3Sjohnz 
177df8bdeb3Sjohnz 	plp = pathlist;
178df8bdeb3Sjohnz 	if (cert_pathname != NULL) {
179df8bdeb3Sjohnz 		/* look in the specified object */
180df8bdeb3Sjohnz 		*plp++ = cert_pathname;
181df8bdeb3Sjohnz 	} else {
182df8bdeb3Sjohnz 		/* look in the certificate directories */
183df8bdeb3Sjohnz 		*plp++ = (char *)_PATH_ELFSIGN_CRYPTO_CERTS;
184df8bdeb3Sjohnz 		/*
185df8bdeb3Sjohnz 		 * crypto verifications don't search beyond
186df8bdeb3Sjohnz 		 * _PATH_ELFSIGN_CRYPTO_CERTS
187df8bdeb3Sjohnz 		 */
188df8bdeb3Sjohnz 		if (action != ES_GET_CRYPTO)
189df8bdeb3Sjohnz 			*plp++ = (char *)_PATH_ELFSIGN_ETC_CERTS;
190df8bdeb3Sjohnz 	}
191df8bdeb3Sjohnz 	*plp = NULL;
192df8bdeb3Sjohnz 
193df8bdeb3Sjohnz 	if ((cert = elfcertlib_allocatecert()) == NULL) {
194df8bdeb3Sjohnz 		return (ret);
195df8bdeb3Sjohnz 	}
196df8bdeb3Sjohnz 
197df8bdeb3Sjohnz 	for (plp = pathlist; *plp; plp++) {
198*8bab47abSJohn.Zolnowsky@Sun.COM 		KMF_ATTRIBUTE	attrlist[8];
199*8bab47abSJohn.Zolnowsky@Sun.COM 		KMF_KEYSTORE_TYPE	kstype;
200*8bab47abSJohn.Zolnowsky@Sun.COM 		KMF_CERT_VALIDITY	certvalidity;
201*8bab47abSJohn.Zolnowsky@Sun.COM 		int		numattr;
202*8bab47abSJohn.Zolnowsky@Sun.COM 
203*8bab47abSJohn.Zolnowsky@Sun.COM 		kstype = KMF_KEYSTORE_OPENSSL;
204*8bab47abSJohn.Zolnowsky@Sun.COM 		certvalidity = KMF_ALL_CERTS;
205df8bdeb3Sjohnz 		ncerts = 2;
206df8bdeb3Sjohnz 
207*8bab47abSJohn.Zolnowsky@Sun.COM 		numattr = 0;
208*8bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
209*8bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
210*8bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
211*8bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_X509_DER_CERT_ATTR, certbuf,
212*8bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_X509_DER_CERT));
213*8bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
214*8bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_COUNT_ATTR, &ncerts, sizeof (uint32_t));
215*8bab47abSJohn.Zolnowsky@Sun.COM 		if (signer_DN != NULL) {
216*8bab47abSJohn.Zolnowsky@Sun.COM 			kmf_set_attr_at_index(attrlist, numattr++,
217*8bab47abSJohn.Zolnowsky@Sun.COM 			    KMF_SUBJECT_NAME_ATTR, signer_DN,
218*8bab47abSJohn.Zolnowsky@Sun.COM 			    strlen(signer_DN));
219*8bab47abSJohn.Zolnowsky@Sun.COM 		}
220*8bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
221*8bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_CERT_VALIDITY_ATTR, &certvalidity,
222*8bab47abSJohn.Zolnowsky@Sun.COM 		    sizeof (KMF_CERT_VALIDITY));
223*8bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
224*8bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_CERT_FILENAME_ATTR, *plp, strlen (*plp));
225*8bab47abSJohn.Zolnowsky@Sun.COM 
226*8bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_find_cert(ess->es_kmfhandle, numattr, attrlist);
227*8bab47abSJohn.Zolnowsky@Sun.COM 
228df8bdeb3Sjohnz 		if (rv != KMF_OK)
229df8bdeb3Sjohnz 			continue;
230*8bab47abSJohn.Zolnowsky@Sun.COM 		/* found one */
231*8bab47abSJohn.Zolnowsky@Sun.COM 		cert->c_cert = certbuf[0];
232*8bab47abSJohn.Zolnowsky@Sun.COM 		if (ncerts > 1) {
233*8bab47abSJohn.Zolnowsky@Sun.COM 			/* release any extras */
234*8bab47abSJohn.Zolnowsky@Sun.COM 			kmf_free_kmf_cert(ess->es_kmfhandle, &certbuf[1]);
235*8bab47abSJohn.Zolnowsky@Sun.COM 			if (signer_DN == NULL) {
236df8bdeb3Sjohnz 				/* There can be only one */
237df8bdeb3Sjohnz 				cryptodebug("elfcertlib_getcert: "
238df8bdeb3Sjohnz 				    "too many certificates found in %s",
239df8bdeb3Sjohnz 				    cert_pathname);
240df8bdeb3Sjohnz 				goto cleanup;
241df8bdeb3Sjohnz 			}
242*8bab47abSJohn.Zolnowsky@Sun.COM 		}
243*8bab47abSJohn.Zolnowsky@Sun.COM 		/* cache subject and issuer */
244*8bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_get_cert_subject_str(ess->es_kmfhandle,
245df8bdeb3Sjohnz 		    &cert->c_cert.certificate, &cert->c_subject);
246df8bdeb3Sjohnz 		if (rv != KMF_OK)
247df8bdeb3Sjohnz 			goto cleanup;
248df8bdeb3Sjohnz 
249*8bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_get_cert_issuer_str(ess->es_kmfhandle,
250df8bdeb3Sjohnz 		    &cert->c_cert.certificate, &cert->c_issuer);
251df8bdeb3Sjohnz 		if (rv != KMF_OK)
252df8bdeb3Sjohnz 			goto cleanup;
253df8bdeb3Sjohnz 		break;
254df8bdeb3Sjohnz 	}
255df8bdeb3Sjohnz 	if (*plp == NULL) {
256df8bdeb3Sjohnz 		cryptodebug("elfcertlib_getcert: no certificate found");
257df8bdeb3Sjohnz 		goto cleanup;
258df8bdeb3Sjohnz 	}
259df8bdeb3Sjohnz 
260df8bdeb3Sjohnz 	cert->c_verified = E_UNCHECKED;
261df8bdeb3Sjohnz 
262df8bdeb3Sjohnz 	/*
2632225707cSValerie Bubb Fenwick 	 * If the cert we are loading is the trust anchor (ie the CA) then
264df8bdeb3Sjohnz 	 * we mark it as such in cert.  This is so that we don't attempt
265df8bdeb3Sjohnz 	 * to verify it later.  The CA is always implicitly verified.
266df8bdeb3Sjohnz 	 */
267df8bdeb3Sjohnz 	if (cert_pathname != NULL && (
268df8bdeb3Sjohnz 	    strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 ||
269df8bdeb3Sjohnz 	    strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0)) {
270df8bdeb3Sjohnz 		if (ess->es_certCAcallback != NULL)
271df8bdeb3Sjohnz 			(ess->es_certCAcallback)(ess->es_callbackctx, cert,
272df8bdeb3Sjohnz 			    cert_pathname);
273df8bdeb3Sjohnz 		cert->c_verified = E_IS_TA;
274df8bdeb3Sjohnz 	}
275df8bdeb3Sjohnz 
276df8bdeb3Sjohnz 	ret = B_TRUE;
277df8bdeb3Sjohnz 
278df8bdeb3Sjohnz cleanup:
279df8bdeb3Sjohnz 	if (ret) {
280df8bdeb3Sjohnz 		*certp = cert;
281df8bdeb3Sjohnz 	} else {
282df8bdeb3Sjohnz 		if (cert != NULL)
283df8bdeb3Sjohnz 			elfcertlib_freecert(ess, cert);
284df8bdeb3Sjohnz 		if (signer_DN != NULL)
285df8bdeb3Sjohnz 			cryptoerror(LOG_ERR, "unable to find a certificate "
286df8bdeb3Sjohnz 			    "for DN: %s", signer_DN);
287df8bdeb3Sjohnz 		else
288df8bdeb3Sjohnz 			cryptoerror(LOG_ERR, "unable to load certificate "
289df8bdeb3Sjohnz 			    "from %s", cert_pathname);
290df8bdeb3Sjohnz 	}
291df8bdeb3Sjohnz 	return (ret);
292df8bdeb3Sjohnz }
293df8bdeb3Sjohnz 
294df8bdeb3Sjohnz /*
295df8bdeb3Sjohnz  * elfcertlib_loadprivatekey - Load the private key from path
296df8bdeb3Sjohnz  *
297df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
298df8bdeb3Sjohnz  *	cert
299df8bdeb3Sjohnz  *	pathname
300df8bdeb3Sjohnz  * OUT	cert
301df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
302df8bdeb3Sjohnz  */
303df8bdeb3Sjohnz boolean_t
304df8bdeb3Sjohnz elfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname)
305df8bdeb3Sjohnz {
306df8bdeb3Sjohnz 	KMF_RETURN	rv = KMF_OK;
307df8bdeb3Sjohnz 	KMF_KEY_HANDLE	keybuf[2];
308*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[16];
309*8bab47abSJohn.Zolnowsky@Sun.COM 	uint32_t	nkeys;
310*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
311*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEY_ALG	keytype;
312*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEY_CLASS	keyclass;
313*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ENCODE_FORMAT	format;
314*8bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
315df8bdeb3Sjohnz 
316*8bab47abSJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_OPENSSL;
317*8bab47abSJohn.Zolnowsky@Sun.COM 	nkeys = 2;
318*8bab47abSJohn.Zolnowsky@Sun.COM 	keytype = KMF_KEYALG_NONE;
319*8bab47abSJohn.Zolnowsky@Sun.COM 	keyclass = KMF_ASYM_PRI;
320*8bab47abSJohn.Zolnowsky@Sun.COM 	format = KMF_FORMAT_UNDEF;
321df8bdeb3Sjohnz 
322*8bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
323*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
324*8bab47abSJohn.Zolnowsky@Sun.COM 	    &kstype, sizeof (kstype));
325*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
326*8bab47abSJohn.Zolnowsky@Sun.COM 	    keybuf, sizeof (KMF_KEY_HANDLE));
327*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
328*8bab47abSJohn.Zolnowsky@Sun.COM 	    &nkeys, sizeof (uint32_t));
329*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
330*8bab47abSJohn.Zolnowsky@Sun.COM 	    &keytype, sizeof (keytype));
331*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
332*8bab47abSJohn.Zolnowsky@Sun.COM 	    &keyclass, sizeof (keyclass));
333*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
334*8bab47abSJohn.Zolnowsky@Sun.COM 	    &format, sizeof (format));
335*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_FILENAME_ATTR,
336*8bab47abSJohn.Zolnowsky@Sun.COM 	    (char *)pathname, strlen(pathname));
337*8bab47abSJohn.Zolnowsky@Sun.COM 
338*8bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
339df8bdeb3Sjohnz 	if (rv != KMF_OK)
340df8bdeb3Sjohnz 		return (B_FALSE);
341df8bdeb3Sjohnz 	if (nkeys != 1) {
342df8bdeb3Sjohnz 		/* lack of specificity */
343df8bdeb3Sjohnz 		cryptodebug("found %d keys at %s", nkeys, pathname);
344df8bdeb3Sjohnz 		return (B_FALSE);
345df8bdeb3Sjohnz 	}
346df8bdeb3Sjohnz 	cert->c_privatekey = keybuf[0];
347df8bdeb3Sjohnz 	cryptodebug("key %s loaded", pathname);
348df8bdeb3Sjohnz 	return (B_TRUE);
349df8bdeb3Sjohnz }
350df8bdeb3Sjohnz 
351df8bdeb3Sjohnz /*
352df8bdeb3Sjohnz  * elfcertlib_loadtokenkey - Load the private key from token
353df8bdeb3Sjohnz  *
354df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
355df8bdeb3Sjohnz  *	cert
356df8bdeb3Sjohnz  *	token_label
357df8bdeb3Sjohnz  *	pin
358df8bdeb3Sjohnz  * OUT	cert
359df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
360df8bdeb3Sjohnz  */
361df8bdeb3Sjohnz boolean_t
362df8bdeb3Sjohnz elfcertlib_loadtokenkey(ELFsign_t ess, ELFCert_t cert,
363df8bdeb3Sjohnz     const char *token_label, const char *pin)
364df8bdeb3Sjohnz {
365*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_RETURN	rv;
366df8bdeb3Sjohnz 	char		*idstr = NULL;
367*8bab47abSJohn.Zolnowsky@Sun.COM 	char		*kmferr;
368*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[16];
369*8bab47abSJohn.Zolnowsky@Sun.COM 	uint32_t	nkeys;
370*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
371*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEY_ALG	keytype;
372*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEY_CLASS	keyclass;
373*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ENCODE_FORMAT	format;
374*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_CREDENTIAL	pincred;
375*8bab47abSJohn.Zolnowsky@Sun.COM 	boolean_t	tokenbool, privatebool;
376*8bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
377df8bdeb3Sjohnz 
378df8bdeb3Sjohnz 	/*
379df8bdeb3Sjohnz 	 * We will search for the key based on the ID attribute
380df8bdeb3Sjohnz 	 * which was added when the key was created.  ID is
381df8bdeb3Sjohnz 	 * a SHA-1 hash of the public modulus shared by the
382df8bdeb3Sjohnz 	 * key and the certificate.
383df8bdeb3Sjohnz 	 */
384*8bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_get_cert_id_str(&cert->c_cert.certificate, &idstr);
385df8bdeb3Sjohnz 	if (rv != KMF_OK) {
386*8bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(rv, &kmferr);
387*8bab47abSJohn.Zolnowsky@Sun.COM 		cryptodebug("Error getting ID from cert: %s\n",
388*8bab47abSJohn.Zolnowsky@Sun.COM 		    (kmferr ? kmferr : "Unrecognized KMF error"));
389*8bab47abSJohn.Zolnowsky@Sun.COM 		free(kmferr);
390df8bdeb3Sjohnz 		return (B_FALSE);
391df8bdeb3Sjohnz 	}
392df8bdeb3Sjohnz 
393*8bab47abSJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_PK11TOKEN;
394*8bab47abSJohn.Zolnowsky@Sun.COM 	nkeys = 1;
395*8bab47abSJohn.Zolnowsky@Sun.COM 	keytype = KMF_KEYALG_NONE;
396*8bab47abSJohn.Zolnowsky@Sun.COM 	keyclass = KMF_ASYM_PRI;
397*8bab47abSJohn.Zolnowsky@Sun.COM 	format = KMF_FORMAT_UNDEF;
398*8bab47abSJohn.Zolnowsky@Sun.COM 	pincred.cred = (char *)pin;
399*8bab47abSJohn.Zolnowsky@Sun.COM 	pincred.credlen = strlen(pin);
400*8bab47abSJohn.Zolnowsky@Sun.COM 	tokenbool = B_FALSE;
401*8bab47abSJohn.Zolnowsky@Sun.COM 	privatebool = B_TRUE;
402*8bab47abSJohn.Zolnowsky@Sun.COM 
403*8bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
404*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
405*8bab47abSJohn.Zolnowsky@Sun.COM 	    &kstype, sizeof (kstype));
406*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
407*8bab47abSJohn.Zolnowsky@Sun.COM 	    &cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
408*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR,
409*8bab47abSJohn.Zolnowsky@Sun.COM 	    &nkeys, sizeof (uint32_t));
410*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR,
411*8bab47abSJohn.Zolnowsky@Sun.COM 	    &keytype, sizeof (keytype));
412*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR,
413*8bab47abSJohn.Zolnowsky@Sun.COM 	    &keyclass, sizeof (keyclass));
414*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR,
415*8bab47abSJohn.Zolnowsky@Sun.COM 	    &format, sizeof (format));
416*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_IDSTR_ATTR,
417*8bab47abSJohn.Zolnowsky@Sun.COM 	    idstr, strlen(idstr));
418*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_CREDENTIAL_ATTR,
419*8bab47abSJohn.Zolnowsky@Sun.COM 	    &pincred, sizeof (KMF_CREDENTIAL));
420*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_TOKEN_BOOL_ATTR,
421*8bab47abSJohn.Zolnowsky@Sun.COM 	    &tokenbool, sizeof (tokenbool));
422*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_PRIVATE_BOOL_ATTR,
423*8bab47abSJohn.Zolnowsky@Sun.COM 	    &privatebool, sizeof (privatebool));
424*8bab47abSJohn.Zolnowsky@Sun.COM 
425*8bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist);
426df8bdeb3Sjohnz 	free(idstr);
427*8bab47abSJohn.Zolnowsky@Sun.COM 	if (rv != KMF_OK) {
428*8bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(rv, &kmferr);
429*8bab47abSJohn.Zolnowsky@Sun.COM 		cryptodebug("Error finding private key: %s\n",
430*8bab47abSJohn.Zolnowsky@Sun.COM 		    (kmferr ? kmferr : "Unrecognized KMF error"));
431*8bab47abSJohn.Zolnowsky@Sun.COM 		free(kmferr);
432*8bab47abSJohn.Zolnowsky@Sun.COM 		return (B_FALSE);
433*8bab47abSJohn.Zolnowsky@Sun.COM 	}
434*8bab47abSJohn.Zolnowsky@Sun.COM 	if (nkeys != 1) {
435*8bab47abSJohn.Zolnowsky@Sun.COM 		cryptodebug("Error finding private key: No key found\n");
436df8bdeb3Sjohnz 		return (B_FALSE);
437df8bdeb3Sjohnz 	}
438df8bdeb3Sjohnz 	cryptodebug("key found in %s", token_label);
439df8bdeb3Sjohnz 	cryptodebug("elfcertlib_loadprivatekey = 0x%.8X",
440df8bdeb3Sjohnz 	    &cert->c_privatekey);
441df8bdeb3Sjohnz 
442df8bdeb3Sjohnz 	return (B_TRUE);
443df8bdeb3Sjohnz }
444df8bdeb3Sjohnz 
445df8bdeb3Sjohnz static const CK_BYTE MD5_DER_PREFIX[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
446df8bdeb3Sjohnz 	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
447df8bdeb3Sjohnz 
448df8bdeb3Sjohnz /*
449df8bdeb3Sjohnz  * elfcertlib_sign - sign the given DATA using the privatekey in cert
450df8bdeb3Sjohnz  *
451df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
452df8bdeb3Sjohnz  *	cert
453df8bdeb3Sjohnz  *	data
454df8bdeb3Sjohnz  *	data_len
455df8bdeb3Sjohnz  * OUT	sig	- must be big enough to hold the signature of data
456df8bdeb3Sjohnz  *		  Caller must allocate
457df8bdeb3Sjohnz  *	sig_len	- actual length used; 0 on failure.
458df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
459df8bdeb3Sjohnz  */
460df8bdeb3Sjohnz /*ARGSUSED*/
461df8bdeb3Sjohnz boolean_t
462df8bdeb3Sjohnz elfcertlib_sign(ELFsign_t ess, ELFCert_t cert,
463df8bdeb3Sjohnz 	const uchar_t *data, size_t data_len,
464df8bdeb3Sjohnz 	uchar_t *sig, size_t *sig_len)
465df8bdeb3Sjohnz {
466*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_RETURN	ret;
467df8bdeb3Sjohnz 	KMF_DATA	tobesigned;
468df8bdeb3Sjohnz 	KMF_DATA	signature;
469df8bdeb3Sjohnz 	uchar_t		der_data[sizeof (MD5_DER_PREFIX) + MD5_DIGEST_LENGTH];
470*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
471*8bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
472df8bdeb3Sjohnz 
473df8bdeb3Sjohnz 	if (ess->es_version <= FILESIG_VERSION2) {
474df8bdeb3Sjohnz 		/* compatibility: take MD5 hash of SHA1 hash */
475df8bdeb3Sjohnz 		size_t	derlen = MD5_DIGEST_LENGTH;
476df8bdeb3Sjohnz 		MD5_CTX ctx;
477df8bdeb3Sjohnz 
478df8bdeb3Sjohnz 		/*
479df8bdeb3Sjohnz 		 * first: digest using software-based methods, don't
480df8bdeb3Sjohnz 		 * rely on the token for hashing.
481df8bdeb3Sjohnz 		 */
482df8bdeb3Sjohnz 		MD5Init(&ctx);
483df8bdeb3Sjohnz 		MD5Update(&ctx, data, data_len);
484df8bdeb3Sjohnz 		MD5Final(&der_data[sizeof (MD5_DER_PREFIX)], &ctx);
485df8bdeb3Sjohnz 
486df8bdeb3Sjohnz 		/*
487df8bdeb3Sjohnz 		 * second: insert prefix
488df8bdeb3Sjohnz 		 */
489df8bdeb3Sjohnz 		(void) memcpy(der_data, MD5_DER_PREFIX,
490df8bdeb3Sjohnz 		    sizeof (MD5_DER_PREFIX));
491df8bdeb3Sjohnz 		/*
492df8bdeb3Sjohnz 		 * prepare to sign the local buffer
493df8bdeb3Sjohnz 		 */
494df8bdeb3Sjohnz 		tobesigned.Data = (uchar_t *)der_data;
495df8bdeb3Sjohnz 		tobesigned.Length = sizeof (MD5_DER_PREFIX) + derlen;
496df8bdeb3Sjohnz 	} else {
497df8bdeb3Sjohnz 		tobesigned.Data = (uchar_t *)data;
498df8bdeb3Sjohnz 		tobesigned.Length = data_len;
499df8bdeb3Sjohnz 	}
500df8bdeb3Sjohnz 
501df8bdeb3Sjohnz 	signature.Data = (uchar_t *)sig;
502df8bdeb3Sjohnz 	signature.Length = *sig_len;
503df8bdeb3Sjohnz 
504*8bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
505*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
506*8bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_KEYSTORE_TYPE_ATTR, &(cert->c_privatekey.kstype),
507*8bab47abSJohn.Zolnowsky@Sun.COM 	    sizeof (KMF_KEYSTORE_TYPE));
508*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
509*8bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_KEY_HANDLE_ATTR, &cert->c_privatekey, sizeof (KMF_KEY_HANDLE));
510*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
511*8bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_OID_ATTR, (KMF_OID *)&KMFOID_RSA, sizeof (KMF_OID));
512*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
513*8bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_DATA_ATTR, &tobesigned, sizeof (KMF_DATA));
514*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
515*8bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_OUT_DATA_ATTR, &signature, sizeof (KMF_DATA));
516*8bab47abSJohn.Zolnowsky@Sun.COM 
517*8bab47abSJohn.Zolnowsky@Sun.COM 	ret = kmf_sign_data(ess->es_kmfhandle, numattr, attrlist);
518df8bdeb3Sjohnz 
519df8bdeb3Sjohnz 	if (ret != KMF_OK) {
520*8bab47abSJohn.Zolnowsky@Sun.COM 		char	*kmferr;
521*8bab47abSJohn.Zolnowsky@Sun.COM 
522*8bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(ret, &kmferr);
523*8bab47abSJohn.Zolnowsky@Sun.COM 		cryptodebug("Error signing data: %s\n",
524*8bab47abSJohn.Zolnowsky@Sun.COM 		    (kmferr ? kmferr : "Unrecognized KMF error"));
525*8bab47abSJohn.Zolnowsky@Sun.COM 		free(kmferr);
526df8bdeb3Sjohnz 		*sig_len = 0;
527df8bdeb3Sjohnz 		return (B_FALSE);
528df8bdeb3Sjohnz 	}
529df8bdeb3Sjohnz 	*sig_len = signature.Length;
530df8bdeb3Sjohnz 	return (B_TRUE);
531df8bdeb3Sjohnz }
532df8bdeb3Sjohnz 
533df8bdeb3Sjohnz /*
534df8bdeb3Sjohnz  * elfcertlib_verifysig - verify the given DATA using the public key in cert
535df8bdeb3Sjohnz  *
536df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
537df8bdeb3Sjohnz  *	cert
538df8bdeb3Sjohnz  *	signature
539df8bdeb3Sjohnz  *	sig_len
540df8bdeb3Sjohnz  *	data
541df8bdeb3Sjohnz  *	data_len
542df8bdeb3Sjohnz  * OUT	N/A
543df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
544df8bdeb3Sjohnz  */
545df8bdeb3Sjohnz boolean_t
546df8bdeb3Sjohnz elfcertlib_verifysig(ELFsign_t ess, ELFCert_t cert,
547df8bdeb3Sjohnz 	const uchar_t *signature, size_t sig_len,
548df8bdeb3Sjohnz 	const uchar_t *data, size_t data_len)
549df8bdeb3Sjohnz {
550df8bdeb3Sjohnz 	KMF_RETURN	rv;
551df8bdeb3Sjohnz 	KMF_DATA	indata;
552df8bdeb3Sjohnz 	KMF_DATA	insig;
553df8bdeb3Sjohnz 	KMF_ALGORITHM_INDEX algid;
554*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
555*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
556*8bab47abSJohn.Zolnowsky@Sun.COM 	int		numattr;
557df8bdeb3Sjohnz 
558df8bdeb3Sjohnz 	indata.Data = (uchar_t *)data;
559df8bdeb3Sjohnz 	indata.Length = data_len;
560df8bdeb3Sjohnz 	insig.Data = (uchar_t *)signature;
561df8bdeb3Sjohnz 	insig.Length = sig_len;
562df8bdeb3Sjohnz 
563df8bdeb3Sjohnz 	if (ess->es_version <= FILESIG_VERSION2)
564df8bdeb3Sjohnz 		algid = KMF_ALGID_MD5WithRSA;
565df8bdeb3Sjohnz 	else
566df8bdeb3Sjohnz 		algid = KMF_ALGID_RSA;
567df8bdeb3Sjohnz 
568df8bdeb3Sjohnz 	/*
5692225707cSValerie Bubb Fenwick 	 * We tell KMF to use the PKCS11 verification APIs
5702225707cSValerie Bubb Fenwick 	 * here to prevent the use of OpenSSL and to keep
5712225707cSValerie Bubb Fenwick 	 * all validation within the FIPS-140 boundary for
5722225707cSValerie Bubb Fenwick 	 * the Cryptographic Framework.
573df8bdeb3Sjohnz 	 */
574*8bab47abSJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_PK11TOKEN;
575*8bab47abSJohn.Zolnowsky@Sun.COM 
576*8bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
577*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
578*8bab47abSJohn.Zolnowsky@Sun.COM 	    &kstype,  sizeof (kstype));
579*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_DATA_ATTR,
580*8bab47abSJohn.Zolnowsky@Sun.COM 	    &indata, sizeof (KMF_DATA));
581*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_IN_SIGN_ATTR,
582*8bab47abSJohn.Zolnowsky@Sun.COM 	    &insig, sizeof (KMF_DATA));
583*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_SIGNER_CERT_DATA_ATTR,
584*8bab47abSJohn.Zolnowsky@Sun.COM 	    (KMF_DATA *)(&cert->c_cert.certificate), sizeof (KMF_DATA));
585*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++, KMF_ALGORITHM_INDEX_ATTR,
586*8bab47abSJohn.Zolnowsky@Sun.COM 	    &algid, sizeof (algid));
587*8bab47abSJohn.Zolnowsky@Sun.COM 
588*8bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_verify_data(ess->es_kmfhandle, numattr, attrlist);
589df8bdeb3Sjohnz 
590df8bdeb3Sjohnz 	return ((rv == KMF_OK));
591df8bdeb3Sjohnz }
592df8bdeb3Sjohnz 
593df8bdeb3Sjohnz /*
594df8bdeb3Sjohnz  * elfcertlib_getdn
595df8bdeb3Sjohnz  *
596df8bdeb3Sjohnz  * IN	cert
597df8bdeb3Sjohnz  * OUT	NONE
598df8bdeb3Sjohnz  * RETURN 	dn or NULL
599df8bdeb3Sjohnz  */
600df8bdeb3Sjohnz char *
601df8bdeb3Sjohnz elfcertlib_getdn(ELFCert_t cert)
602df8bdeb3Sjohnz {
603df8bdeb3Sjohnz 	cryptodebug("elfcertlib_getdn");
604df8bdeb3Sjohnz 
605df8bdeb3Sjohnz 	return (cert->c_subject);
606df8bdeb3Sjohnz }
607df8bdeb3Sjohnz 
608df8bdeb3Sjohnz /*
609df8bdeb3Sjohnz  * elfcertlib_getissuer
610df8bdeb3Sjohnz  *
611df8bdeb3Sjohnz  * IN	cert
612df8bdeb3Sjohnz  * OUT	NONE
613df8bdeb3Sjohnz  * RETURN 	dn or NULL
614df8bdeb3Sjohnz  */
615df8bdeb3Sjohnz char *
616df8bdeb3Sjohnz elfcertlib_getissuer(ELFCert_t cert)
617df8bdeb3Sjohnz {
618df8bdeb3Sjohnz 	cryptodebug("elfcertlib_issuer");
619df8bdeb3Sjohnz 
620df8bdeb3Sjohnz 	return (cert->c_issuer);
621df8bdeb3Sjohnz }
622df8bdeb3Sjohnz 
623df8bdeb3Sjohnz boolean_t
624df8bdeb3Sjohnz elfcertlib_init(ELFsign_t ess)
625df8bdeb3Sjohnz {
626df8bdeb3Sjohnz 	boolean_t rc = B_TRUE;
627df8bdeb3Sjohnz 	KMF_RETURN rv;
628df8bdeb3Sjohnz 	if (ess->es_kmfhandle == NULL) {
629*8bab47abSJohn.Zolnowsky@Sun.COM 		rv = kmf_initialize(&ess->es_kmfhandle, NULL, NULL);
630df8bdeb3Sjohnz 		if (rv != KMF_OK) {
631df8bdeb3Sjohnz 			cryptoerror(LOG_ERR,
632df8bdeb3Sjohnz 			    "unable to initialize KMF library");
633df8bdeb3Sjohnz 			rc = B_FALSE;
634df8bdeb3Sjohnz 		}
635df8bdeb3Sjohnz 	}
636df8bdeb3Sjohnz 	return (rc);
637df8bdeb3Sjohnz }
638df8bdeb3Sjohnz 
639df8bdeb3Sjohnz void
640df8bdeb3Sjohnz elfcertlib_fini(ELFsign_t ess)
641df8bdeb3Sjohnz {
642*8bab47abSJohn.Zolnowsky@Sun.COM 	(void) kmf_finalize(ess->es_kmfhandle);
643df8bdeb3Sjohnz }
644df8bdeb3Sjohnz 
645df8bdeb3Sjohnz /*
646df8bdeb3Sjohnz  * set the token device
647df8bdeb3Sjohnz  */
648df8bdeb3Sjohnz boolean_t
649df8bdeb3Sjohnz elfcertlib_settoken(ELFsign_t ess, char *token)
650df8bdeb3Sjohnz {
651df8bdeb3Sjohnz 	boolean_t	rc = B_TRUE;
652df8bdeb3Sjohnz 	KMF_RETURN	rv;
653*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[8];
654*8bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
655*8bab47abSJohn.Zolnowsky@Sun.COM 	boolean_t	readonly;
656*8bab47abSJohn.Zolnowsky@Sun.COM 	int	numattr;
657df8bdeb3Sjohnz 
658*8bab47abSJohn.Zolnowsky@Sun.COM 	kstype = KMF_KEYSTORE_PK11TOKEN;
659*8bab47abSJohn.Zolnowsky@Sun.COM 	readonly = B_TRUE;
660*8bab47abSJohn.Zolnowsky@Sun.COM 
661*8bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
662*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
663*8bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
664*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
665*8bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_TOKEN_LABEL_ATTR, token, strlen(token));
666*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
667*8bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_READONLY_ATTR, &readonly, sizeof (readonly));
668*8bab47abSJohn.Zolnowsky@Sun.COM 
669*8bab47abSJohn.Zolnowsky@Sun.COM 	rv = kmf_configure_keystore(ess->es_kmfhandle, numattr, attrlist);
670df8bdeb3Sjohnz 	if (rv != KMF_OK) {
671df8bdeb3Sjohnz 		cryptoerror(LOG_ERR, "unable to select token\n");
672df8bdeb3Sjohnz 		rc = B_FALSE;
673df8bdeb3Sjohnz 	}
674df8bdeb3Sjohnz 
675df8bdeb3Sjohnz 	return (rc);
676df8bdeb3Sjohnz }
677df8bdeb3Sjohnz 
678df8bdeb3Sjohnz /*
679df8bdeb3Sjohnz  * set the certificate CA identification callback
680df8bdeb3Sjohnz  */
681df8bdeb3Sjohnz void
682df8bdeb3Sjohnz elfcertlib_setcertCAcallback(ELFsign_t ess,
683df8bdeb3Sjohnz     void (*cb)(void *, ELFCert_t, char *))
684df8bdeb3Sjohnz {
685df8bdeb3Sjohnz 	ess->es_certCAcallback = cb;
686df8bdeb3Sjohnz }
687df8bdeb3Sjohnz 
688df8bdeb3Sjohnz /*
689df8bdeb3Sjohnz  * set the certificate verification callback
690df8bdeb3Sjohnz  */
691df8bdeb3Sjohnz void
692df8bdeb3Sjohnz elfcertlib_setcertvercallback(ELFsign_t ess,
693df8bdeb3Sjohnz     void (*cb)(void *, ELFCert_t, ELFCert_t))
694df8bdeb3Sjohnz {
695df8bdeb3Sjohnz 	ess->es_certvercallback = cb;
696df8bdeb3Sjohnz }
697df8bdeb3Sjohnz 
698df8bdeb3Sjohnz 
699df8bdeb3Sjohnz /*
700df8bdeb3Sjohnz  * elfcertlib_releasecert - release a cert
701df8bdeb3Sjohnz  *
702df8bdeb3Sjohnz  * IN cert
703df8bdeb3Sjohnz  * OUT cert
704df8bdeb3Sjohnz  * RETURN	N/A
705df8bdeb3Sjohnz  *
706df8bdeb3Sjohnz  */
707df8bdeb3Sjohnz void
708df8bdeb3Sjohnz elfcertlib_releasecert(ELFsign_t ess, ELFCert_t cert)
709df8bdeb3Sjohnz {
710df8bdeb3Sjohnz 	elfcertlib_freecert(ess, cert);
711df8bdeb3Sjohnz }
712df8bdeb3Sjohnz 
713df8bdeb3Sjohnz /*
714df8bdeb3Sjohnz  * elfcertlib_allocatecert - create a new ELFCert_t
715df8bdeb3Sjohnz  *
716df8bdeb3Sjohnz  * IN N/A
717df8bdeb3Sjohnz  * OUT	N/A
718df8bdeb3Sjohnz  * RETURN 	ELFCert_t, NULL on failure.
719df8bdeb3Sjohnz  */
720df8bdeb3Sjohnz static ELFCert_t
721df8bdeb3Sjohnz elfcertlib_allocatecert(void)
722df8bdeb3Sjohnz {
723df8bdeb3Sjohnz 	ELFCert_t cert = NULL;
724df8bdeb3Sjohnz 
725df8bdeb3Sjohnz 	cert = malloc(sizeof (struct ELFCert_s));
726df8bdeb3Sjohnz 	if (cert == NULL) {
727df8bdeb3Sjohnz 		cryptoerror(LOG_ERR,
728df8bdeb3Sjohnz 		    "elfcertlib_allocatecert: malloc failed %s",
729df8bdeb3Sjohnz 		    strerror(errno));
730df8bdeb3Sjohnz 		return (NULL);
731df8bdeb3Sjohnz 	}
732df8bdeb3Sjohnz 	(void) memset(cert, 0, sizeof (struct ELFCert_s));
733df8bdeb3Sjohnz 	cert->c_verified = E_UNCHECKED;
734df8bdeb3Sjohnz 	cert->c_subject = NULL;
735df8bdeb3Sjohnz 	cert->c_issuer = NULL;
736df8bdeb3Sjohnz 	return (cert);
737df8bdeb3Sjohnz }
738df8bdeb3Sjohnz 
739df8bdeb3Sjohnz /*
740df8bdeb3Sjohnz  * elfcertlib_freecert - freeup the memory of a cert
741df8bdeb3Sjohnz  *
742df8bdeb3Sjohnz  * IN cert
743df8bdeb3Sjohnz  * OUT cert
744df8bdeb3Sjohnz  * RETURN	N/A
745df8bdeb3Sjohnz  *
746df8bdeb3Sjohnz  */
747df8bdeb3Sjohnz static void
748df8bdeb3Sjohnz elfcertlib_freecert(ELFsign_t ess, ELFCert_t cert)
749df8bdeb3Sjohnz {
750df8bdeb3Sjohnz 	if (cert == NULL)
751df8bdeb3Sjohnz 		return;
752df8bdeb3Sjohnz 
753df8bdeb3Sjohnz 	free(cert->c_subject);
754df8bdeb3Sjohnz 	free(cert->c_issuer);
755df8bdeb3Sjohnz 
756*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_free_kmf_cert(ess->es_kmfhandle, &cert->c_cert);
757*8bab47abSJohn.Zolnowsky@Sun.COM 	kmf_free_kmf_key(ess->es_kmfhandle, &cert->c_privatekey);
758df8bdeb3Sjohnz 
759df8bdeb3Sjohnz 	free(cert);
760df8bdeb3Sjohnz }
761