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