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