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