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