15194Sjohnz /* 25194Sjohnz * CDDL HEADER START 35194Sjohnz * 45194Sjohnz * The contents of this file are subject to the terms of the 55194Sjohnz * Common Development and Distribution License (the "License"). 65194Sjohnz * You may not use this file except in compliance with the License. 75194Sjohnz * 85194Sjohnz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95194Sjohnz * or http://www.opensolaris.org/os/licensing. 105194Sjohnz * See the License for the specific language governing permissions 115194Sjohnz * and limitations under the License. 125194Sjohnz * 135194Sjohnz * When distributing Covered Code, include this CDDL HEADER in each 145194Sjohnz * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155194Sjohnz * If applicable, add the following below this CDDL HEADER, with the 165194Sjohnz * fields enclosed by brackets "[]" replaced with your own identifying 175194Sjohnz * information: Portions Copyright [yyyy] [name of copyright owner] 185194Sjohnz * 195194Sjohnz * CDDL HEADER END 205194Sjohnz */ 215194Sjohnz 225194Sjohnz /* 23*10123SValerie.Fenwick@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 245194Sjohnz * Use is subject to license terms. 255194Sjohnz */ 265194Sjohnz 275194Sjohnz #include <limits.h> 285194Sjohnz #include <sys/types.h> 295194Sjohnz #include <sys/stat.h> 305194Sjohnz #include <fcntl.h> 315194Sjohnz #include <unistd.h> 325194Sjohnz #include <dirent.h> 335194Sjohnz #include <strings.h> 345194Sjohnz #include <stdio.h> 355194Sjohnz #include <stdlib.h> 365194Sjohnz #include <errno.h> 375194Sjohnz #include <sys/mman.h> 385194Sjohnz #include <md5.h> 395194Sjohnz #include <pthread.h> 405194Sjohnz 415194Sjohnz #include <cryptoutil.h> 425194Sjohnz 435194Sjohnz #include <kmfapi.h> 445194Sjohnz #include <sys/crypto/elfsign.h> 455194Sjohnz #include <libelfsign.h> 465194Sjohnz 475194Sjohnz #include <synch.h> 485194Sjohnz 495194Sjohnz const char _PATH_ELFSIGN_CRYPTO_CERTS[] = CRYPTO_CERTS_DIR; 505194Sjohnz const char _PATH_ELFSIGN_ETC_CERTS[] = ETC_CERTS_DIR; 515194Sjohnz 525194Sjohnz /* 535194Sjohnz * The CACERT and OBJCACERT are the Cryptographic Trust Anchors 545194Sjohnz * for the Solaris Cryptographic Framework. 555194Sjohnz */ 565194Sjohnz static const char _PATH_CRYPTO_CACERT[] = CRYPTO_CERTS_DIR "/CA"; 575194Sjohnz static const char _PATH_CRYPTO_OBJCACERT[] = CRYPTO_CERTS_DIR "/SUNWObjectCA"; 585194Sjohnz static ELFCert_t CACERT = NULL; 595194Sjohnz static ELFCert_t OBJCACERT = NULL; 605194Sjohnz static pthread_mutex_t ca_mutex = PTHREAD_MUTEX_INITIALIZER; 615194Sjohnz 625194Sjohnz static void elfcertlib_freecert(ELFsign_t, ELFCert_t); 635194Sjohnz static ELFCert_t elfcertlib_allocatecert(void); 645194Sjohnz 655194Sjohnz /* 665194Sjohnz * elfcertlib_verifycert - Verify the Cert with a Trust Anchor 675194Sjohnz * 685194Sjohnz * IN ess - elfsign context structure 695194Sjohnz * cert 705194Sjohnz * OUT NONE 715194Sjohnz * RETURN TRUE/FALSE 725194Sjohnz * 735194Sjohnz * We first setup the Trust Anchor (CA and SUNWObjectCA) certs 745194Sjohnz * if it hasn't been done already. We verify that the files on disk 755194Sjohnz * are those we expected. 765194Sjohnz * 775194Sjohnz * We then verify the given cert using the publickey of a TA. 785194Sjohnz * If the passed in cert is a TA or it has been verified already we 795194Sjohnz * short cut and return TRUE without futher validation. 805194Sjohnz */ 815194Sjohnz /*ARGSUSED*/ 825194Sjohnz boolean_t 835194Sjohnz elfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert) 845194Sjohnz { 855194Sjohnz KMF_RETURN rv; 865194Sjohnz if ((cert->c_verified == E_OK) || (cert->c_verified == E_IS_TA)) { 875194Sjohnz return (B_TRUE); 885194Sjohnz } 895194Sjohnz 905194Sjohnz (void) pthread_mutex_lock(&ca_mutex); 915194Sjohnz if (CACERT == NULL) { 925194Sjohnz (void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT, 935194Sjohnz NULL, &CACERT, ES_GET); 945194Sjohnz } 955194Sjohnz if (OBJCACERT == NULL) { 965194Sjohnz (void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT, 975194Sjohnz NULL, &OBJCACERT, ES_GET); 985194Sjohnz } 995194Sjohnz (void) pthread_mutex_unlock(&ca_mutex); 1005194Sjohnz 1015194Sjohnz if (CACERT != NULL) { 1025194Sjohnz rv = KMF_VerifyCertWithCert(ess->es_kmfhandle, 1035194Sjohnz (const KMF_DATA *)&cert->c_cert, 1045194Sjohnz (const KMF_DATA *)&CACERT->c_cert.certificate); 1055194Sjohnz if (rv == KMF_OK) { 1065194Sjohnz if (ess->es_certCAcallback != NULL) 1075194Sjohnz (ess->es_certvercallback)(ess->es_callbackctx, 1085194Sjohnz cert, CACERT); 1095194Sjohnz cert->c_verified = E_OK; 1105194Sjohnz return (B_TRUE); 1115194Sjohnz } 1125194Sjohnz } 1135194Sjohnz 1145194Sjohnz if (OBJCACERT != NULL) { 1155194Sjohnz rv = KMF_VerifyCertWithCert(ess->es_kmfhandle, 1165194Sjohnz (const KMF_DATA *)&cert->c_cert, 1175194Sjohnz (const KMF_DATA *)&OBJCACERT->c_cert.certificate); 1185194Sjohnz if (rv == KMF_OK) { 1195194Sjohnz if (ess->es_certCAcallback != NULL) 1205194Sjohnz (ess->es_certvercallback)(ess->es_callbackctx, 1215194Sjohnz cert, OBJCACERT); 1225194Sjohnz cert->c_verified = E_OK; 1235194Sjohnz return (B_TRUE); 1245194Sjohnz } 1255194Sjohnz } 1265194Sjohnz 1275194Sjohnz return (B_FALSE); 1285194Sjohnz } 1295194Sjohnz 1305194Sjohnz /* 1315194Sjohnz * elfcertlib_getcert - Get the certificate for signer_DN 1325194Sjohnz * 1335194Sjohnz * IN ess - elfsign context structure 1345194Sjohnz * cert_pathname - path to cert (May be NULL) 1355194Sjohnz * signer_DN - The DN we are looking for (May be NULL) 1365194Sjohnz * action - indicates crypto verification call 1375194Sjohnz * OUT certp - allocated/loaded ELFCert_t 1385194Sjohnz * 1395194Sjohnz * If the cert_pathname is passed use it and don't search. 1405194Sjohnz * Otherwise, go looking in certificate directories 1415194Sjohnz */ 1425194Sjohnz boolean_t 1435194Sjohnz elfcertlib_getcert(ELFsign_t ess, char *cert_pathname, 1445194Sjohnz char *signer_DN, ELFCert_t *certp, enum ES_ACTION action) 1455194Sjohnz { 1465194Sjohnz KMF_RETURN rv; 1475194Sjohnz ELFCert_t cert = NULL; 1485194Sjohnz KMF_FINDCERT_PARAMS fcparams; 1495194Sjohnz KMF_X509_DER_CERT certbuf[2]; 1505194Sjohnz uint32_t ncerts; 1515194Sjohnz boolean_t ret = B_FALSE; 1525194Sjohnz char *pathlist[3], **plp; 1535194Sjohnz 1545194Sjohnz cryptodebug("elfcertlib_getcert: path=%s, DN=%s", 1555194Sjohnz cert_pathname ? cert_pathname : "-none-", 1565194Sjohnz signer_DN ? signer_DN : "-none-"); 1575194Sjohnz *certp = NULL; 1585194Sjohnz if (cert_pathname == NULL && signer_DN == NULL) { 1595194Sjohnz cryptodebug("elfcertlib_getcert: lack of specificity"); 1605194Sjohnz return (ret); 1615194Sjohnz } 1625194Sjohnz 1635194Sjohnz plp = pathlist; 1645194Sjohnz if (cert_pathname != NULL) { 1655194Sjohnz /* look in the specified object */ 1665194Sjohnz *plp++ = cert_pathname; 1675194Sjohnz } else { 1685194Sjohnz /* look in the certificate directories */ 1695194Sjohnz *plp++ = (char *)_PATH_ELFSIGN_CRYPTO_CERTS; 1705194Sjohnz /* 1715194Sjohnz * crypto verifications don't search beyond 1725194Sjohnz * _PATH_ELFSIGN_CRYPTO_CERTS 1735194Sjohnz */ 1745194Sjohnz if (action != ES_GET_CRYPTO) 1755194Sjohnz *plp++ = (char *)_PATH_ELFSIGN_ETC_CERTS; 1765194Sjohnz } 1775194Sjohnz *plp = NULL; 1785194Sjohnz 1795194Sjohnz if ((cert = elfcertlib_allocatecert()) == NULL) { 1805194Sjohnz return (ret); 1815194Sjohnz } 1825194Sjohnz 1835194Sjohnz for (plp = pathlist; *plp; plp++) { 1845194Sjohnz (void) memset(&fcparams, 0, sizeof (fcparams)); 1855194Sjohnz fcparams.kstype = KMF_KEYSTORE_OPENSSL; 1865194Sjohnz fcparams.sslparms.certfile = *plp; 1875194Sjohnz fcparams.subject = signer_DN; 1885194Sjohnz ncerts = 2; 1895194Sjohnz 1905194Sjohnz rv = KMF_FindCert(ess->es_kmfhandle, &fcparams, certbuf, 1915194Sjohnz &ncerts); 1925194Sjohnz if (rv != KMF_OK) 1935194Sjohnz continue; 1945194Sjohnz if (ncerts > 1 && signer_DN == NULL) { 1955194Sjohnz /* There can be only one */ 1965194Sjohnz cryptodebug("elfcertlib_getcert: " 1975194Sjohnz "too many certificates found in %s", 1985194Sjohnz cert_pathname); 1995194Sjohnz goto cleanup; 2005194Sjohnz } 2015194Sjohnz /* found it, cache subject and issuer */ 2025194Sjohnz cert->c_cert = certbuf[0]; 2035194Sjohnz rv = KMF_GetCertSubjectNameString(ess->es_kmfhandle, 2045194Sjohnz &cert->c_cert.certificate, &cert->c_subject); 2055194Sjohnz if (rv != KMF_OK) 2065194Sjohnz goto cleanup; 2075194Sjohnz 2085194Sjohnz rv = KMF_GetCertIssuerNameString(ess->es_kmfhandle, 2095194Sjohnz &cert->c_cert.certificate, &cert->c_issuer); 2105194Sjohnz if (rv != KMF_OK) 2115194Sjohnz goto cleanup; 2125194Sjohnz break; 2135194Sjohnz } 2145194Sjohnz if (*plp == NULL) { 2155194Sjohnz cryptodebug("elfcertlib_getcert: no certificate found"); 2165194Sjohnz goto cleanup; 2175194Sjohnz } 2185194Sjohnz 2195194Sjohnz cert->c_verified = E_UNCHECKED; 2205194Sjohnz 2215194Sjohnz /* 222*10123SValerie.Fenwick@Sun.COM * If the cert we are loading is the trust anchor (ie the CA) then 2235194Sjohnz * we mark it as such in cert. This is so that we don't attempt 2245194Sjohnz * to verify it later. The CA is always implicitly verified. 2255194Sjohnz */ 2265194Sjohnz if (cert_pathname != NULL && ( 2275194Sjohnz strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 || 2285194Sjohnz strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0)) { 2295194Sjohnz if (ess->es_certCAcallback != NULL) 2305194Sjohnz (ess->es_certCAcallback)(ess->es_callbackctx, cert, 2315194Sjohnz cert_pathname); 2325194Sjohnz cert->c_verified = E_IS_TA; 2335194Sjohnz } 2345194Sjohnz 2355194Sjohnz ret = B_TRUE; 2365194Sjohnz 2375194Sjohnz cleanup: 2385194Sjohnz if (ret) { 2395194Sjohnz *certp = cert; 2405194Sjohnz } else { 2415194Sjohnz if (cert != NULL) 2425194Sjohnz elfcertlib_freecert(ess, cert); 2435194Sjohnz if (signer_DN != NULL) 2445194Sjohnz cryptoerror(LOG_ERR, "unable to find a certificate " 2455194Sjohnz "for DN: %s", signer_DN); 2465194Sjohnz else 2475194Sjohnz cryptoerror(LOG_ERR, "unable to load certificate " 2485194Sjohnz "from %s", cert_pathname); 2495194Sjohnz } 2505194Sjohnz return (ret); 2515194Sjohnz } 2525194Sjohnz 2535194Sjohnz /* 2545194Sjohnz * elfcertlib_loadprivatekey - Load the private key from path 2555194Sjohnz * 2565194Sjohnz * IN ess - elfsign context structure 2575194Sjohnz * cert 2585194Sjohnz * pathname 2595194Sjohnz * OUT cert 2605194Sjohnz * RETURNS TRUE/FALSE 2615194Sjohnz */ 2625194Sjohnz boolean_t 2635194Sjohnz elfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname) 2645194Sjohnz { 2655194Sjohnz KMF_RETURN rv = KMF_OK; 2665194Sjohnz uint32_t nkeys = 2; 2675194Sjohnz KMF_FINDKEY_PARAMS fkparams; 2685194Sjohnz KMF_KEY_HANDLE keybuf[2]; 2695194Sjohnz 2705194Sjohnz (void) memset(&fkparams, 0, sizeof (fkparams)); 2715194Sjohnz fkparams.keyclass = KMF_ASYM_PRI; 2725194Sjohnz fkparams.kstype = KMF_KEYSTORE_OPENSSL; 2735194Sjohnz fkparams.sslparms.keyfile = (char *)pathname; 2745194Sjohnz 2755194Sjohnz rv = KMF_FindKey(ess->es_kmfhandle, &fkparams, keybuf, &nkeys); 2765194Sjohnz if (rv != KMF_OK) 2775194Sjohnz return (B_FALSE); 2785194Sjohnz if (nkeys != 1) { 2795194Sjohnz /* lack of specificity */ 2805194Sjohnz cryptodebug("found %d keys at %s", nkeys, pathname); 2815194Sjohnz return (B_FALSE); 2825194Sjohnz } 2835194Sjohnz cert->c_privatekey = keybuf[0]; 2845194Sjohnz cryptodebug("key %s loaded", pathname); 2855194Sjohnz return (B_TRUE); 2865194Sjohnz } 2875194Sjohnz 2885194Sjohnz /* 2895194Sjohnz * elfcertlib_loadtokenkey - Load the private key from token 2905194Sjohnz * 2915194Sjohnz * IN ess - elfsign context structure 2925194Sjohnz * cert 2935194Sjohnz * token_label 2945194Sjohnz * pin 2955194Sjohnz * OUT cert 2965194Sjohnz * RETURNS TRUE/FALSE 2975194Sjohnz */ 2985194Sjohnz boolean_t 2995194Sjohnz elfcertlib_loadtokenkey(ELFsign_t ess, ELFCert_t cert, 3005194Sjohnz const char *token_label, const char *pin) 3015194Sjohnz { 3025194Sjohnz KMF_RETURN rv = KMF_OK; 3035194Sjohnz KMF_FINDKEY_PARAMS fkparams; 3045194Sjohnz KMF_CONFIG_PARAMS cfgparams; 3055194Sjohnz uint32_t nkeys = 1; 3065194Sjohnz char *idstr = NULL; 3075194Sjohnz char *err = NULL; 3085194Sjohnz 3095194Sjohnz (void) memset(&fkparams, 0, sizeof (fkparams)); 3105194Sjohnz (void) memset(&cfgparams, 0, sizeof (cfgparams)); 3115194Sjohnz 3125194Sjohnz cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN; 3135194Sjohnz cfgparams.pkcs11config.label = (char *)token_label; 3145194Sjohnz cfgparams.pkcs11config.readonly = B_TRUE; 3155194Sjohnz rv = KMF_ConfigureKeystore(ess->es_kmfhandle, &cfgparams); 3165194Sjohnz if (rv != KMF_OK) { 3175194Sjohnz if (KMF_GetKMFErrorString(rv, &err) == KMF_OK) { 3185194Sjohnz cryptodebug("Error configuring token access:" 3195194Sjohnz " %s\n", err); 3205194Sjohnz free(err); 3215194Sjohnz } 3225194Sjohnz return (B_FALSE); 3235194Sjohnz } 3245194Sjohnz 3255194Sjohnz fkparams.idstr = idstr; 3265194Sjohnz fkparams.kstype = KMF_KEYSTORE_PK11TOKEN; 3275194Sjohnz fkparams.keyclass = KMF_ASYM_PRI; 3285194Sjohnz fkparams.cred.cred = (char *)pin; 3295194Sjohnz fkparams.cred.credlen = (pin != NULL ? strlen(pin) : 0); 3305194Sjohnz fkparams.pkcs11parms.private = B_TRUE; 3315194Sjohnz 3325194Sjohnz /* 3335194Sjohnz * We will search for the key based on the ID attribute 3345194Sjohnz * which was added when the key was created. ID is 3355194Sjohnz * a SHA-1 hash of the public modulus shared by the 3365194Sjohnz * key and the certificate. 3375194Sjohnz */ 3385194Sjohnz rv = KMF_GetCertIDString(&cert->c_cert.certificate, &idstr); 3395194Sjohnz if (rv != KMF_OK) { 3405194Sjohnz if (KMF_GetKMFErrorString(rv, &err) == KMF_OK) { 3415194Sjohnz cryptodebug("Error getting ID from cert: %s\n", err); 3425194Sjohnz free(err); 3435194Sjohnz } 3445194Sjohnz return (B_FALSE); 3455194Sjohnz } 3465194Sjohnz fkparams.idstr = idstr; 3475194Sjohnz 3485194Sjohnz rv = KMF_FindKey(ess->es_kmfhandle, &fkparams, 3495194Sjohnz &cert->c_privatekey, &nkeys); 3505194Sjohnz if (rv != KMF_OK || nkeys != 1) { 3515194Sjohnz if (KMF_GetKMFErrorString(rv, &err) == KMF_OK) { 3525194Sjohnz cryptodebug("Error finding private key: %s\n", err); 3535194Sjohnz free(err); 3545194Sjohnz } 3555194Sjohnz free(idstr); 3565194Sjohnz return (B_FALSE); 3575194Sjohnz } 3585194Sjohnz cryptodebug("key found in %s", token_label); 3595194Sjohnz cryptodebug("elfcertlib_loadprivatekey = 0x%.8X", 3605194Sjohnz &cert->c_privatekey); 3615194Sjohnz 3625194Sjohnz free(idstr); 3635194Sjohnz return (B_TRUE); 3645194Sjohnz } 3655194Sjohnz 3665194Sjohnz static const CK_BYTE MD5_DER_PREFIX[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 3675194Sjohnz 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; 3685194Sjohnz 3695194Sjohnz /* 3705194Sjohnz * elfcertlib_sign - sign the given DATA using the privatekey in cert 3715194Sjohnz * 3725194Sjohnz * IN ess - elfsign context structure 3735194Sjohnz * cert 3745194Sjohnz * data 3755194Sjohnz * data_len 3765194Sjohnz * OUT sig - must be big enough to hold the signature of data 3775194Sjohnz * Caller must allocate 3785194Sjohnz * sig_len - actual length used; 0 on failure. 3795194Sjohnz * RETURNS TRUE/FALSE 3805194Sjohnz */ 3815194Sjohnz /*ARGSUSED*/ 3825194Sjohnz boolean_t 3835194Sjohnz elfcertlib_sign(ELFsign_t ess, ELFCert_t cert, 3845194Sjohnz const uchar_t *data, size_t data_len, 3855194Sjohnz uchar_t *sig, size_t *sig_len) 3865194Sjohnz { 3875194Sjohnz KMF_RETURN ret = KMF_OK; 3885194Sjohnz KMF_DATA tobesigned; 3895194Sjohnz KMF_DATA signature; 3905194Sjohnz uchar_t der_data[sizeof (MD5_DER_PREFIX) + MD5_DIGEST_LENGTH]; 3915194Sjohnz 3925194Sjohnz if (ess->es_version <= FILESIG_VERSION2) { 3935194Sjohnz /* compatibility: take MD5 hash of SHA1 hash */ 3945194Sjohnz size_t derlen = MD5_DIGEST_LENGTH; 3955194Sjohnz MD5_CTX ctx; 3965194Sjohnz 3975194Sjohnz /* 3985194Sjohnz * first: digest using software-based methods, don't 3995194Sjohnz * rely on the token for hashing. 4005194Sjohnz */ 4015194Sjohnz MD5Init(&ctx); 4025194Sjohnz MD5Update(&ctx, data, data_len); 4035194Sjohnz MD5Final(&der_data[sizeof (MD5_DER_PREFIX)], &ctx); 4045194Sjohnz 4055194Sjohnz /* 4065194Sjohnz * second: insert prefix 4075194Sjohnz */ 4085194Sjohnz (void) memcpy(der_data, MD5_DER_PREFIX, 4095194Sjohnz sizeof (MD5_DER_PREFIX)); 4105194Sjohnz /* 4115194Sjohnz * prepare to sign the local buffer 4125194Sjohnz */ 4135194Sjohnz tobesigned.Data = (uchar_t *)der_data; 4145194Sjohnz tobesigned.Length = sizeof (MD5_DER_PREFIX) + derlen; 4155194Sjohnz } else { 4165194Sjohnz tobesigned.Data = (uchar_t *)data; 4175194Sjohnz tobesigned.Length = data_len; 4185194Sjohnz } 4195194Sjohnz 4205194Sjohnz signature.Data = (uchar_t *)sig; 4215194Sjohnz signature.Length = *sig_len; 4225194Sjohnz 4235194Sjohnz ret = KMF_SignDataWithKey(ess->es_kmfhandle, 4245194Sjohnz &cert->c_privatekey, (KMF_OID *)&KMFOID_RSA, 4255194Sjohnz &tobesigned, &signature); 4265194Sjohnz 4275194Sjohnz if (ret != KMF_OK) { 4285194Sjohnz char *err; 4295194Sjohnz if (KMF_GetKMFErrorString(ret, &err) == KMF_OK && 4305194Sjohnz err != NULL) { 4315194Sjohnz cryptodebug("Error signing data: %s\n", err); 4325194Sjohnz free(err); 4335194Sjohnz } 4345194Sjohnz *sig_len = 0; 4355194Sjohnz return (B_FALSE); 4365194Sjohnz } 4375194Sjohnz *sig_len = signature.Length; 4385194Sjohnz return (B_TRUE); 4395194Sjohnz } 4405194Sjohnz 4415194Sjohnz /* 4425194Sjohnz * elfcertlib_verifysig - verify the given DATA using the public key in cert 4435194Sjohnz * 4445194Sjohnz * IN ess - elfsign context structure 4455194Sjohnz * cert 4465194Sjohnz * signature 4475194Sjohnz * sig_len 4485194Sjohnz * data 4495194Sjohnz * data_len 4505194Sjohnz * OUT N/A 4515194Sjohnz * RETURNS TRUE/FALSE 4525194Sjohnz */ 4535194Sjohnz boolean_t 4545194Sjohnz elfcertlib_verifysig(ELFsign_t ess, ELFCert_t cert, 4555194Sjohnz const uchar_t *signature, size_t sig_len, 4565194Sjohnz const uchar_t *data, size_t data_len) 4575194Sjohnz { 4585194Sjohnz KMF_RETURN rv; 4595194Sjohnz KMF_DATA indata; 4605194Sjohnz KMF_DATA insig; 4615194Sjohnz KMF_ALGORITHM_INDEX algid; 4625194Sjohnz 4635194Sjohnz indata.Data = (uchar_t *)data; 4645194Sjohnz indata.Length = data_len; 4655194Sjohnz insig.Data = (uchar_t *)signature; 4665194Sjohnz insig.Length = sig_len; 4675194Sjohnz 4685194Sjohnz if (ess->es_version <= FILESIG_VERSION2) 4695194Sjohnz algid = KMF_ALGID_MD5WithRSA; 4705194Sjohnz else 4715194Sjohnz algid = KMF_ALGID_RSA; 4725194Sjohnz 4735194Sjohnz /* 474*10123SValerie.Fenwick@Sun.COM * We tell KMF to use the PKCS11 verification APIs 475*10123SValerie.Fenwick@Sun.COM * here to prevent the use of OpenSSL and to keep 476*10123SValerie.Fenwick@Sun.COM * all validation within the FIPS-140 boundary for 477*10123SValerie.Fenwick@Sun.COM * the Cryptographic Framework. 4785194Sjohnz */ 4795194Sjohnz rv = KMF_VerifyDataWithCert(ess->es_kmfhandle, 480*10123SValerie.Fenwick@Sun.COM KMF_KEYSTORE_PK11TOKEN, algid, 4815194Sjohnz &indata, &insig, &cert->c_cert.certificate); 4825194Sjohnz 4835194Sjohnz return ((rv == KMF_OK)); 4845194Sjohnz } 4855194Sjohnz 4865194Sjohnz /* 4875194Sjohnz * elfcertlib_getdn 4885194Sjohnz * 4895194Sjohnz * IN cert 4905194Sjohnz * OUT NONE 4915194Sjohnz * RETURN dn or NULL 4925194Sjohnz */ 4935194Sjohnz char * 4945194Sjohnz elfcertlib_getdn(ELFCert_t cert) 4955194Sjohnz { 4965194Sjohnz cryptodebug("elfcertlib_getdn"); 4975194Sjohnz 4985194Sjohnz return (cert->c_subject); 4995194Sjohnz } 5005194Sjohnz 5015194Sjohnz /* 5025194Sjohnz * elfcertlib_getissuer 5035194Sjohnz * 5045194Sjohnz * IN cert 5055194Sjohnz * OUT NONE 5065194Sjohnz * RETURN dn or NULL 5075194Sjohnz */ 5085194Sjohnz char * 5095194Sjohnz elfcertlib_getissuer(ELFCert_t cert) 5105194Sjohnz { 5115194Sjohnz cryptodebug("elfcertlib_issuer"); 5125194Sjohnz 5135194Sjohnz return (cert->c_issuer); 5145194Sjohnz } 5155194Sjohnz 5165194Sjohnz boolean_t 5175194Sjohnz elfcertlib_init(ELFsign_t ess) 5185194Sjohnz { 5195194Sjohnz boolean_t rc = B_TRUE; 5205194Sjohnz KMF_RETURN rv; 5215194Sjohnz if (ess->es_kmfhandle == NULL) { 5225194Sjohnz rv = KMF_Initialize(&ess->es_kmfhandle, NULL, NULL); 5235194Sjohnz if (rv != KMF_OK) { 5245194Sjohnz cryptoerror(LOG_ERR, 5255194Sjohnz "unable to initialize KMF library"); 5265194Sjohnz rc = B_FALSE; 5275194Sjohnz } 5285194Sjohnz } 5295194Sjohnz return (rc); 5305194Sjohnz } 5315194Sjohnz 5325194Sjohnz void 5335194Sjohnz elfcertlib_fini(ELFsign_t ess) 5345194Sjohnz { 5355194Sjohnz (void) KMF_Finalize(ess->es_kmfhandle); 5365194Sjohnz } 5375194Sjohnz 5385194Sjohnz /* 5395194Sjohnz * set the token device 5405194Sjohnz */ 5415194Sjohnz boolean_t 5425194Sjohnz elfcertlib_settoken(ELFsign_t ess, char *token) 5435194Sjohnz { 5445194Sjohnz boolean_t rc = B_TRUE; 5455194Sjohnz KMF_RETURN rv; 5465194Sjohnz KMF_CONFIG_PARAMS cfgparams; 5475194Sjohnz 5485194Sjohnz (void) memset(&cfgparams, 0, sizeof (cfgparams)); 5495194Sjohnz cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN; 5505194Sjohnz cfgparams.pkcs11config.label = token; 5515194Sjohnz cfgparams.pkcs11config.readonly = B_TRUE; 5525194Sjohnz rv = KMF_ConfigureKeystore(ess->es_kmfhandle, &cfgparams); 5535194Sjohnz if (rv != KMF_OK) { 5545194Sjohnz cryptoerror(LOG_ERR, "unable to select token\n"); 5555194Sjohnz rc = B_FALSE; 5565194Sjohnz } 5575194Sjohnz 5585194Sjohnz return (rc); 5595194Sjohnz } 5605194Sjohnz 5615194Sjohnz /* 5625194Sjohnz * set the certificate CA identification callback 5635194Sjohnz */ 5645194Sjohnz void 5655194Sjohnz elfcertlib_setcertCAcallback(ELFsign_t ess, 5665194Sjohnz void (*cb)(void *, ELFCert_t, char *)) 5675194Sjohnz { 5685194Sjohnz ess->es_certCAcallback = cb; 5695194Sjohnz } 5705194Sjohnz 5715194Sjohnz /* 5725194Sjohnz * set the certificate verification callback 5735194Sjohnz */ 5745194Sjohnz void 5755194Sjohnz elfcertlib_setcertvercallback(ELFsign_t ess, 5765194Sjohnz void (*cb)(void *, ELFCert_t, ELFCert_t)) 5775194Sjohnz { 5785194Sjohnz ess->es_certvercallback = cb; 5795194Sjohnz } 5805194Sjohnz 5815194Sjohnz 5825194Sjohnz /* 5835194Sjohnz * elfcertlib_releasecert - release a cert 5845194Sjohnz * 5855194Sjohnz * IN cert 5865194Sjohnz * OUT cert 5875194Sjohnz * RETURN N/A 5885194Sjohnz * 5895194Sjohnz */ 5905194Sjohnz void 5915194Sjohnz elfcertlib_releasecert(ELFsign_t ess, ELFCert_t cert) 5925194Sjohnz { 5935194Sjohnz elfcertlib_freecert(ess, cert); 5945194Sjohnz } 5955194Sjohnz 5965194Sjohnz /* 5975194Sjohnz * elfcertlib_allocatecert - create a new ELFCert_t 5985194Sjohnz * 5995194Sjohnz * IN N/A 6005194Sjohnz * OUT N/A 6015194Sjohnz * RETURN ELFCert_t, NULL on failure. 6025194Sjohnz */ 6035194Sjohnz static ELFCert_t 6045194Sjohnz elfcertlib_allocatecert(void) 6055194Sjohnz { 6065194Sjohnz ELFCert_t cert = NULL; 6075194Sjohnz 6085194Sjohnz cert = malloc(sizeof (struct ELFCert_s)); 6095194Sjohnz if (cert == NULL) { 6105194Sjohnz cryptoerror(LOG_ERR, 6115194Sjohnz "elfcertlib_allocatecert: malloc failed %s", 6125194Sjohnz strerror(errno)); 6135194Sjohnz return (NULL); 6145194Sjohnz } 6155194Sjohnz (void) memset(cert, 0, sizeof (struct ELFCert_s)); 6165194Sjohnz cert->c_verified = E_UNCHECKED; 6175194Sjohnz cert->c_subject = NULL; 6185194Sjohnz cert->c_issuer = NULL; 6195194Sjohnz return (cert); 6205194Sjohnz } 6215194Sjohnz 6225194Sjohnz /* 6235194Sjohnz * elfcertlib_freecert - freeup the memory of a cert 6245194Sjohnz * 6255194Sjohnz * IN cert 6265194Sjohnz * OUT cert 6275194Sjohnz * RETURN N/A 6285194Sjohnz * 6295194Sjohnz */ 6305194Sjohnz static void 6315194Sjohnz elfcertlib_freecert(ELFsign_t ess, ELFCert_t cert) 6325194Sjohnz { 6335194Sjohnz if (cert == NULL) 6345194Sjohnz return; 6355194Sjohnz 6365194Sjohnz free(cert->c_subject); 6375194Sjohnz free(cert->c_issuer); 6385194Sjohnz 6395194Sjohnz KMF_FreeKMFCert(ess->es_kmfhandle, &cert->c_cert); 6405194Sjohnz KMF_FreeKMFKey(ess->es_kmfhandle, &cert->c_privatekey); 6415194Sjohnz 6425194Sjohnz free(cert); 6435194Sjohnz } 644