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