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