]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_keychain/lib/Trust.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_keychain / lib / Trust.cpp
diff --git a/Security/libsecurity_keychain/lib/Trust.cpp b/Security/libsecurity_keychain/lib/Trust.cpp
deleted file mode 100644 (file)
index dad8891..0000000
+++ /dev/null
@@ -1,915 +0,0 @@
-/*
- * Copyright (c) 2002-2015 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-//
-// Trust.cpp
-//
-#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;
-
-//
-// Translate CFDataRef to CssmData. The output shares the input's buffer.
-//
-static inline CssmData cfData(CFDataRef data)
-{
-    return CssmData(const_cast<UInt8 *>(CFDataGetBytePtr(data)),
-        CFDataGetLength(data));
-}
-
-//
-// Convert a SecPointer to a CF object.
-//
-static SecCertificateRef
-convert(const SecPointer<Certificate> &certificate)
-{
-       return *certificate;
-}
-
-//
-// For now, we use a global TrustStore
-//
-ModuleNexus<TrustStore> Trust::gStore;
-
-#pragma mark -- TrustKeychains --
-
-static const CSSM_DL_DB_HANDLE nullCSSMDLDBHandle = {0,};
-//
-// TrustKeychains maintains a global reference to standard system keychains,
-// to avoid having them be opened anew for each Trust instance.
-//
-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;
-};
-
-//
-// Singleton maintaining open references to standard system keychains,
-// to avoid having them be opened anew every time SecTrust is used.
-//
-
-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()) // in server mode?  Don't make a keychain for the root store
-       {
-               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 --
-//
-// Construct a Trust object with suitable defaults.
-// Use setters for additional arguments before calling evaluate().
-//
-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));
-       }
-}
-
-
-//
-// Clean up a Trust object
-//
-Trust::~Trust()
-{
-       clearResults();
-       if (mSearchLibs) {
-               delete mSearchLibs;
-       }
-
-    mPolicies = NULL;
-}
-
-
-//
-// Get searchLibs (a vector of Keychain objects);
-// normally initialized to default search list
-//
-StorageManager::KeychainList& Trust::searchLibs(bool init)
-{
-       if (!mSearchLibs) {
-               mSearchLibs = new StorageManager::KeychainList;
-               if (init) {
-                       globals().storageManager.getSearchList(*mSearchLibs);
-               }
-       }
-       return *mSearchLibs;
-}
-
-
-//
-// Set searchLibs to provided vector of Keychain objects
-//
-void Trust::searchLibs(StorageManager::KeychainList &libs)
-{
-       searchLibs(false) = libs;
-       mSearchLibsSet = true;
-}
-
-
-//
-// Retrieve the last TP evaluation result, if any
-//
-CSSM_TP_VERIFY_CONTEXT_RESULT_PTR Trust::cssmResult()
-{
-       if (mResult == kSecTrustResultInvalid)
-               MacOSError::throwMe(errSecTrustNotAvailable);
-    return &mTpResult;
-}
-
-
-// SecCertificateRef -> CssmData
-static
-CssmData cfCertificateData(SecCertificateRef certificate)
-{
-    return Certificate::required(certificate)->data();
-}
-
-// SecPolicyRef -> CssmField (CFDataRef/NULL or oid/value of a SecPolicy)
-static
-CssmField cfField(SecPolicyRef item)
-{
-       SecPointer<Policy> policy = Policy::required(SecPolicyRef(item));
-    return CssmField(policy->oid(), policy->value());
-}
-
-// SecKeychain -> CssmDlDbHandle
-#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
-
-//
-// Here's the big "E" - evaluation.
-// We build most of the CSSM-layer input structures dynamically right here;
-// they will auto-destruct when we're done. The output structures are kept
-// around (in our data members) for later analysis.
-// Note that evaluate() can be called repeatedly, so we must be careful to
-// dispose of prior results.
-//
-void Trust::evaluate(bool disableEV)
-{
-       bool isEVCandidate=false;
-       // begin evaluation block with stack-based mutex
-       {
-       StLock<Mutex>_(mMutex);
-       // if we have evaluated before, release prior result
-       clearResults();
-
-       // determine whether the leaf certificate is an EV candidate
-       CFArrayRef allowedAnchors = NULL;
-       if (!disableEV) {
-               allowedAnchors = allowedEVRootsForLeafCertificate(mCerts);
-               isEVCandidate = (allowedAnchors != NULL);
-       }
-       CFArrayRef filteredCerts = NULL;
-       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);
-               }
-       }
-       // retain these certs as long as we potentially could have results involving them
-       // (note that assignment to a CFRef type performs an implicit retain)
-       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
-       }
-
-       // set default search list from user's default, if caller did not explicitly supply it
-       if(!mSearchLibsSet) {
-               globals().storageManager.getSearchList(searchLibs());
-               mSearchLibsSet = true;
-       }
-
-    // build the target cert group
-    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;
-
-    // build a TP_VERIFY_CONTEXT, a veritable nightmare of a data structure
-    TPBuildVerifyContext context(mAction);
-
-       /*
-        * Guarantee *some* action data...
-        * NOTE this only works with the local X509 TP. When this module can deal
-        * with other TPs, this must be revisited.
-        */
-       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;
-       }
-
-       bool hasSSLPolicy = policySpecified(mPolicies, CSSMOID_APPLE_TP_SSL);
-       bool hasEAPPolicy = policySpecified(mPolicies, CSSMOID_APPLE_TP_EAP);
-
-       if (!mAnchors) {
-               // always check trust settings if caller did not provide explicit trust anchors
-               actionDataP->ActionFlags |= CSSM_TP_ACTION_TRUST_SETTINGS;
-       }
-
-       if (mNetworkPolicy == useNetworkDefault) {
-               if (hasSSLPolicy) {
-                       // enable network cert fetch for SSL only: <rdar://7422356>
-                       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);
-
-       if (policySpecified(mPolicies, CSSMOID_APPLE_TP_ESCROW_SERVICE)) {
-               // ignore expiration dates, per rdar://21943474
-               actionDataP->ActionFlags |= (CSSM_TP_ACTION_ALLOW_EXPIRED |
-                               CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT);
-       }
-
-    /*
-        * Policies (one at least, please).
-        * For revocation policies, see if any have been explicitly specified...
-        */
-       CFMutableArrayRef allPolicies = NULL;
-       uint32 numRevocationAdded = 0;
-       bool requirePerCert = (actionDataP->ActionFlags & CSSM_TP_ACTION_REQUIRE_REV_PER_CERT);
-
-       // If a new unified revocation policy was explicitly specified,
-       // convert into old-style individual OCSP and CRL policies.
-       // Note that the caller could configure revocation policy options
-       // to explicitly disable both methods, so 0 policies might be added,
-       // in which case we must no longer consider the cert an EV candidate.
-
-       allPolicies = convertRevocationPolicy(numRevocationAdded, context.allocator);
-       if (allPolicies) {
-               // caller has explicitly set the revocation policy they want to use
-               secdebug("evTrust", "Trust::evaluate() using explicit revocation policy (%d)",
-                       numRevocationAdded);
-               if (numRevocationAdded == 0)
-                       isEVCandidate = false;
-       }
-       else if (mAnchors && (CFArrayGetCount(mAnchors)==0) && (searchLibs().size()==0)) {
-               // caller explicitly provided empty anchors and no keychain list,
-               // and did not explicitly specify the revocation policy;
-               // override global revocation check setting for this evaluation
-               secdebug("evTrust", "Trust::evaluate() has empty anchors and no keychains");
-               allPolicies = NULL; // use only mPolicies
-               isEVCandidate = false;
-       }
-       else if (isEVCandidate || requirePerCert) {
-               // force revocation checking for this evaluation
-               secdebug("evTrust", "Trust::evaluate() forcing OCSP/CRL revocation check");
-               allPolicies = forceRevocationPolicies(true, requirePerCert,
-                       numRevocationAdded, context.allocator, requirePerCert);
-       }
-       else if(!(revocationPolicySpecified(mPolicies))) {
-               // none specified in mPolicies; try preferences
-               allPolicies = addPreferenceRevocationPolicies(!(hasSSLPolicy || hasEAPPolicy),
-                       !(hasSSLPolicy || hasEAPPolicy), numRevocationAdded, context.allocator);
-       }
-       if (allPolicies == NULL) {
-               // use mPolicies; no revocation checking will be performed
-               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
-       // error exit here if empty policies are not supported
-    if (policies.empty())
-        MacOSError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS);
-#endif
-    context.setPolicies(policies, policies);
-
-       // anchor certificates (if caller provides them, or if cert requires EV)
-       CFCopyRef<CFArrayRef> anchors(mAllowedAnchors);
-       CFToVector<CssmData, SecCertificateRef, cfCertificateData> roots(anchors);
-       if (!anchors) {
-               // no anchor certificates were provided;
-               // built-in anchors will be trusted unless explicitly disabled.
-               mUsingTrustSettings = (mAnchorPolicy < useAnchorsOnly);
-               secdebug("userTrust", "Trust::evaluate() %s",
-                                (mUsingTrustSettings) ? "using UserTrust" : "has no trusted anchors!");
-    }
-       else {
-               // anchor certificates were provided;
-               // built-in anchors will NOT also be trusted unless explicitly enabled.
-               mUsingTrustSettings = (mAnchorPolicy == useAnchorsAndBuiltIns);
-               secdebug("userTrust", "Trust::evaluate() using %s %s anchors",
-                                (mUsingTrustSettings) ? "UserTrust AND" : "only",
-                                (isEVCandidate) ? "EV" : "caller");
-               context.anchors(roots, roots);
-       }
-
-       // dlDbList (keychain list)
-       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
-                       {
-                               // For the purpose of looking up intermediate certificates to establish trust,
-                               // do not include the network-based LDAP or DotMac pseudo-keychains. (The only
-                               // time the network should be consulted for certificates is if there is an AIA
-                               // extension with a specific URL, which will be handled by the TP code.)
-                               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; // don't add to dlDbList
-                                               }
-                                       }
-                               }
-                               // This DB is OK to search for intermediate certificates.
-                               dlDbList.push_back(dldbHandle);
-                       }
-                       catch (...)
-                       {
-                       }
-               }
-               if(mUsingTrustSettings) {
-                       /* Append system anchors for use with Trust Settings */
-                       try {
-                CSSM_DL_DB_HANDLE rootStoreHandle = trustKeychains().rootStoreHandle();
-                if (rootStoreHandle.DBHandle)
-                    dlDbList.push_back(rootStoreHandle);
-                               actionDataP->ActionFlags |= CSSM_TP_ACTION_TRUST_SETTINGS;
-                       }
-                       catch (...) {
-                               // no root store or system keychain; don't use trust settings but continue
-                               mUsingTrustSettings = false;
-                       }
-                       try {
-                CSSM_DL_DB_HANDLE systemKcHandle = trustKeychains().systemKcHandle();
-                if (systemKcHandle.DBHandle)
-                    dlDbList.push_back(systemKcHandle);
-                       }
-                       catch(...) {
-                               /* Oh well, at least we got the root store DB */
-                       }
-               }
-               context.setDlDbList((uint32)dlDbList.size(), &dlDbList[0]);
-       }
-
-    // verification time
-    char timeString[15];
-    if (mVerifyTime) {
-        CssmUniformDate(static_cast<CFDateRef>(mVerifyTime)).convertTo(
-                       timeString, sizeof(timeString));
-        context.time(timeString);
-    }
-
-       // to avoid keychain open/close thrashing, hold a copy of the search list
-       StorageManager::KeychainList *holdSearchList = NULL;
-       if (searchLibs().size() > 0) {
-               holdSearchList = new StorageManager::KeychainList;
-               globals().storageManager.getSearchList(*holdSearchList);
-       }
-
-    // Go TP!
-    try {
-        mTP->certGroupVerify(subjectCertGroup, context, &mTpResult);
-        mTpReturn = errSecSuccess;
-    } catch (CommonError &err) {
-        mTpReturn = err.osStatus();
-        secdebug("trusteval", "certGroupVerify exception: %d", (int)mTpReturn);
-    }
-    mResult = diagnoseOutcome();
-
-    // see if we can use the evidence
-    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 {
-        // unexpected evidence information. Can't use it
-        secdebug("trusteval", "unexpected evidence ignored");
-    }
-
-       /* do post-processing for the evaluated certificate chain */
-       CFArrayRef fullChain = makeCFArray(convert, mCertChain);
-       CFDictionaryRef etResult = extendedTrustResults(fullChain, mResult, mTpReturn, isEVCandidate);
-       mExtendedResult = etResult; // assignment to CFRef type is an implicit retain
-       if (etResult) {
-               CFRelease(etResult);
-       }
-       if (fullChain) {
-               CFRelease(fullChain);
-       }
-
-       if (allPolicies) {
-               /* clean up revocation policies we created implicitly */
-               if(numRevocationAdded) {
-                       freeAddedRevocationPolicyData(allPolicies, numRevocationAdded, context.allocator);
-               }
-               CFRelease(allPolicies);
-       }
-
-       if (holdSearchList) {
-               delete holdSearchList;
-               holdSearchList = NULL;
-       }
-       } // end evaluation block with mutex; releases all temporary allocations in this scope
-
-
-       if (isEVCandidate && mResult == kSecTrustResultRecoverableTrustFailure &&
-               (mTpReturn == CSSMERR_TP_NOT_TRUSTED || isRevocationServerMetaError(mTpReturn))) {
-               // re-do the evaluation, this time disabling EV
-               evaluate(true);
-       }
-}
-
-// CSSM_RETURN values that map to kSecTrustResultRecoverableTrustFailure.
-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))
-
-//
-// Classify the TP outcome in terms of a SecTrustResultType
-//
-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:                                                                        // peachy
-               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;          // explicitly allowed
-                               }
-                       }
-               }
-               return kSecTrustResultUnspecified;              // cert evaluates OK
-    case CSSMERR_TP_INVALID_CERTIFICATE:               // bad certificate
-        return kSecTrustResultFatalTrustFailure;
-       case CSSMERR_APPLETP_TRUST_SETTING_DENY:        // authoritative denial
-               return kSecTrustResultDeny;
-    default:
-               break;
-    }
-
-       // a known list of returns maps to kSecTrustResultRecoverableTrustFailure
-       const CSSM_RETURN *errp=recoverableErrors;
-       for(unsigned dex=0; dex<NUM_RECOVERABLE_ERRORS; dex++, errp++) {
-               if(*errp == mTpReturn) {
-                       return kSecTrustResultRecoverableTrustFailure;
-               }
-       }
-       return kSecTrustResultOtherError;                       // unknown
-}
-
-
-//
-// Assuming a good evidence chain, check user trust
-// settings and set mResult accordingly.
-//
-void Trust::evaluateUserTrust(const CertGroup &chain,
-    const CSSM_TP_APPLE_EVIDENCE_INFO *infoList, CFCopyRef<CFArrayRef> anchors)
-{
-       StLock<Mutex>_(mMutex);
-    // extract cert chain as Certificate objects
-    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(); // transfers ownership
-                       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 {
-            // unknown source; make a new Certificate for it
-            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);
-        }
-    }
-
-    // now walk the chain, leaf-to-root, checking for user settings
-       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);
-       }
-}
-
-
-//
-// Release TP evidence information.
-// This information is severely under-defined by CSSM, so we proceed
-// as follows:
-//  (a) If the evidence matches an Apple-defined pattern, use specific
-//      knowledge of that format.
-//  (b) Otherwise, assume that the void * are flat blocks of memory.
-//
-void Trust::releaseTPEvidence(TPVerifyResult &result, Allocator &allocator)
-{
-       if (result.count() > 0) {       // something to do
-               if (result[0].form() == CSSM_EVIDENCE_FORM_APPLE_HEADER) {
-                       // Apple defined evidence form -- use intimate knowledge
-                       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) {
-                               // proper format
-                               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());       // just a struct
-                               certs.destroy(allocator);               // certgroup contents
-                               allocator.free(result[1].data());       // the CertGroup itself
-                               for (uint32 n = 0; n < count; n++)
-                                       allocator.free(evidence[n].StatusCodes);
-                               allocator.free(result[2].data());       // array of (flat) info structs
-                       } else {
-                               secdebug("trusteval", "unrecognized Apple TP evidence format");
-                               // drop it -- better leak than kill
-                       }
-               } else {
-                       // unknown format -- blindly assume flat blobs
-                       secdebug("trusteval", "destroying unknown TP evidence format");
-                       for (uint32 n = 0; n < result.count(); n++)
-                       {
-                               allocator.free(result[n].data());
-                       }
-               }
-
-               allocator.free (result.Evidence);
-       }
-}
-
-
-//
-// Clear evaluation results unless state is initial (invalid)
-//
-void Trust::clearResults()
-{
-       StLock<Mutex>_(mMutex);
-       if (mResult != kSecTrustResultInvalid) {
-               releaseTPEvidence(mTpResult, mTP.allocator());
-               mResult = kSecTrustResultInvalid;
-       }
-}
-
-
-//
-// Build evidence information
-//
-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;
-       }
-}
-
-
-//
-// Return extended result dictionary
-//
-void Trust::extendedResult(CFDictionaryRef &result)
-{
-       if (mResult == kSecTrustResultInvalid)
-               MacOSError::throwMe(errSecTrustNotAvailable);
-       if (mExtendedResult)
-               CFRetain(mExtendedResult); // retain before handing out to caller
-    result = mExtendedResult;
-}
-
-
-//
-// Return properties array (a CFDictionaryRef for each certificate in chain)
-//
-CFArrayRef Trust::properties()
-{
-       // Builds and returns an array which the caller must release.
-       StLock<Mutex>_(mMutex);
-       CFMutableArrayRef properties = CFArrayCreateMutable(NULL, 0,
-               &kCFTypeArrayCallBacks);
-       if (mResult == kSecTrustResultInvalid) // chain not built or evaluated
-               return properties;
-
-       // Walk the chain from leaf to anchor, building properties dictionaries
-       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;
-}
-
-//
-// Return dictionary of evaluation results
-//
-CFDictionaryRef Trust::results()
-{
-       // Builds and returns a dictionary which the caller must release.
-       StLock<Mutex>_(mMutex);
-       CFMutableDictionaryRef results = CFDictionaryCreateMutable(NULL, 0,
-                       &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
-       // kSecTrustResultValue
-       CFNumberRef numValue = CFNumberCreate(NULL, kCFNumberSInt32Type, &mResult);
-       if (numValue) {
-               CFDictionarySetValue(results, (const void *)kSecTrustResultValue, (const void *)numValue);
-               CFRelease(numValue);
-       }
-       if (mResult == kSecTrustResultInvalid || !mExtendedResult)
-               return results; // we have nothing more to add
-
-       // kSecTrustEvaluationDate
-       CFTypeRef evaluationDate;
-       if (CFDictionaryGetValueIfPresent(mExtendedResult, kSecTrustEvaluationDate, &evaluationDate))
-               CFDictionarySetValue(results, (const void *)kSecTrustEvaluationDate, (const void *)evaluationDate);
-
-       // kSecTrustExtendedValidation, kSecTrustOrganizationName
-       CFTypeRef organizationName;
-       if (CFDictionaryGetValueIfPresent(mExtendedResult, kSecEVOrganizationName, &organizationName)) {
-               CFDictionarySetValue(results, (const void *)kSecTrustOrganizationName, (const void *)organizationName);
-               CFDictionarySetValue(results, (const void *)kSecTrustExtendedValidation, (const void *)kCFBooleanTrue);
-       }
-
-       // kSecTrustRevocationChecked, kSecTrustRevocationValidUntilDate
-       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;
-}
-
-
-
-//* ===========================================================================
-//* We need a way to compare two CSSM_DL_DB_HANDLEs WITHOUT using a operator
-//* overload
-//* ===========================================================================
-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);
-}
-
-
-
-//
-// Given a DL_DB_HANDLE, locate the Keychain object (from the search list)
-//
-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(...) {
-                       /* one of those is missing; proceed */
-               }
-       }
-
-       // could not find in search list - internal error
-
-       // we now throw an error here rather than assert and silently fail.  That way our application won't crash...
-       MacOSError::throwMe(errSecInternal);
-}