#include <security_keychain/Trust.h>
#include <security_keychain/TrustSettingsSchema.h>
#include <security_cdsa_utilities/cssmdates.h>
#include <security_utilities/cfutilities.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/SecCertificate.h>
#include <Security/SecTrust.h>
#include "SecBridge.h"
#include "TrustAdditions.h"
#include "TrustKeychains.h"
#include <security_cdsa_client/dlclient.h>
using namespace Security;
using namespace KeychainCore;
static inline CssmData cfData(CFDataRef data)
{
return CssmData(const_cast<UInt8 *>(CFDataGetBytePtr(data)),
CFDataGetLength(data));
}
static SecCertificateRef
convert(const SecPointer<Certificate> &certificate)
{
return *certificate;
}
ModuleNexus<TrustStore> Trust::gStore;
#pragma mark -- TrustKeychains --
static const CSSM_DL_DB_HANDLE nullCSSMDLDBHandle = {0,};
class TrustKeychains
{
public:
TrustKeychains();
~TrustKeychains() {}
CSSM_DL_DB_HANDLE rootStoreHandle() { return mRootStoreHandle; }
CSSM_DL_DB_HANDLE systemKcHandle() { return mSystem ? mSystem->database()->handle() : nullCSSMDLDBHandle; }
Keychain &systemKc() { return mSystem; }
Keychain &rootStore() { return *mRootStore; }
private:
DL* mRootStoreDL;
Db* mRootStoreDb;
Keychain* mRootStore;
CSSM_DL_DB_HANDLE mRootStoreHandle;
Keychain mSystem;
};
static ModuleNexus<TrustKeychains> trustKeychains;
static ModuleNexus<RecursiveMutex> trustKeychainsMutex;
extern "C" bool GetServerMode();
TrustKeychains::TrustKeychains() :
mRootStoreHandle(nullCSSMDLDBHandle),
mSystem(globals().storageManager.make(ADMIN_CERT_STORE_PATH, false))
{
if (GetServerMode()) {
mRootStoreDL = new DL(gGuidAppleFileDL),
mRootStoreDb = new Db(*mRootStoreDL, SYSTEM_ROOT_STORE_PATH),
(*mRootStoreDb)->activate();
mRootStoreHandle = (*mRootStoreDb)->handle();
}
else
{
mRootStore = new Keychain(globals().storageManager.make(SYSTEM_ROOT_STORE_PATH, false));
(*mRootStore)->database()->activate();
mRootStoreHandle = (*mRootStore)->database()->handle();
}
}
RecursiveMutex& SecTrustKeychainsGetMutex()
{
return trustKeychainsMutex();
}
#pragma mark -- Trust --
Trust::Trust(CFTypeRef certificates, CFTypeRef policies)
: mTP(gGuidAppleX509TP), mAction(CSSM_TP_ACTION_DEFAULT),
mCerts(cfArrayize(certificates)), mPolicies(cfArrayize(policies)),
mSearchLibs(NULL), mSearchLibsSet(false), mResult(kSecTrustResultInvalid),
mUsingTrustSettings(false), mAnchorPolicy(useAnchorsDefault), mMutex(Mutex::recursive)
{
if (!mPolicies) {
mPolicies.take(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks));
}
}
Trust::~Trust()
{
clearResults();
if (mSearchLibs) {
delete mSearchLibs;
}
mPolicies = NULL;
}
StorageManager::KeychainList& Trust::searchLibs(bool init)
{
if (!mSearchLibs) {
mSearchLibs = new StorageManager::KeychainList;
if (init) {
globals().storageManager.getSearchList(*mSearchLibs);
}
}
return *mSearchLibs;
}
void Trust::searchLibs(StorageManager::KeychainList &libs)
{
searchLibs(false) = libs;
mSearchLibsSet = true;
}
CSSM_TP_VERIFY_CONTEXT_RESULT_PTR Trust::cssmResult()
{
if (mResult == kSecTrustResultInvalid)
MacOSError::throwMe(errSecTrustNotAvailable);
return &mTpResult;
}
static
CssmData cfCertificateData(SecCertificateRef certificate)
{
return Certificate::required(certificate)->data();
}
static
CssmField cfField(SecPolicyRef item)
{
SecPointer<Policy> policy = Policy::required(SecPolicyRef(item));
return CssmField(policy->oid(), policy->value());
}
#if 0
static
CSSM_DL_DB_HANDLE cfKeychain(SecKeychainRef ref)
{
Keychain keychain = KeychainImpl::required(ref);
return keychain->database()->handle();
}
#endif
#if !defined(NDEBUG)
void showCertSKID(const void *value, void *context);
#endif
void Trust::evaluate(bool disableEV)
{
bool isEVCandidate=false;
{
StLock<Mutex>_(mMutex);
clearResults();
CFArrayRef allowedAnchors = allowedEVRootsForLeafCertificate(mCerts);
CFArrayRef filteredCerts = NULL;
isEVCandidate = (allowedAnchors && !disableEV) ? true : false;
if (isEVCandidate) {
secdebug("evTrust", "Trust::evaluate() certificate is EV candidate");
filteredCerts = potentialEVChainWithCertificates(mCerts);
mCerts = filteredCerts;
} else {
secdebug("evTrust", "Trust::evaluate() performing standard evaluation");
if (mCerts) {
filteredCerts = CFArrayCreateMutableCopy(NULL, 0, mCerts);
}
if (mAnchors) {
allowedAnchors = CFArrayCreateMutableCopy(NULL, 0, mAnchors);
}
}
mAllowedAnchors = allowedAnchors;
mFilteredCerts = filteredCerts;
if (allowedAnchors)
CFRelease(allowedAnchors);
if (filteredCerts)
CFRelease(filteredCerts);
if (mAllowedAnchors)
{
secdebug("trusteval", "Trust::evaluate: anchors: %ld", CFArrayGetCount(mAllowedAnchors));
#if !defined(NDEBUG)
CFArrayApplyFunction(mAllowedAnchors, CFRangeMake(0, CFArrayGetCount(mAllowedAnchors)), showCertSKID, NULL);
#endif
}
if(!mSearchLibsSet) {
globals().storageManager.getSearchList(searchLibs());
mSearchLibsSet = true;
}
CFToVector<CssmData, SecCertificateRef, cfCertificateData> subjects(mFilteredCerts);
CertGroup subjectCertGroup(CSSM_CERT_X_509v3,
CSSM_CERT_ENCODING_BER, CSSM_CERTGROUP_DATA);
subjectCertGroup.count() = subjects;
subjectCertGroup.blobCerts() = subjects;
TPBuildVerifyContext context(mAction);
CSSM_APPLE_TP_ACTION_DATA localActionData;
memset(&localActionData, 0, sizeof(localActionData));
CssmData localActionCData((uint8 *)&localActionData, sizeof(localActionData));
CSSM_APPLE_TP_ACTION_DATA *actionDataP = &localActionData;
if (mActionData) {
context.actionData() = cfData(mActionData);
actionDataP = (CSSM_APPLE_TP_ACTION_DATA *)context.actionData().data();
}
else {
context.actionData() = localActionCData;
}
if (!mAnchors) {
actionDataP->ActionFlags |= CSSM_TP_ACTION_TRUST_SETTINGS;
}
if (mNetworkPolicy == useNetworkDefault) {
if (policySpecified(mPolicies, CSSMOID_APPLE_TP_SSL)) {
actionDataP->ActionFlags |= CSSM_TP_ACTION_FETCH_CERT_FROM_NET;
}
}
else if (mNetworkPolicy == useNetworkEnabled)
actionDataP->ActionFlags |= CSSM_TP_ACTION_FETCH_CERT_FROM_NET;
else if (mNetworkPolicy == useNetworkDisabled)
actionDataP->ActionFlags &= ~(CSSM_TP_ACTION_FETCH_CERT_FROM_NET);
CFMutableArrayRef allPolicies = NULL;
uint32 numRevocationAdded = 0;
bool requirePerCert = (actionDataP->ActionFlags & CSSM_TP_ACTION_REQUIRE_REV_PER_CERT);
bool avoidRevChecks = (policySpecified(mPolicies, CSSMOID_APPLE_TP_EAP));
allPolicies = convertRevocationPolicy(numRevocationAdded, context.allocator);
if (allPolicies) {
secdebug("evTrust", "Trust::evaluate() using explicit revocation policy (%d)",
numRevocationAdded);
if (numRevocationAdded == 0)
isEVCandidate = false;
}
else if (mAnchors && (CFArrayGetCount(mAnchors)==0) && (searchLibs().size()==0)) {
secdebug("evTrust", "Trust::evaluate() has empty anchors and no keychains");
allPolicies = NULL; isEVCandidate = false;
}
else if ((isEVCandidate && !avoidRevChecks) || requirePerCert) {
secdebug("evTrust", "Trust::evaluate() forcing OCSP/CRL revocation check");
allPolicies = forceRevocationPolicies(numRevocationAdded,
context.allocator, requirePerCert);
}
else if(!(revocationPolicySpecified(mPolicies)) && !avoidRevChecks) {
allPolicies = addPreferenceRevocationPolicies(numRevocationAdded,
context.allocator);
}
if (allPolicies == NULL) {
secdebug("evTrust", "Trust::evaluate() will not perform revocation check");
CFIndex numPolicies = CFArrayGetCount(mPolicies);
CFAllocatorRef allocator = CFGetAllocator(mPolicies);
allPolicies = CFArrayCreateMutableCopy(allocator, numPolicies, mPolicies);
}
orderRevocationPolicies(allPolicies);
CFToVector<CssmField, SecPolicyRef, cfField> policies(allPolicies);
#if 0
if (policies.empty())
MacOSError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS);
#endif
context.setPolicies(policies, policies);
CFCopyRef<CFArrayRef> anchors(mAllowedAnchors);
CFToVector<CssmData, SecCertificateRef, cfCertificateData> roots(anchors);
if (!anchors) {
mUsingTrustSettings = (mAnchorPolicy < useAnchorsOnly);
secdebug("userTrust", "Trust::evaluate() %s",
(mUsingTrustSettings) ? "using UserTrust" : "has no trusted anchors!");
}
else {
mUsingTrustSettings = (mAnchorPolicy == useAnchorsAndBuiltIns);
secdebug("userTrust", "Trust::evaluate() using %s %s anchors",
(mUsingTrustSettings) ? "UserTrust AND" : "only",
(isEVCandidate) ? "EV" : "caller");
context.anchors(roots, roots);
}
vector<CSSM_DL_DB_HANDLE> dlDbList;
{
StLock<Mutex> _(SecTrustKeychainsGetMutex());
StorageManager::KeychainList& list = searchLibs();
for (StorageManager::KeychainList::const_iterator it = list.begin();
it != list.end(); it++)
{
try
{
CSSM_DL_DB_HANDLE dldbHandle = (*it)->database()->handle();
if (dldbHandle.DLHandle) {
CSSM_GUID guid = {};
CSSM_RETURN crtn = CSSM_GetModuleGUIDFromHandle(dldbHandle.DLHandle, &guid);
if (crtn == CSSM_OK) {
if ((memcmp(&guid, &gGuidAppleLDAPDL, sizeof(CSSM_GUID))==0) ||
(memcmp(&guid, &gGuidAppleDotMacDL, sizeof(CSSM_GUID))==0)) {
continue; }
}
}
dlDbList.push_back(dldbHandle);
}
catch (...)
{
}
}
if(mUsingTrustSettings) {
try {
CSSM_DL_DB_HANDLE rootStoreHandle = trustKeychains().rootStoreHandle();
if (rootStoreHandle.DBHandle)
dlDbList.push_back(rootStoreHandle);
actionDataP->ActionFlags |= CSSM_TP_ACTION_TRUST_SETTINGS;
}
catch (...) {
mUsingTrustSettings = false;
}
try {
CSSM_DL_DB_HANDLE systemKcHandle = trustKeychains().systemKcHandle();
if (systemKcHandle.DBHandle)
dlDbList.push_back(systemKcHandle);
}
catch(...) {
}
}
context.setDlDbList((uint32)dlDbList.size(), &dlDbList[0]);
}
char timeString[15];
if (mVerifyTime) {
CssmUniformDate(static_cast<CFDateRef>(mVerifyTime)).convertTo(
timeString, sizeof(timeString));
context.time(timeString);
}
StorageManager::KeychainList *holdSearchList = NULL;
if (searchLibs().size() > 0) {
holdSearchList = new StorageManager::KeychainList;
globals().storageManager.getSearchList(*holdSearchList);
}
try {
mTP->certGroupVerify(subjectCertGroup, context, &mTpResult);
mTpReturn = errSecSuccess;
} catch (CommonError &err) {
mTpReturn = err.osStatus();
secdebug("trusteval", "certGroupVerify exception: %d", (int)mTpReturn);
}
mResult = diagnoseOutcome();
if (mTpResult.count() > 0
&& mTpResult[0].form() == CSSM_EVIDENCE_FORM_APPLE_HEADER
&& mTpResult[0].as<CSSM_TP_APPLE_EVIDENCE_HEADER>()->Version == CSSM_TP_APPLE_EVIDENCE_VERSION
&& mTpResult.count() == 3
&& mTpResult[1].form() == CSSM_EVIDENCE_FORM_APPLE_CERTGROUP
&& mTpResult[2].form() == CSSM_EVIDENCE_FORM_APPLE_CERT_INFO) {
evaluateUserTrust(*mTpResult[1].as<CertGroup>(),
mTpResult[2].as<CSSM_TP_APPLE_EVIDENCE_INFO>(), anchors);
} else {
secdebug("trusteval", "unexpected evidence ignored");
}
CFArrayRef fullChain = makeCFArray(convert, mCertChain);
CFDictionaryRef etResult = extendedTrustResults(fullChain, mResult, mTpReturn, isEVCandidate);
mExtendedResult = etResult; if (etResult) {
CFRelease(etResult);
}
if (fullChain) {
CFRelease(fullChain);
}
if (allPolicies) {
if(numRevocationAdded) {
freeAddedRevocationPolicyData(allPolicies, numRevocationAdded, context.allocator);
}
CFRelease(allPolicies);
}
if (holdSearchList) {
delete holdSearchList;
holdSearchList = NULL;
}
}
if (isEVCandidate && mResult == kSecTrustResultRecoverableTrustFailure &&
isRevocationServerMetaError(mTpReturn)) {
evaluate(true);
}
}
static const CSSM_RETURN recoverableErrors[] =
{
CSSMERR_TP_INVALID_ANCHOR_CERT,
CSSMERR_TP_NOT_TRUSTED,
CSSMERR_TP_VERIFICATION_FAILURE,
CSSMERR_TP_VERIFY_ACTION_FAILED,
CSSMERR_TP_INVALID_REQUEST_INPUTS,
CSSMERR_TP_CERT_EXPIRED,
CSSMERR_TP_CERT_NOT_VALID_YET,
CSSMERR_TP_CERTIFICATE_CANT_OPERATE,
CSSMERR_TP_INVALID_CERT_AUTHORITY,
CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK,
CSSMERR_APPLETP_HOSTNAME_MISMATCH,
CSSMERR_TP_VERIFY_ACTION_FAILED,
CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND,
CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS,
CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE,
CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH,
CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS,
CSSMERR_APPLETP_CS_BAD_PATH_LENGTH,
CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE,
CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE,
CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT,
CSSMERR_APPLETP_RS_BAD_CERT_CHAIN_LENGTH,
CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN,
CSSMERR_APPLETP_CRL_NOT_FOUND,
CSSMERR_APPLETP_CRL_SERVER_DOWN,
CSSMERR_APPLETP_CRL_NOT_VALID_YET,
CSSMERR_APPLETP_OCSP_UNAVAILABLE,
CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK,
CSSMERR_APPLETP_NETWORK_FAILURE,
CSSMERR_APPLETP_OCSP_RESP_TRY_LATER,
CSSMERR_APPLETP_IDENTIFIER_MISSING,
};
#define NUM_RECOVERABLE_ERRORS (sizeof(recoverableErrors) / sizeof(CSSM_RETURN))
SecTrustResultType Trust::diagnoseOutcome()
{
StLock<Mutex>_(mMutex);
uint32 chainLength = 0;
if (mTpResult.count() == 3 &&
mTpResult[1].form() == CSSM_EVIDENCE_FORM_APPLE_CERTGROUP &&
mTpResult[2].form() == CSSM_EVIDENCE_FORM_APPLE_CERT_INFO)
{
const CertGroup &chain = *mTpResult[1].as<CertGroup>();
chainLength = chain.count();
}
switch (mTpReturn) {
case errSecSuccess: if (mUsingTrustSettings)
{
if (chainLength)
{
const CSSM_TP_APPLE_EVIDENCE_INFO *infoList = mTpResult[2].as<CSSM_TP_APPLE_EVIDENCE_INFO>();
const TPEvidenceInfo &info = TPEvidenceInfo::overlay(infoList[chainLength-1]);
const CSSM_TP_APPLE_CERT_STATUS resultCertStatus = info.status();
bool hasUserDomainTrust = ((resultCertStatus & CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST) &&
(resultCertStatus & CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER));
bool hasAdminDomainTrust = ((resultCertStatus & CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST) &&
(resultCertStatus & CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN));
if (hasUserDomainTrust || hasAdminDomainTrust)
{
return kSecTrustResultProceed; }
}
}
return kSecTrustResultUnspecified; case CSSMERR_TP_INVALID_CERTIFICATE: return kSecTrustResultFatalTrustFailure;
case CSSMERR_APPLETP_TRUST_SETTING_DENY: return kSecTrustResultDeny;
default:
break;
}
const CSSM_RETURN *errp=recoverableErrors;
for(unsigned dex=0; dex<NUM_RECOVERABLE_ERRORS; dex++, errp++) {
if(*errp == mTpReturn) {
return kSecTrustResultRecoverableTrustFailure;
}
}
return kSecTrustResultOtherError; }
void Trust::evaluateUserTrust(const CertGroup &chain,
const CSSM_TP_APPLE_EVIDENCE_INFO *infoList, CFCopyRef<CFArrayRef> anchors)
{
StLock<Mutex>_(mMutex);
mCertChain.resize(chain.count());
for (uint32 n = 0; n < mCertChain.size(); n++) {
const TPEvidenceInfo &info = TPEvidenceInfo::overlay(infoList[n]);
if (info.recordId()) {
Keychain keychain = keychainByDLDb(info.DlDbHandle);
DbUniqueRecord uniqueId(keychain->database()->newDbUniqueRecord());
secdebug("trusteval", "evidence %lu from keychain \"%s\"", (unsigned long)n, keychain->name());
*static_cast<CSSM_DB_UNIQUE_RECORD_PTR *>(uniqueId) = info.UniqueRecord;
uniqueId->activate(); Item ii = keychain->item(CSSM_DL_DB_RECORD_X509_CERTIFICATE, uniqueId);
Certificate* cert = dynamic_cast<Certificate*>(ii.get());
if (cert == NULL) {
CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
}
mCertChain[n] = cert;
} else if (info.status(CSSM_CERT_STATUS_IS_IN_INPUT_CERTS)) {
secdebug("trusteval", "evidence %lu from input cert %lu", (unsigned long)n, (unsigned long)info.index());
assert(info.index() < uint32(CFArrayGetCount(mCerts)));
SecCertificateRef cert = SecCertificateRef(CFArrayGetValueAtIndex(mCerts,
info.index()));
mCertChain[n] = Certificate::required(cert);
} else if (info.status(CSSM_CERT_STATUS_IS_IN_ANCHORS)) {
secdebug("trusteval", "evidence %lu from anchor cert %lu", (unsigned long)n, (unsigned long)info.index());
assert(info.index() < uint32(CFArrayGetCount(anchors)));
SecCertificateRef cert = SecCertificateRef(CFArrayGetValueAtIndex(anchors,
info.index()));
mCertChain[n] = Certificate::required(cert);
} else {
secdebug("trusteval", "evidence %lu from unknown source", (unsigned long)n);
mCertChain[n] =
new Certificate(chain.blobCerts()[n],
CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_BER);
}
}
TrustStore &store = gStore();
SecPointer<Policy> policy = (CFArrayGetCount(mPolicies)) ?
Policy::required(SecPolicyRef(CFArrayGetValueAtIndex(mPolicies, 0))) : NULL;
for (mResultIndex = 0;
mResult == kSecTrustResultUnspecified && mResultIndex < mCertChain.size() && policy;
mResultIndex++) {
if (!mCertChain[mResultIndex]) {
assert(false);
continue;
}
mResult = store.find(mCertChain[mResultIndex], policy, searchLibs());
secdebug("trusteval", "trustResult=%d from cert %d", (int)mResult, (int)mResultIndex);
}
}
void Trust::releaseTPEvidence(TPVerifyResult &result, Allocator &allocator)
{
if (result.count() > 0) { if (result[0].form() == CSSM_EVIDENCE_FORM_APPLE_HEADER) {
if (result[0].as<CSSM_TP_APPLE_EVIDENCE_HEADER>()->Version == CSSM_TP_APPLE_EVIDENCE_VERSION
&& result.count() == 3
&& result[1].form() == CSSM_EVIDENCE_FORM_APPLE_CERTGROUP
&& result[2].form() == CSSM_EVIDENCE_FORM_APPLE_CERT_INFO) {
CertGroup& certs = *result[1].as<CertGroup>();
CSSM_TP_APPLE_EVIDENCE_INFO *evidence = result[2].as<CSSM_TP_APPLE_EVIDENCE_INFO>();
uint32 count = certs.count();
allocator.free(result[0].data()); certs.destroy(allocator); allocator.free(result[1].data()); for (uint32 n = 0; n < count; n++)
allocator.free(evidence[n].StatusCodes);
allocator.free(result[2].data()); } else {
secdebug("trusteval", "unrecognized Apple TP evidence format");
}
} else {
secdebug("trusteval", "destroying unknown TP evidence format");
for (uint32 n = 0; n < result.count(); n++)
{
allocator.free(result[n].data());
}
}
allocator.free (result.Evidence);
}
}
void Trust::clearResults()
{
StLock<Mutex>_(mMutex);
if (mResult != kSecTrustResultInvalid) {
releaseTPEvidence(mTpResult, mTP.allocator());
mResult = kSecTrustResultInvalid;
}
}
void Trust::buildEvidence(CFArrayRef &certChain, TPEvidenceInfo * &statusChain)
{
StLock<Mutex>_(mMutex);
if (mResult == kSecTrustResultInvalid)
MacOSError::throwMe(errSecTrustNotAvailable);
certChain = mEvidenceReturned =
makeCFArray(convert, mCertChain);
if(mTpResult.count() >= 3) {
statusChain = mTpResult[2].as<TPEvidenceInfo>();
}
else {
statusChain = NULL;
}
}
void Trust::extendedResult(CFDictionaryRef &result)
{
if (mResult == kSecTrustResultInvalid)
MacOSError::throwMe(errSecTrustNotAvailable);
if (mExtendedResult)
CFRetain(mExtendedResult); result = mExtendedResult;
}
CFArrayRef Trust::properties()
{
StLock<Mutex>_(mMutex);
CFMutableArrayRef properties = CFArrayCreateMutable(NULL, 0,
&kCFTypeArrayCallBacks);
if (mResult == kSecTrustResultInvalid) return properties;
for (uint32 idx=0; idx < mCertChain.size(); idx++) {
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (dict) {
CFStringRef title = NULL;
mCertChain[idx]->inferLabel(false, &title);
if (title) {
CFDictionarySetValue(dict, (const void *)kSecPropertyTypeTitle, (const void *)title);
CFRelease(title);
}
if (idx == 0 && mTpReturn != errSecSuccess) {
CFStringRef error = SecCopyErrorMessageString(mTpReturn, NULL);
if (error) {
CFDictionarySetValue(dict, (const void *)kSecPropertyTypeError, (const void *)error);
CFRelease(error);
}
}
CFArrayAppendValue(properties, (const void *)dict);
CFRelease(dict);
}
}
return properties;
}
CFDictionaryRef Trust::results()
{
StLock<Mutex>_(mMutex);
CFMutableDictionaryRef results = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFNumberRef numValue = CFNumberCreate(NULL, kCFNumberSInt32Type, &mResult);
if (numValue) {
CFDictionarySetValue(results, (const void *)kSecTrustResultValue, (const void *)numValue);
CFRelease(numValue);
}
if (mResult == kSecTrustResultInvalid || !mExtendedResult)
return results;
CFTypeRef evaluationDate;
if (CFDictionaryGetValueIfPresent(mExtendedResult, kSecTrustEvaluationDate, &evaluationDate))
CFDictionarySetValue(results, (const void *)kSecTrustEvaluationDate, (const void *)evaluationDate);
CFTypeRef organizationName;
if (CFDictionaryGetValueIfPresent(mExtendedResult, kSecEVOrganizationName, &organizationName)) {
CFDictionarySetValue(results, (const void *)kSecTrustOrganizationName, (const void *)organizationName);
CFDictionarySetValue(results, (const void *)kSecTrustExtendedValidation, (const void *)kCFBooleanTrue);
}
CFTypeRef expirationDate;
if (CFDictionaryGetValueIfPresent(mExtendedResult, kSecTrustExpirationDate, &expirationDate)) {
CFDictionarySetValue(results, (const void *)kSecTrustRevocationValidUntilDate, (const void *)expirationDate);
CFDictionarySetValue(results, (const void *)kSecTrustRevocationChecked, (const void *)kCFBooleanTrue);
}
return results;
}
static
bool Compare_CSSM_DL_DB_HANDLE(const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2)
{
return (h1.DLHandle == h2.DLHandle && h1.DBHandle == h2.DBHandle);
}
Keychain Trust::keychainByDLDb(const CSSM_DL_DB_HANDLE &handle)
{
StLock<Mutex>_(mMutex);
StorageManager::KeychainList& list = searchLibs();
for (StorageManager::KeychainList::const_iterator it = list.begin();
it != list.end(); it++)
{
try
{
if (Compare_CSSM_DL_DB_HANDLE((*it)->database()->handle(), handle))
return *it;
}
catch (...)
{
}
}
if(mUsingTrustSettings) {
try {
if(Compare_CSSM_DL_DB_HANDLE(trustKeychains().rootStoreHandle(), handle)) {
return trustKeychains().rootStore();
}
if(Compare_CSSM_DL_DB_HANDLE(trustKeychains().systemKcHandle(), handle)) {
return trustKeychains().systemKc();
}
}
catch(...) {
}
}
MacOSError::throwMe(errSecInternal);
}