xref: /titanic_44/usr/src/lib/libelfsign/common/elfcertlib.c (revision 2225707c7e7edf7c636ed349df2592ef85329cdd)
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*2225707cSValerie 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 {
85df8bdeb3Sjohnz 	KMF_RETURN rv;
86df8bdeb3Sjohnz 	if ((cert->c_verified == E_OK) || (cert->c_verified == E_IS_TA)) {
87df8bdeb3Sjohnz 		return (B_TRUE);
88df8bdeb3Sjohnz 	}
89df8bdeb3Sjohnz 
90df8bdeb3Sjohnz 	(void) pthread_mutex_lock(&ca_mutex);
91df8bdeb3Sjohnz 	if (CACERT == NULL) {
92df8bdeb3Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT,
93df8bdeb3Sjohnz 		    NULL, &CACERT, ES_GET);
94df8bdeb3Sjohnz 	}
95df8bdeb3Sjohnz 	if (OBJCACERT == NULL) {
96df8bdeb3Sjohnz 		(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT,
97df8bdeb3Sjohnz 		    NULL, &OBJCACERT, ES_GET);
98df8bdeb3Sjohnz 	}
99df8bdeb3Sjohnz 	(void) pthread_mutex_unlock(&ca_mutex);
100df8bdeb3Sjohnz 
101df8bdeb3Sjohnz 	if (CACERT != NULL) {
102df8bdeb3Sjohnz 		rv = KMF_VerifyCertWithCert(ess->es_kmfhandle,
103df8bdeb3Sjohnz 		    (const KMF_DATA *)&cert->c_cert,
104df8bdeb3Sjohnz 		    (const KMF_DATA *)&CACERT->c_cert.certificate);
105df8bdeb3Sjohnz 		if (rv == KMF_OK) {
106df8bdeb3Sjohnz 			if (ess->es_certCAcallback != NULL)
107df8bdeb3Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
108df8bdeb3Sjohnz 				    cert, CACERT);
109df8bdeb3Sjohnz 			cert->c_verified = E_OK;
110df8bdeb3Sjohnz 			return (B_TRUE);
111df8bdeb3Sjohnz 		}
112df8bdeb3Sjohnz 	}
113df8bdeb3Sjohnz 
114df8bdeb3Sjohnz 	if (OBJCACERT != NULL) {
115df8bdeb3Sjohnz 		rv = KMF_VerifyCertWithCert(ess->es_kmfhandle,
116df8bdeb3Sjohnz 		    (const KMF_DATA *)&cert->c_cert,
117df8bdeb3Sjohnz 		    (const KMF_DATA *)&OBJCACERT->c_cert.certificate);
118df8bdeb3Sjohnz 		if (rv == KMF_OK) {
119df8bdeb3Sjohnz 			if (ess->es_certCAcallback != NULL)
120df8bdeb3Sjohnz 				(ess->es_certvercallback)(ess->es_callbackctx,
121df8bdeb3Sjohnz 				    cert, OBJCACERT);
122df8bdeb3Sjohnz 			cert->c_verified = E_OK;
123df8bdeb3Sjohnz 			return (B_TRUE);
124df8bdeb3Sjohnz 		}
125df8bdeb3Sjohnz 	}
126df8bdeb3Sjohnz 
127df8bdeb3Sjohnz 	return (B_FALSE);
128df8bdeb3Sjohnz }
129df8bdeb3Sjohnz 
130df8bdeb3Sjohnz /*
131df8bdeb3Sjohnz  * elfcertlib_getcert - Get the certificate for signer_DN
132df8bdeb3Sjohnz  *
133df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
134df8bdeb3Sjohnz  *	cert_pathname	- path to cert (May be NULL)
135df8bdeb3Sjohnz  *	signer_DN	- The DN we are looking for (May be NULL)
136df8bdeb3Sjohnz  *      action		- indicates crypto verification call
137df8bdeb3Sjohnz  * OUT  certp		- allocated/loaded ELFCert_t
138df8bdeb3Sjohnz  *
139df8bdeb3Sjohnz  * If the cert_pathname is passed use it and don't search.
140df8bdeb3Sjohnz  * Otherwise, go looking in certificate directories
141df8bdeb3Sjohnz  */
142df8bdeb3Sjohnz boolean_t
143df8bdeb3Sjohnz elfcertlib_getcert(ELFsign_t ess, char *cert_pathname,
144df8bdeb3Sjohnz     char *signer_DN, ELFCert_t *certp, enum ES_ACTION action)
145df8bdeb3Sjohnz {
146df8bdeb3Sjohnz 	KMF_RETURN rv;
147df8bdeb3Sjohnz 	ELFCert_t	cert = NULL;
148df8bdeb3Sjohnz 	KMF_FINDCERT_PARAMS fcparams;
149df8bdeb3Sjohnz 	KMF_X509_DER_CERT certbuf[2];
150df8bdeb3Sjohnz 	uint32_t ncerts;
151df8bdeb3Sjohnz 	boolean_t ret = B_FALSE;
152df8bdeb3Sjohnz 	char	*pathlist[3], **plp;
153df8bdeb3Sjohnz 
154df8bdeb3Sjohnz 	cryptodebug("elfcertlib_getcert: path=%s, DN=%s",
155df8bdeb3Sjohnz 	    cert_pathname ? cert_pathname : "-none-",
156df8bdeb3Sjohnz 	    signer_DN ? signer_DN : "-none-");
157df8bdeb3Sjohnz 	*certp = NULL;
158df8bdeb3Sjohnz 	if (cert_pathname == NULL && signer_DN == NULL) {
159df8bdeb3Sjohnz 		cryptodebug("elfcertlib_getcert: lack of specificity");
160df8bdeb3Sjohnz 		return (ret);
161df8bdeb3Sjohnz 	}
162df8bdeb3Sjohnz 
163df8bdeb3Sjohnz 	plp = pathlist;
164df8bdeb3Sjohnz 	if (cert_pathname != NULL) {
165df8bdeb3Sjohnz 		/* look in the specified object */
166df8bdeb3Sjohnz 		*plp++ = cert_pathname;
167df8bdeb3Sjohnz 	} else {
168df8bdeb3Sjohnz 		/* look in the certificate directories */
169df8bdeb3Sjohnz 		*plp++ = (char *)_PATH_ELFSIGN_CRYPTO_CERTS;
170df8bdeb3Sjohnz 		/*
171df8bdeb3Sjohnz 		 * crypto verifications don't search beyond
172df8bdeb3Sjohnz 		 * _PATH_ELFSIGN_CRYPTO_CERTS
173df8bdeb3Sjohnz 		 */
174df8bdeb3Sjohnz 		if (action != ES_GET_CRYPTO)
175df8bdeb3Sjohnz 			*plp++ = (char *)_PATH_ELFSIGN_ETC_CERTS;
176df8bdeb3Sjohnz 	}
177df8bdeb3Sjohnz 	*plp = NULL;
178df8bdeb3Sjohnz 
179df8bdeb3Sjohnz 	if ((cert = elfcertlib_allocatecert()) == NULL) {
180df8bdeb3Sjohnz 		return (ret);
181df8bdeb3Sjohnz 	}
182df8bdeb3Sjohnz 
183df8bdeb3Sjohnz 	for (plp = pathlist; *plp; plp++) {
184df8bdeb3Sjohnz 		(void) memset(&fcparams, 0, sizeof (fcparams));
185df8bdeb3Sjohnz 		fcparams.kstype = KMF_KEYSTORE_OPENSSL;
186df8bdeb3Sjohnz 		fcparams.sslparms.certfile = *plp;
187df8bdeb3Sjohnz 		fcparams.subject = signer_DN;
188df8bdeb3Sjohnz 		ncerts = 2;
189df8bdeb3Sjohnz 
190df8bdeb3Sjohnz 		rv = KMF_FindCert(ess->es_kmfhandle, &fcparams, certbuf,
191df8bdeb3Sjohnz 		    &ncerts);
192df8bdeb3Sjohnz 		if (rv != KMF_OK)
193df8bdeb3Sjohnz 			continue;
194df8bdeb3Sjohnz 		if (ncerts > 1 && signer_DN == NULL) {
195df8bdeb3Sjohnz 			/* There can be only one */
196df8bdeb3Sjohnz 			cryptodebug("elfcertlib_getcert: "
197df8bdeb3Sjohnz 			    "too many certificates found in %s",
198df8bdeb3Sjohnz 			    cert_pathname);
199df8bdeb3Sjohnz 			goto cleanup;
200df8bdeb3Sjohnz 		}
201df8bdeb3Sjohnz 		/* found it, cache subject and issuer */
202df8bdeb3Sjohnz 		cert->c_cert = certbuf[0];
203df8bdeb3Sjohnz 		rv = KMF_GetCertSubjectNameString(ess->es_kmfhandle,
204df8bdeb3Sjohnz 		    &cert->c_cert.certificate, &cert->c_subject);
205df8bdeb3Sjohnz 		if (rv != KMF_OK)
206df8bdeb3Sjohnz 			goto cleanup;
207df8bdeb3Sjohnz 
208df8bdeb3Sjohnz 		rv = KMF_GetCertIssuerNameString(ess->es_kmfhandle,
209df8bdeb3Sjohnz 		    &cert->c_cert.certificate, &cert->c_issuer);
210df8bdeb3Sjohnz 		if (rv != KMF_OK)
211df8bdeb3Sjohnz 			goto cleanup;
212df8bdeb3Sjohnz 		break;
213df8bdeb3Sjohnz 	}
214df8bdeb3Sjohnz 	if (*plp == NULL) {
215df8bdeb3Sjohnz 		cryptodebug("elfcertlib_getcert: no certificate found");
216df8bdeb3Sjohnz 		goto cleanup;
217df8bdeb3Sjohnz 	}
218df8bdeb3Sjohnz 
219df8bdeb3Sjohnz 	cert->c_verified = E_UNCHECKED;
220df8bdeb3Sjohnz 
221df8bdeb3Sjohnz 	/*
222*2225707cSValerie Bubb Fenwick 	 * If the cert we are loading is the trust anchor (ie the CA) then
223df8bdeb3Sjohnz 	 * we mark it as such in cert.  This is so that we don't attempt
224df8bdeb3Sjohnz 	 * to verify it later.  The CA is always implicitly verified.
225df8bdeb3Sjohnz 	 */
226df8bdeb3Sjohnz 	if (cert_pathname != NULL && (
227df8bdeb3Sjohnz 	    strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 ||
228df8bdeb3Sjohnz 	    strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0)) {
229df8bdeb3Sjohnz 		if (ess->es_certCAcallback != NULL)
230df8bdeb3Sjohnz 			(ess->es_certCAcallback)(ess->es_callbackctx, cert,
231df8bdeb3Sjohnz 			    cert_pathname);
232df8bdeb3Sjohnz 		cert->c_verified = E_IS_TA;
233df8bdeb3Sjohnz 	}
234df8bdeb3Sjohnz 
235df8bdeb3Sjohnz 	ret = B_TRUE;
236df8bdeb3Sjohnz 
237df8bdeb3Sjohnz cleanup:
238df8bdeb3Sjohnz 	if (ret) {
239df8bdeb3Sjohnz 		*certp = cert;
240df8bdeb3Sjohnz 	} else {
241df8bdeb3Sjohnz 		if (cert != NULL)
242df8bdeb3Sjohnz 			elfcertlib_freecert(ess, cert);
243df8bdeb3Sjohnz 		if (signer_DN != NULL)
244df8bdeb3Sjohnz 			cryptoerror(LOG_ERR, "unable to find a certificate "
245df8bdeb3Sjohnz 			    "for DN: %s", signer_DN);
246df8bdeb3Sjohnz 		else
247df8bdeb3Sjohnz 			cryptoerror(LOG_ERR, "unable to load certificate "
248df8bdeb3Sjohnz 			    "from %s", cert_pathname);
249df8bdeb3Sjohnz 	}
250df8bdeb3Sjohnz 	return (ret);
251df8bdeb3Sjohnz }
252df8bdeb3Sjohnz 
253df8bdeb3Sjohnz /*
254df8bdeb3Sjohnz  * elfcertlib_loadprivatekey - Load the private key from path
255df8bdeb3Sjohnz  *
256df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
257df8bdeb3Sjohnz  *	cert
258df8bdeb3Sjohnz  *	pathname
259df8bdeb3Sjohnz  * OUT	cert
260df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
261df8bdeb3Sjohnz  */
262df8bdeb3Sjohnz boolean_t
263df8bdeb3Sjohnz elfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname)
264df8bdeb3Sjohnz {
265df8bdeb3Sjohnz 	KMF_RETURN rv = KMF_OK;
266df8bdeb3Sjohnz 	uint32_t nkeys = 2;
267df8bdeb3Sjohnz 	KMF_FINDKEY_PARAMS fkparams;
268df8bdeb3Sjohnz 	KMF_KEY_HANDLE	keybuf[2];
269df8bdeb3Sjohnz 
270df8bdeb3Sjohnz 	(void) memset(&fkparams, 0, sizeof (fkparams));
271df8bdeb3Sjohnz 	fkparams.keyclass = KMF_ASYM_PRI;
272df8bdeb3Sjohnz 	fkparams.kstype = KMF_KEYSTORE_OPENSSL;
273df8bdeb3Sjohnz 	fkparams.sslparms.keyfile = (char *)pathname;
274df8bdeb3Sjohnz 
275df8bdeb3Sjohnz 	rv = KMF_FindKey(ess->es_kmfhandle, &fkparams, keybuf, &nkeys);
276df8bdeb3Sjohnz 	if (rv != KMF_OK)
277df8bdeb3Sjohnz 		return (B_FALSE);
278df8bdeb3Sjohnz 	if (nkeys != 1) {
279df8bdeb3Sjohnz 		/* lack of specificity */
280df8bdeb3Sjohnz 		cryptodebug("found %d keys at %s", nkeys, pathname);
281df8bdeb3Sjohnz 		return (B_FALSE);
282df8bdeb3Sjohnz 	}
283df8bdeb3Sjohnz 	cert->c_privatekey = keybuf[0];
284df8bdeb3Sjohnz 	cryptodebug("key %s loaded", pathname);
285df8bdeb3Sjohnz 	return (B_TRUE);
286df8bdeb3Sjohnz }
287df8bdeb3Sjohnz 
288df8bdeb3Sjohnz /*
289df8bdeb3Sjohnz  * elfcertlib_loadtokenkey - Load the private key from token
290df8bdeb3Sjohnz  *
291df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
292df8bdeb3Sjohnz  *	cert
293df8bdeb3Sjohnz  *	token_label
294df8bdeb3Sjohnz  *	pin
295df8bdeb3Sjohnz  * OUT	cert
296df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
297df8bdeb3Sjohnz  */
298df8bdeb3Sjohnz boolean_t
299df8bdeb3Sjohnz elfcertlib_loadtokenkey(ELFsign_t ess, ELFCert_t cert,
300df8bdeb3Sjohnz     const char *token_label, const char *pin)
301df8bdeb3Sjohnz {
302df8bdeb3Sjohnz 	KMF_RETURN rv = KMF_OK;
303df8bdeb3Sjohnz 	KMF_FINDKEY_PARAMS fkparams;
304df8bdeb3Sjohnz 	KMF_CONFIG_PARAMS cfgparams;
305df8bdeb3Sjohnz 	uint32_t nkeys = 1;
306df8bdeb3Sjohnz 	char *idstr = NULL;
307df8bdeb3Sjohnz 	char *err = NULL;
308df8bdeb3Sjohnz 
309df8bdeb3Sjohnz 	(void) memset(&fkparams, 0, sizeof (fkparams));
310df8bdeb3Sjohnz 	(void) memset(&cfgparams, 0, sizeof (cfgparams));
311df8bdeb3Sjohnz 
312df8bdeb3Sjohnz 	cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN;
313df8bdeb3Sjohnz 	cfgparams.pkcs11config.label = (char *)token_label;
314df8bdeb3Sjohnz 	cfgparams.pkcs11config.readonly = B_TRUE;
315df8bdeb3Sjohnz 	rv = KMF_ConfigureKeystore(ess->es_kmfhandle, &cfgparams);
316df8bdeb3Sjohnz 	if (rv != KMF_OK) {
317df8bdeb3Sjohnz 		if (KMF_GetKMFErrorString(rv, &err) == KMF_OK) {
318df8bdeb3Sjohnz 			cryptodebug("Error configuring token access:"
319df8bdeb3Sjohnz 			    " %s\n", err);
320df8bdeb3Sjohnz 			free(err);
321df8bdeb3Sjohnz 		}
322df8bdeb3Sjohnz 		return (B_FALSE);
323df8bdeb3Sjohnz 	}
324df8bdeb3Sjohnz 
325df8bdeb3Sjohnz 	fkparams.idstr = idstr;
326df8bdeb3Sjohnz 	fkparams.kstype = KMF_KEYSTORE_PK11TOKEN;
327df8bdeb3Sjohnz 	fkparams.keyclass = KMF_ASYM_PRI;
328df8bdeb3Sjohnz 	fkparams.cred.cred = (char *)pin;
329df8bdeb3Sjohnz 	fkparams.cred.credlen = (pin != NULL ? strlen(pin) : 0);
330df8bdeb3Sjohnz 	fkparams.pkcs11parms.private = B_TRUE;
331df8bdeb3Sjohnz 
332df8bdeb3Sjohnz 	/*
333df8bdeb3Sjohnz 	 * We will search for the key based on the ID attribute
334df8bdeb3Sjohnz 	 * which was added when the key was created.  ID is
335df8bdeb3Sjohnz 	 * a SHA-1 hash of the public modulus shared by the
336df8bdeb3Sjohnz 	 * key and the certificate.
337df8bdeb3Sjohnz 	 */
338df8bdeb3Sjohnz 	rv = KMF_GetCertIDString(&cert->c_cert.certificate, &idstr);
339df8bdeb3Sjohnz 	if (rv != KMF_OK) {
340df8bdeb3Sjohnz 		if (KMF_GetKMFErrorString(rv, &err) == KMF_OK) {
341df8bdeb3Sjohnz 			cryptodebug("Error getting ID from cert: %s\n", err);
342df8bdeb3Sjohnz 			free(err);
343df8bdeb3Sjohnz 		}
344df8bdeb3Sjohnz 		return (B_FALSE);
345df8bdeb3Sjohnz 	}
346df8bdeb3Sjohnz 	fkparams.idstr = idstr;
347df8bdeb3Sjohnz 
348df8bdeb3Sjohnz 	rv = KMF_FindKey(ess->es_kmfhandle, &fkparams,
349df8bdeb3Sjohnz 	    &cert->c_privatekey, &nkeys);
350df8bdeb3Sjohnz 	if (rv != KMF_OK || nkeys != 1) {
351df8bdeb3Sjohnz 		if (KMF_GetKMFErrorString(rv, &err) == KMF_OK) {
352df8bdeb3Sjohnz 			cryptodebug("Error finding private key: %s\n", err);
353df8bdeb3Sjohnz 			free(err);
354df8bdeb3Sjohnz 		}
355df8bdeb3Sjohnz 		free(idstr);
356df8bdeb3Sjohnz 		return (B_FALSE);
357df8bdeb3Sjohnz 	}
358df8bdeb3Sjohnz 	cryptodebug("key found in %s", token_label);
359df8bdeb3Sjohnz 	cryptodebug("elfcertlib_loadprivatekey = 0x%.8X",
360df8bdeb3Sjohnz 	    &cert->c_privatekey);
361df8bdeb3Sjohnz 
362df8bdeb3Sjohnz 	free(idstr);
363df8bdeb3Sjohnz 	return (B_TRUE);
364df8bdeb3Sjohnz }
365df8bdeb3Sjohnz 
366df8bdeb3Sjohnz static const CK_BYTE MD5_DER_PREFIX[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
367df8bdeb3Sjohnz 	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
368df8bdeb3Sjohnz 
369df8bdeb3Sjohnz /*
370df8bdeb3Sjohnz  * elfcertlib_sign - sign the given DATA using the privatekey in cert
371df8bdeb3Sjohnz  *
372df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
373df8bdeb3Sjohnz  *	cert
374df8bdeb3Sjohnz  *	data
375df8bdeb3Sjohnz  *	data_len
376df8bdeb3Sjohnz  * OUT	sig	- must be big enough to hold the signature of data
377df8bdeb3Sjohnz  *		  Caller must allocate
378df8bdeb3Sjohnz  *	sig_len	- actual length used; 0 on failure.
379df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
380df8bdeb3Sjohnz  */
381df8bdeb3Sjohnz /*ARGSUSED*/
382df8bdeb3Sjohnz boolean_t
383df8bdeb3Sjohnz elfcertlib_sign(ELFsign_t ess, ELFCert_t cert,
384df8bdeb3Sjohnz 	const uchar_t *data, size_t data_len,
385df8bdeb3Sjohnz 	uchar_t *sig, size_t *sig_len)
386df8bdeb3Sjohnz {
387df8bdeb3Sjohnz 	KMF_RETURN ret = KMF_OK;
388df8bdeb3Sjohnz 	KMF_DATA tobesigned;
389df8bdeb3Sjohnz 	KMF_DATA signature;
390df8bdeb3Sjohnz 	uchar_t	 der_data[sizeof (MD5_DER_PREFIX) + MD5_DIGEST_LENGTH];
391df8bdeb3Sjohnz 
392df8bdeb3Sjohnz 	if (ess->es_version <= FILESIG_VERSION2) {
393df8bdeb3Sjohnz 		/* compatibility: take MD5 hash of SHA1 hash */
394df8bdeb3Sjohnz 		size_t	derlen = MD5_DIGEST_LENGTH;
395df8bdeb3Sjohnz 		MD5_CTX ctx;
396df8bdeb3Sjohnz 
397df8bdeb3Sjohnz 		/*
398df8bdeb3Sjohnz 		 * first: digest using software-based methods, don't
399df8bdeb3Sjohnz 		 * rely on the token for hashing.
400df8bdeb3Sjohnz 		 */
401df8bdeb3Sjohnz 		MD5Init(&ctx);
402df8bdeb3Sjohnz 		MD5Update(&ctx, data, data_len);
403df8bdeb3Sjohnz 		MD5Final(&der_data[sizeof (MD5_DER_PREFIX)], &ctx);
404df8bdeb3Sjohnz 
405df8bdeb3Sjohnz 		/*
406df8bdeb3Sjohnz 		 * second: insert prefix
407df8bdeb3Sjohnz 		 */
408df8bdeb3Sjohnz 		(void) memcpy(der_data, MD5_DER_PREFIX,
409df8bdeb3Sjohnz 		    sizeof (MD5_DER_PREFIX));
410df8bdeb3Sjohnz 		/*
411df8bdeb3Sjohnz 		 * prepare to sign the local buffer
412df8bdeb3Sjohnz 		 */
413df8bdeb3Sjohnz 		tobesigned.Data = (uchar_t *)der_data;
414df8bdeb3Sjohnz 		tobesigned.Length = sizeof (MD5_DER_PREFIX) + derlen;
415df8bdeb3Sjohnz 	} else {
416df8bdeb3Sjohnz 		tobesigned.Data = (uchar_t *)data;
417df8bdeb3Sjohnz 		tobesigned.Length = data_len;
418df8bdeb3Sjohnz 	}
419df8bdeb3Sjohnz 
420df8bdeb3Sjohnz 	signature.Data = (uchar_t *)sig;
421df8bdeb3Sjohnz 	signature.Length = *sig_len;
422df8bdeb3Sjohnz 
423df8bdeb3Sjohnz 	ret = KMF_SignDataWithKey(ess->es_kmfhandle,
424df8bdeb3Sjohnz 	    &cert->c_privatekey, (KMF_OID *)&KMFOID_RSA,
425df8bdeb3Sjohnz 	    &tobesigned, &signature);
426df8bdeb3Sjohnz 
427df8bdeb3Sjohnz 	if (ret != KMF_OK) {
428df8bdeb3Sjohnz 		char *err;
429df8bdeb3Sjohnz 		if (KMF_GetKMFErrorString(ret, &err) == KMF_OK &&
430df8bdeb3Sjohnz 		    err != NULL) {
431df8bdeb3Sjohnz 			cryptodebug("Error signing data: %s\n", err);
432df8bdeb3Sjohnz 			free(err);
433df8bdeb3Sjohnz 		}
434df8bdeb3Sjohnz 		*sig_len = 0;
435df8bdeb3Sjohnz 		return (B_FALSE);
436df8bdeb3Sjohnz 	}
437df8bdeb3Sjohnz 	*sig_len = signature.Length;
438df8bdeb3Sjohnz 	return (B_TRUE);
439df8bdeb3Sjohnz }
440df8bdeb3Sjohnz 
441df8bdeb3Sjohnz /*
442df8bdeb3Sjohnz  * elfcertlib_verifysig - verify the given DATA using the public key in cert
443df8bdeb3Sjohnz  *
444df8bdeb3Sjohnz  * IN	ess		- elfsign context structure
445df8bdeb3Sjohnz  *	cert
446df8bdeb3Sjohnz  *	signature
447df8bdeb3Sjohnz  *	sig_len
448df8bdeb3Sjohnz  *	data
449df8bdeb3Sjohnz  *	data_len
450df8bdeb3Sjohnz  * OUT	N/A
451df8bdeb3Sjohnz  * RETURNS	TRUE/FALSE
452df8bdeb3Sjohnz  */
453df8bdeb3Sjohnz boolean_t
454df8bdeb3Sjohnz elfcertlib_verifysig(ELFsign_t ess, ELFCert_t cert,
455df8bdeb3Sjohnz 	const uchar_t *signature, size_t sig_len,
456df8bdeb3Sjohnz 	const uchar_t *data, size_t data_len)
457df8bdeb3Sjohnz {
458df8bdeb3Sjohnz 	KMF_RETURN	rv;
459df8bdeb3Sjohnz 	KMF_DATA	indata;
460df8bdeb3Sjohnz 	KMF_DATA	insig;
461df8bdeb3Sjohnz 	KMF_ALGORITHM_INDEX algid;
462df8bdeb3Sjohnz 
463df8bdeb3Sjohnz 	indata.Data = (uchar_t *)data;
464df8bdeb3Sjohnz 	indata.Length = data_len;
465df8bdeb3Sjohnz 	insig.Data = (uchar_t *)signature;
466df8bdeb3Sjohnz 	insig.Length = sig_len;
467df8bdeb3Sjohnz 
468df8bdeb3Sjohnz 	if (ess->es_version <= FILESIG_VERSION2)
469df8bdeb3Sjohnz 		algid = KMF_ALGID_MD5WithRSA;
470df8bdeb3Sjohnz 	else
471df8bdeb3Sjohnz 		algid = KMF_ALGID_RSA;
472df8bdeb3Sjohnz 
473df8bdeb3Sjohnz 	/*
474*2225707cSValerie Bubb Fenwick 	 * We tell KMF to use the PKCS11 verification APIs
475*2225707cSValerie Bubb Fenwick 	 * here to prevent the use of OpenSSL and to keep
476*2225707cSValerie Bubb Fenwick 	 * all validation within the FIPS-140 boundary for
477*2225707cSValerie Bubb Fenwick 	 * the Cryptographic Framework.
478df8bdeb3Sjohnz 	 */
479df8bdeb3Sjohnz 	rv = KMF_VerifyDataWithCert(ess->es_kmfhandle,
480*2225707cSValerie Bubb Fenwick 	    KMF_KEYSTORE_PK11TOKEN, algid,
481df8bdeb3Sjohnz 	    &indata, &insig, &cert->c_cert.certificate);
482df8bdeb3Sjohnz 
483df8bdeb3Sjohnz 	return ((rv == KMF_OK));
484df8bdeb3Sjohnz }
485df8bdeb3Sjohnz 
486df8bdeb3Sjohnz /*
487df8bdeb3Sjohnz  * elfcertlib_getdn
488df8bdeb3Sjohnz  *
489df8bdeb3Sjohnz  * IN	cert
490df8bdeb3Sjohnz  * OUT	NONE
491df8bdeb3Sjohnz  * RETURN 	dn or NULL
492df8bdeb3Sjohnz  */
493df8bdeb3Sjohnz char *
494df8bdeb3Sjohnz elfcertlib_getdn(ELFCert_t cert)
495df8bdeb3Sjohnz {
496df8bdeb3Sjohnz 	cryptodebug("elfcertlib_getdn");
497df8bdeb3Sjohnz 
498df8bdeb3Sjohnz 	return (cert->c_subject);
499df8bdeb3Sjohnz }
500df8bdeb3Sjohnz 
501df8bdeb3Sjohnz /*
502df8bdeb3Sjohnz  * elfcertlib_getissuer
503df8bdeb3Sjohnz  *
504df8bdeb3Sjohnz  * IN	cert
505df8bdeb3Sjohnz  * OUT	NONE
506df8bdeb3Sjohnz  * RETURN 	dn or NULL
507df8bdeb3Sjohnz  */
508df8bdeb3Sjohnz char *
509df8bdeb3Sjohnz elfcertlib_getissuer(ELFCert_t cert)
510df8bdeb3Sjohnz {
511df8bdeb3Sjohnz 	cryptodebug("elfcertlib_issuer");
512df8bdeb3Sjohnz 
513df8bdeb3Sjohnz 	return (cert->c_issuer);
514df8bdeb3Sjohnz }
515df8bdeb3Sjohnz 
516df8bdeb3Sjohnz boolean_t
517df8bdeb3Sjohnz elfcertlib_init(ELFsign_t ess)
518df8bdeb3Sjohnz {
519df8bdeb3Sjohnz 	boolean_t rc = B_TRUE;
520df8bdeb3Sjohnz 	KMF_RETURN rv;
521df8bdeb3Sjohnz 	if (ess->es_kmfhandle == NULL) {
522df8bdeb3Sjohnz 		rv = KMF_Initialize(&ess->es_kmfhandle, NULL, NULL);
523df8bdeb3Sjohnz 		if (rv != KMF_OK) {
524df8bdeb3Sjohnz 			cryptoerror(LOG_ERR,
525df8bdeb3Sjohnz 			    "unable to initialize KMF library");
526df8bdeb3Sjohnz 			rc = B_FALSE;
527df8bdeb3Sjohnz 		}
528df8bdeb3Sjohnz 	}
529df8bdeb3Sjohnz 	return (rc);
530df8bdeb3Sjohnz }
531df8bdeb3Sjohnz 
532df8bdeb3Sjohnz void
533df8bdeb3Sjohnz elfcertlib_fini(ELFsign_t ess)
534df8bdeb3Sjohnz {
535df8bdeb3Sjohnz 	(void) KMF_Finalize(ess->es_kmfhandle);
536df8bdeb3Sjohnz }
537df8bdeb3Sjohnz 
538df8bdeb3Sjohnz /*
539df8bdeb3Sjohnz  * set the token device
540df8bdeb3Sjohnz  */
541df8bdeb3Sjohnz boolean_t
542df8bdeb3Sjohnz elfcertlib_settoken(ELFsign_t ess, char *token)
543df8bdeb3Sjohnz {
544df8bdeb3Sjohnz 	boolean_t rc = B_TRUE;
545df8bdeb3Sjohnz 	KMF_RETURN rv;
546df8bdeb3Sjohnz 	KMF_CONFIG_PARAMS cfgparams;
547df8bdeb3Sjohnz 
548df8bdeb3Sjohnz 	(void) memset(&cfgparams, 0, sizeof (cfgparams));
549df8bdeb3Sjohnz 	cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN;
550df8bdeb3Sjohnz 	cfgparams.pkcs11config.label = token;
551df8bdeb3Sjohnz 	cfgparams.pkcs11config.readonly = B_TRUE;
552df8bdeb3Sjohnz 	rv = KMF_ConfigureKeystore(ess->es_kmfhandle, &cfgparams);
553df8bdeb3Sjohnz 	if (rv != KMF_OK) {
554df8bdeb3Sjohnz 		cryptoerror(LOG_ERR, "unable to select token\n");
555df8bdeb3Sjohnz 		rc = B_FALSE;
556df8bdeb3Sjohnz 	}
557df8bdeb3Sjohnz 
558df8bdeb3Sjohnz 	return (rc);
559df8bdeb3Sjohnz }
560df8bdeb3Sjohnz 
561df8bdeb3Sjohnz /*
562df8bdeb3Sjohnz  * set the certificate CA identification callback
563df8bdeb3Sjohnz  */
564df8bdeb3Sjohnz void
565df8bdeb3Sjohnz elfcertlib_setcertCAcallback(ELFsign_t ess,
566df8bdeb3Sjohnz     void (*cb)(void *, ELFCert_t, char *))
567df8bdeb3Sjohnz {
568df8bdeb3Sjohnz 	ess->es_certCAcallback = cb;
569df8bdeb3Sjohnz }
570df8bdeb3Sjohnz 
571df8bdeb3Sjohnz /*
572df8bdeb3Sjohnz  * set the certificate verification callback
573df8bdeb3Sjohnz  */
574df8bdeb3Sjohnz void
575df8bdeb3Sjohnz elfcertlib_setcertvercallback(ELFsign_t ess,
576df8bdeb3Sjohnz     void (*cb)(void *, ELFCert_t, ELFCert_t))
577df8bdeb3Sjohnz {
578df8bdeb3Sjohnz 	ess->es_certvercallback = cb;
579df8bdeb3Sjohnz }
580df8bdeb3Sjohnz 
581df8bdeb3Sjohnz 
582df8bdeb3Sjohnz /*
583df8bdeb3Sjohnz  * elfcertlib_releasecert - release a cert
584df8bdeb3Sjohnz  *
585df8bdeb3Sjohnz  * IN cert
586df8bdeb3Sjohnz  * OUT cert
587df8bdeb3Sjohnz  * RETURN	N/A
588df8bdeb3Sjohnz  *
589df8bdeb3Sjohnz  */
590df8bdeb3Sjohnz void
591df8bdeb3Sjohnz elfcertlib_releasecert(ELFsign_t ess, ELFCert_t cert)
592df8bdeb3Sjohnz {
593df8bdeb3Sjohnz 	elfcertlib_freecert(ess, cert);
594df8bdeb3Sjohnz }
595df8bdeb3Sjohnz 
596df8bdeb3Sjohnz /*
597df8bdeb3Sjohnz  * elfcertlib_allocatecert - create a new ELFCert_t
598df8bdeb3Sjohnz  *
599df8bdeb3Sjohnz  * IN N/A
600df8bdeb3Sjohnz  * OUT	N/A
601df8bdeb3Sjohnz  * RETURN 	ELFCert_t, NULL on failure.
602df8bdeb3Sjohnz  */
603df8bdeb3Sjohnz static ELFCert_t
604df8bdeb3Sjohnz elfcertlib_allocatecert(void)
605df8bdeb3Sjohnz {
606df8bdeb3Sjohnz 	ELFCert_t cert = NULL;
607df8bdeb3Sjohnz 
608df8bdeb3Sjohnz 	cert = malloc(sizeof (struct ELFCert_s));
609df8bdeb3Sjohnz 	if (cert == NULL) {
610df8bdeb3Sjohnz 		cryptoerror(LOG_ERR,
611df8bdeb3Sjohnz 		    "elfcertlib_allocatecert: malloc failed %s",
612df8bdeb3Sjohnz 		    strerror(errno));
613df8bdeb3Sjohnz 		return (NULL);
614df8bdeb3Sjohnz 	}
615df8bdeb3Sjohnz 	(void) memset(cert, 0, sizeof (struct ELFCert_s));
616df8bdeb3Sjohnz 	cert->c_verified = E_UNCHECKED;
617df8bdeb3Sjohnz 	cert->c_subject = NULL;
618df8bdeb3Sjohnz 	cert->c_issuer = NULL;
619df8bdeb3Sjohnz 	return (cert);
620df8bdeb3Sjohnz }
621df8bdeb3Sjohnz 
622df8bdeb3Sjohnz /*
623df8bdeb3Sjohnz  * elfcertlib_freecert - freeup the memory of a cert
624df8bdeb3Sjohnz  *
625df8bdeb3Sjohnz  * IN cert
626df8bdeb3Sjohnz  * OUT cert
627df8bdeb3Sjohnz  * RETURN	N/A
628df8bdeb3Sjohnz  *
629df8bdeb3Sjohnz  */
630df8bdeb3Sjohnz static void
631df8bdeb3Sjohnz elfcertlib_freecert(ELFsign_t ess, ELFCert_t cert)
632df8bdeb3Sjohnz {
633df8bdeb3Sjohnz 	if (cert == NULL)
634df8bdeb3Sjohnz 		return;
635df8bdeb3Sjohnz 
636df8bdeb3Sjohnz 	free(cert->c_subject);
637df8bdeb3Sjohnz 	free(cert->c_issuer);
638df8bdeb3Sjohnz 
639df8bdeb3Sjohnz 	KMF_FreeKMFCert(ess->es_kmfhandle, &cert->c_cert);
640df8bdeb3Sjohnz 	KMF_FreeKMFKey(ess->es_kmfhandle, &cert->c_privatekey);
641df8bdeb3Sjohnz 
642df8bdeb3Sjohnz 	free(cert);
643df8bdeb3Sjohnz }
644