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 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 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 */ 2648bab47abSJohn.Zolnowsky@Sun.COM 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) { 269df8bdeb3Sjohnz /* There can be only one */ 270df8bdeb3Sjohnz cryptodebug("elfcertlib_getcert: " 271df8bdeb3Sjohnz "too many certificates found in %s", 272df8bdeb3Sjohnz cert_pathname); 273df8bdeb3Sjohnz goto cleanup; 274df8bdeb3Sjohnz } 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 338df8bdeb3Sjohnz elfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname) 339df8bdeb3Sjohnz { 340df8bdeb3Sjohnz 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; 349df8bdeb3Sjohnz 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; 355df8bdeb3Sjohnz 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 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; 400df8bdeb3Sjohnz 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 } 426df8bdeb3Sjohnz 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); 460df8bdeb3Sjohnz 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 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; 501df8bdeb3Sjohnz KMF_DATA tobesigned; 502df8bdeb3Sjohnz KMF_DATA signature; 503df8bdeb3Sjohnz 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 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 * 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 * 650df8bdeb3Sjohnz elfcertlib_getissuer(ELFCert_t cert) 651df8bdeb3Sjohnz { 652df8bdeb3Sjohnz cryptodebug("elfcertlib_issuer"); 653df8bdeb3Sjohnz 654df8bdeb3Sjohnz return (cert->c_issuer); 655df8bdeb3Sjohnz } 656df8bdeb3Sjohnz 657df8bdeb3Sjohnz boolean_t 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 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 683df8bdeb3Sjohnz elfcertlib_settoken(ELFsign_t ess, char *token) 684df8bdeb3Sjohnz { 685df8bdeb3Sjohnz boolean_t rc = B_TRUE; 686df8bdeb3Sjohnz 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; 691df8bdeb3Sjohnz 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 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 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 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 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 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