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