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