]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_keychain/lib/SecTrust.cpp
Security-58286.70.7.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecTrust.cpp
index ae0d4c93a0f771bea4521973dd56ecdd44bd6a67..a710f92a1345b8cbacf81b438802478255c4839f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2015 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2002-2017 Apple Inc. All Rights Reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
  * @APPLE_LICENSE_HEADER_END@
  */
 
+#include <libDER/oids.h>
+#include <Security/oidscert.h>
+
 #include "SecTrust.h"
 #include "SecTrustPriv.h"
 #include "Trust.h"
-#include <security_keychain/SecTrustSettingsPriv.h>
 #include "SecBase.h"
 #include "SecBridge.h"
 #include "SecInternal.h"
-#include "SecInternalP.h"
 #include "SecTrustSettings.h"
+#include "SecTrustSettingsPriv.h"
+#include "SecTrustStatusCodes.h"
 #include "SecCertificatePriv.h"
-#include "SecCertificateP.h"
-#include "SecCertificatePrivP.h"
 #include "SecPolicyPriv.h"
 #include <security_utilities/cfutilities.h>
 #include <security_utilities/cfmunge.h>
 #include <syslog.h>
 
 // forward declarations
-#if !SECTRUST_OSX
-CFArrayRef SecTrustCopyDetails(SecTrustRef trust);
-static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix);
-static void SecTrustCheckException(const void *key, const void *value, void *context);
-#endif
+CFArrayRef SecTrustCopyInputCertificates(SecTrustRef trust);
+CFArrayRef SecTrustCopyInputAnchors(SecTrustRef trust);
+CFArrayRef SecTrustCopyConstructedChain(SecTrustRef trust);
+static CSSM_TP_APPLE_EVIDENCE_INFO * SecTrustGetEvidenceInfo(SecTrustRef trust);
 
 typedef struct SecTrustCheckExceptionContext {
        CFDictionaryRef exception;
@@ -61,143 +61,15 @@ const CFStringRef kSecTrustRevocationReason         = CFSTR("TrustRevocationReas
 const CFStringRef kSecTrustRevocationValidUntilDate = CFSTR("TrustExpirationDate");
 const CFStringRef kSecTrustResultDetails            = CFSTR("TrustResultDetails");
 
-//
-// CF boilerplate
-//
-#if !SECTRUST_OSX
-CFTypeID SecTrustGetTypeID(void)
-{
-       BEGIN_SECAPI
-
-       return gTypes().Trust.typeID;
-
-       END_SECAPI1(_kCFRuntimeNotATypeID)
-}
-#endif
-
 //
 // Sec* API bridge functions
 //
-#if !SECTRUST_OSX
-OSStatus SecTrustCreateWithCertificates(
-       CFTypeRef certificates,
-       CFTypeRef policies,
-       SecTrustRef *trustRef)
-{
-       BEGIN_SECAPI
-       Required(trustRef);
-       *trustRef = (new Trust(certificates, policies))->handle();
-       END_SECAPI
-}
-#endif
-
-#if !SECTRUST_OSX
-OSStatus
-SecTrustSetPolicies(SecTrustRef trustRef, CFTypeRef policies)
-{
-       BEGIN_SECAPI
-       Trust::required(trustRef)->policies(policies);
-       END_SECAPI
-}
-#endif
-
-/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
-OSStatus
-SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options)
-{
-#if !SECTRUST_OSX
-       BEGIN_SECAPI
-       CSSM_APPLE_TP_ACTION_DATA actionData = {
-               CSSM_APPLE_TP_ACTION_VERSION,
-               (CSSM_APPLE_TP_ACTION_FLAGS)options
-       };
-       Trust *trust = Trust::required(trustRef);
-       CFDataRef actionDataRef = CFDataCreate(NULL,
-               (const UInt8 *)&actionData,
-               (CFIndex)sizeof(CSSM_APPLE_TP_ACTION_DATA));
-       trust->action(CSSM_TP_ACTION_DEFAULT);
-       trust->actionData(actionDataRef);
-       if (actionDataRef) CFRelease(actionDataRef);
-       END_SECAPI
-#else
-       /* bridge to support API functionality for legacy callers */
-       OSStatus status = errSecSuccess;
-#if 1
-#warning STU: <rdar://21328005>
-//%%% need to ensure that the exception covers only the requested options
-#else
-       CFArrayRef details = SecTrustGetDetails(trustRef); // NOTE: performs the evaluation if not done already
-       CFIndex pathLength = details ? CFArrayGetCount(details) : 0;
-       CFIndex ix;
-       for (ix = 0; ix < pathLength; ++ix) {
-               CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
-               CFIndex detailCount = CFDictionaryGetCount(detail);
-               if (detailCount > 0) {
-                       // see if we can ignore this error
-                       syslog(LOG_ERR, "SecTrustSetOptions: examining detail dictionary items at ix %ld", (long)ix);
-                       CFShow(detail);
-               }
-       }
-       syslog(LOG_ERR, "SecTrustSetOptions: creating trust exception");
-#endif
-       CFDataRef exceptions = SecTrustCopyExceptions(trustRef);
-       if (exceptions) {
-               SecTrustSetExceptions(trustRef, exceptions);
-               CFRelease(exceptions);
-       }
-
-
-#if SECTRUST_DEPRECATION_WARNINGS
-       bool displayModifyMsg = false;
-       bool displayNetworkMsg = false;
-       bool displayPolicyMsg = false;
-       const char *baseMsg = "WARNING: SecTrustSetOptions called with";
-       const char *modifyMsg = "Use SecTrustSetExceptions and SecTrustCopyExceptions to modify default trust results.";
-       const char *networkMsg = "Use SecTrustSetNetworkFetchAllowed to specify whether missing certificates can be fetched from the network.";
-       const char *policyMsg = "Use SecPolicyCreateRevocation to specify revocation policy requirements.";
-
-       if (options & kSecTrustOptionAllowExpired) {
-               syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionAllowExpired");
-               displayModifyMsg = true;
-       }
-       if (options & kSecTrustOptionAllowExpiredRoot) {
-               syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionAllowExpiredRoot");
-               displayModifyMsg = true;
-       }
-       if (options & kSecTrustOptionFetchIssuerFromNet) {
-               syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionFetchIssuerFromNet");
-               displayNetworkMsg = true;
-       }
-       if (options & kSecTrustOptionRequireRevPerCert) {
-               syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionRequireRevPerCert");
-               displayPolicyMsg = true;
-       }
-       if (displayModifyMsg || displayNetworkMsg || displayPolicyMsg) {
-               syslog(LOG_ERR, "%s %s %s",
-                       (displayModifyMsg) ? modifyMsg : "",
-                       (displayNetworkMsg) ? networkMsg : "",
-                       (displayPolicyMsg) ? policyMsg : "");
-       }
-#endif
-
-       return status;
-
-#endif
-}
-
 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
 OSStatus SecTrustSetParameters(
     SecTrustRef trustRef,
     CSSM_TP_ACTION action,
     CFDataRef actionData)
 {
-#if !SECTRUST_OSX
-    BEGIN_SECAPI
-    Trust *trust = Trust::required(trustRef);
-    trust->action(action);
-    trust->actionData(actionData);
-    END_SECAPI
-#else
        /* bridge to support API functionality for legacy callers */
        OSStatus status;
        CSSM_APPLE_TP_ACTION_FLAGS actionFlags = 0;
@@ -216,158 +88,18 @@ OSStatus SecTrustSetParameters(
 #endif
 
        return status;
-
-#endif
 }
 
-#if !SECTRUST_OSX
-OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, CFArrayRef anchorCertificates)
-{
-    BEGIN_SECAPI
-    Trust::required(trust)->anchors(anchorCertificates);
-    END_SECAPI
-}
-#endif
-
-#if !SECTRUST_OSX
-OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, Boolean anchorCertificatesOnly)
-{
-    BEGIN_SECAPI
-    Trust::AnchorPolicy policy = (anchorCertificatesOnly) ? Trust::useAnchorsOnly : Trust::useAnchorsAndBuiltIns;
-    Trust::required(trust)->anchorPolicy(policy);
-    END_SECAPI
-}
-#endif
-
 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
 OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray)
 {
-#if !SECTRUST_OSX
-       BEGIN_SECAPI
-               StorageManager::KeychainList keychains;
-       // avoid unnecessary global initializations if an empty array is passed in
-       if (!( (keychainOrArray != NULL) &&
-                               (CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) &&
-                               (CFArrayGetCount((CFArrayRef)keychainOrArray) == 0) )) {
-               globals().storageManager.optionalSearchList(keychainOrArray, keychains);
-       }
-       Trust::required(trust)->searchLibs(keychains);
-       END_SECAPI
-#else
        /* this function is currently unsupported in unified SecTrust */
     // TODO: pull all certs out of the specified keychains for the evaluation?
 #if SECTRUST_DEPRECATION_WARNINGS
        syslog(LOG_ERR, "WARNING: SecTrustSetKeychains does nothing in 10.11. Use SecTrustSetAnchorCertificates{Only} to provide anchors.");
 #endif
        return errSecSuccess;
-#endif
-}
-
-#if !SECTRUST_OSX
-OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate)
-{
-    BEGIN_SECAPI
-    Trust::required(trust)->time(verifyDate);
-    END_SECAPI
-}
-#endif
-
-#if !SECTRUST_OSX
-CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust)
-{
-       CFAbsoluteTime verifyTime = 0;
-       OSStatus __secapiresult = errSecSuccess;
-       try {
-               CFRef<CFDateRef> verifyDate = Trust::required(trust)->time();
-               verifyTime = CFDateGetAbsoluteTime(verifyDate);
-       }
-       catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
-       catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
-       catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
-       catch (...) { __secapiresult=errSecInternalComponent; }
-       return verifyTime;
-}
-#endif
-
-
-
-#if !SECTRUST_OSX
-OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *resultP)
-{
-       SecTrustResultType trustResult = kSecTrustResultInvalid;
-       CFArrayRef exceptions = NULL;
-       OSStatus __secapiresult = errSecSuccess;
-       try {
-               Trust *trustObj = Trust::required(trust);
-               trustObj->evaluate();
-               trustResult = trustObj->result();
-               exceptions = trustObj->exceptions();
-       }
-       catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
-       catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
-       catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
-       catch (...) { __secapiresult=errSecInternalComponent; }
-
-       if (__secapiresult) {
-               return __secapiresult;
-       }
-
-       /* post-process trust result based on exceptions */
-       if (trustResult == kSecTrustResultUnspecified) {
-               /* If leaf is in exceptions -> proceed, otherwise unspecified. */
-               if (SecTrustGetExceptionForCertificateAtIndex(trust, 0))
-                       trustResult = kSecTrustResultProceed;
-       }
-       else if (trustResult == kSecTrustResultRecoverableTrustFailure && exceptions) {
-               /* If we have exceptions get details and match to exceptions. */
-               CFArrayRef details = SecTrustCopyDetails(trust);
-               if (details) {
-                       CFIndex pathLength = CFArrayGetCount(details);
-                       struct SecTrustCheckExceptionContext context = {};
-                       CFIndex ix;
-                       for (ix = 0; ix < pathLength; ++ix) {
-                               CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
-                       //      if ((ix == 0) && CFDictionaryContainsKey(detail, kSecPolicyCheckBlackListedLeaf))
-                       //              trustResult = kSecTrustResultFatalTrustFailure;
-                               context.exception = SecTrustGetExceptionForCertificateAtIndex(trust, ix);
-                               CFDictionaryApplyFunction(detail, SecTrustCheckException, &context);
-                               if (context.exceptionNotFound) {
-                                       break;
-                               }
-                       }
-                       if (!context.exceptionNotFound)
-                               trustResult = kSecTrustResultProceed;
-               }
-       }
-
-
-       secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult);
-       if (resultP) {
-               *resultP = trustResult;
-       }
-       return __secapiresult;
-}
-#endif
-
-#if !SECTRUST_OSX
-OSStatus SecTrustEvaluateAsync(SecTrustRef trust,
-       dispatch_queue_t queue, SecTrustCallback result)
-{
-       BEGIN_SECAPI
-       dispatch_async(queue, ^{
-               try {
-                       Trust *trustObj = Trust::required(trust);
-                       trustObj->evaluate();
-                       SecTrustResultType trustResult = trustObj->result();
-                       result(trust, trustResult);
-               }
-               catch (...) {
-                       result(trust, kSecTrustResultInvalid);
-               };
-       });
-       END_SECAPI
 }
-#endif
 
 //
 // Construct the "official" result evidence and return it
@@ -378,141 +110,26 @@ OSStatus SecTrustGetResult(
     SecTrustResultType *result,
        CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain)
 {
-#if !SECTRUST_OSX
-    BEGIN_SECAPI
-    Trust *trust = Trust::required(trustRef);
-    if (result)
-        *result = trust->result();
-    if (certChain && statusChain)
-        trust->buildEvidence(*certChain, TPEvidenceInfo::overlayVar(*statusChain));
-    END_SECAPI
-#else
        /* bridge to support old functionality */
 #if SECTRUST_DEPRECATION_WARNINGS
-       syslog(LOG_ERR, "WARNING: SecTrustGetResult has been deprecated since 10.7, and may not return a statusChain in 10.11. Please use SecTrustGetTrustResult instead.");
+       syslog(LOG_ERR, "WARNING: SecTrustGetResult has been deprecated since 10.7. Please use SecTrustGetTrustResult instead.");
 #endif
-       SecTrustResultType trustResult;
-       OSStatus status = SecTrustGetTrustResult(trustRef, &trustResult);
+    SecTrustResultType trustResult;
+    OSStatus status = SecTrustGetTrustResult(trustRef, &trustResult);
+    if (status != errSecSuccess) {
+        return status;
+    }
        if (result) {
                *result = trustResult;
        }
-       if (certChain && !statusChain) {
-               /* This is the easy case; caller only wants cert chain and not status chain. */
-               CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-               CFIndex idx, count = SecTrustGetCertificateCount(trustRef);
-               for (idx=0; idx < count; idx++) {
-                       SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trustRef, idx);
-                       if (certificate) {
-                               CFArrayAppendValue(certArray, certificate);
-                       }
-               }
-               *certChain = certArray;
+       if (certChain) {
+        *certChain = SecTrustCopyConstructedChain(trustRef);
        }
-       else if (certChain && statusChain) {
-               /*
-                * Here is where backward compatibility gets ugly. CSSM_TP_APPLE_EVIDENCE_INFO* is tied to a
-                * Trust object and does not exist in the new unified world. Unfortunately, some clients are
-                * still calling this legacy API and grubbing through the info for StatusBits and StatusCodes.
-                * If they want this info, then we have to do a legacy evaluation to get it. The info struct
-                * goes away once the old-style object does, so we must keep the old-style object alive after
-                * returning from the function.
-                *
-                * TODO: keep a dictionary and figure out how to expire entries when no longer needed.,
-                * or build the evidence info ourselves: rdar://21005914
-                */
-               static CFMutableArrayRef sTrustArray = NULL;
-
-               // make array of Certificate instances from unified SecCertificateRefs
-               CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-               CFIndex idx, count = SecTrustGetCertificateCount(trustRef);
-               for (idx=0; idx < count; idx++) {
-                       SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trustRef, idx);
-                       if (certificate) {
-                               SecCertificateRef itemImplRef = SecCertificateCreateItemImplInstance(certificate);
-                               if (itemImplRef) {
-                                       CFArrayAppendValue(certArray, itemImplRef);
-                                       CFRelease(itemImplRef);
-                               }
-                       }
-               }
-               // make array of Policy instances from unified SecPolicyRefs
-               CFMutableArrayRef policyArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-               CFArrayRef policies = NULL;
-               status = SecTrustCopyPolicies(trustRef, &policies);
-               count = (!status && policies) ? CFArrayGetCount(policies) : 0;
-               for (idx=0; idx < count; idx++) {
-                       SecPolicyRef policy = (SecPolicyRef) CFArrayGetValueAtIndex(policies, idx);
-                       if (policy) {
-                               SecPolicyRef itemImplRef = SecPolicyCreateItemImplInstance(policy);
-                               if (itemImplRef) {
-                                       CFArrayAppendValue(policyArray, itemImplRef);
-                                       CFRelease(itemImplRef);
-                               }
-                       }
-               }
-               // now make a Trust instance and evaluate it
-               try {
-                       Trust *trustObj = new Trust(certArray, policyArray);
-                       SecTrustRef trust = trustObj->handle();
-                       if (!trust) {
-                               MacOSError::throwMe(errSecTrustNotAvailable);
-                       }
-                       if (!sTrustArray) {
-                               sTrustArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-                               if (!sTrustArray) {
-                                       MacOSError::throwMe(errSecAllocate);
-                               }
-                       }
-                       // fetch the built cert chain and status chain
-                       CFArrayRef itemImplCertArray = NULL;
-                       trustObj->evaluate();
-                       trustObj->buildEvidence(itemImplCertArray, TPEvidenceInfo::overlayVar(*statusChain));
-
-                       // convert each Certificate in the built chain to a unified SecCertificateRef
-                       CFMutableArrayRef outCertChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-                       CFIndex idx, count = (itemImplCertArray) ? CFArrayGetCount(itemImplCertArray) : 0;
-                       for (idx=0; idx < count; idx++) {
-                               SecCertificateRef inCert = (SecCertificateRef) CFArrayGetValueAtIndex(itemImplCertArray, idx);
-                               SecCertificateRef outCert = SecCertificateCreateFromItemImplInstance(inCert);
-                               if (outCert) {
-                                       CFArrayAppendValue(outCertChain, outCert);
-                                       CFRelease(outCert);
-                               }
-                       }
-                       *certChain = outCertChain;
-                       if (itemImplCertArray) {
-                               CFRelease(itemImplCertArray);
-                       }
-                       CFArrayAppendValue(sTrustArray, trust);
-                       status = errSecSuccess;
-               }
-               catch (const MacOSError &err) { status=err.osStatus(); }
-               catch (const CommonError &err) { status=SecKeychainErrFromOSStatus(err.osStatus()); }
-               catch (const std::bad_alloc &) { status=errSecAllocate; }
-               catch (...) { status=errSecInternalComponent; }
-
-               if (policyArray)
-                       CFRelease(policyArray);
-               if (certArray)
-                       CFRelease(certArray);
+       if (statusChain) {
+        *statusChain = SecTrustGetEvidenceInfo(trustRef);
        }
        return status;
-#endif
-}
-
-//
-// Retrieve result of trust evaluation only
-//
-#if !SECTRUST_OSX
-OSStatus SecTrustGetTrustResult(SecTrustRef trustRef,
-       SecTrustResultType *result)
-{
-    BEGIN_SECAPI
-    Trust *trust = Trust::required(trustRef);
-    if (result) *result = trust->result();
-    END_SECAPI
 }
-#endif
 
 //
 // Retrieve extended validation trust results
@@ -520,25 +137,17 @@ OSStatus SecTrustGetTrustResult(SecTrustRef trustRef,
 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
 OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result)
 {
-#if !SECTRUST_OSX
-    BEGIN_SECAPI
-       Trust *trustObj = Trust::required(trust);
-       if (result == nil)
-               return errSecParam;
-       trustObj->extendedResult(*result);
-    END_SECAPI
-#else
        /* bridge to support old functionality */
 #if SECTRUST_DEPRECATION_WARNINGS
     syslog(LOG_ERR, "WARNING: SecTrustCopyExtendedResult will be deprecated in an upcoming release. Please use SecTrustCopyResult instead.");
 #endif
        CFDictionaryRef resultDict = SecTrustCopyResult(trust);
        if (result == nil) {
+        CFReleaseNull(resultDict);
                return errSecParam;
        }
        *result = resultDict;
        return errSecSuccess;
-#endif
 }
 
 //
@@ -547,11 +156,6 @@ OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result)
 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
 OSStatus SecTrustGetCssmResult(SecTrustRef trust, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result)
 {
-#if !SECTRUST_OSX
-    BEGIN_SECAPI
-    Required(result) = Trust::required(trust)->cssmResult();
-    END_SECAPI
-#else
        /* this function is unsupported in unified SecTrust */
 #if SECTRUST_DEPRECATION_WARNINGS
        syslog(LOG_ERR, "WARNING: SecTrustGetCssmResult has been deprecated since 10.7, and has no functional equivalent in 10.11. Please use SecTrustCopyResult instead.");
@@ -560,35 +164,98 @@ OSStatus SecTrustGetCssmResult(SecTrustRef trust, CSSM_TP_VERIFY_CONTEXT_RESULT_
                *result = NULL;
        }
        return errSecServiceNotAvailable;
-#endif
 }
 
-#if SECTRUST_OSX
-static void applyPropertyToCssmResultCode(const void *_key, const void *_value, void *context) {
-       CFStringRef key = (CFStringRef)_key;
-       CFStringRef value = (CFStringRef)_value;
-       OSStatus *result = (OSStatus *)context;
-       if (CFGetTypeID(_value) != CFStringGetTypeID()) {
-               return;
-       }
-       if (!CFEqual(CFSTR("value"), key)) {
-               return;
-       }
-       if (CFEqual(CFSTR("Invalid certificate chain linkage."), value)) {
-               *result = CSSMERR_APPLETP_INVALID_ID_LINKAGE;
-       } else if (CFEqual(CFSTR("One or more unsupported critical extensions found."), value)) {
-               *result = CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN;
-       } else if (CFEqual(CFSTR("Root certificate is not trusted."), value)) {
-               *result = CSSMERR_TP_NOT_TRUSTED;
-       } else if (CFEqual(CFSTR("Hostname mismatch."), value)) {
-               *result = CSSMERR_APPLETP_HOSTNAME_MISMATCH;
-       } else if (CFEqual(CFSTR("One or more certificates have expired or are not valid yet."), value)) {
-               *result = CSSMERR_TP_CERT_EXPIRED;
-       } else if (CFEqual(CFSTR("Policy requirements not met."), value)) {
-               *result = CSSMERR_TP_VERIFY_ACTION_FAILED;
-       }
+static uint8_t convertCssmResultToPriority(CSSM_RETURN resultCode) {
+    switch (resultCode) {
+        /* explicitly not trusted */
+        case CSSMERR_TP_CERT_REVOKED:
+        case CSSMERR_APPLETP_TRUST_SETTING_DENY:
+            return 1;
+        /* failure to comply with X.509 */
+        case CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS:
+        case CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT:
+        case CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT:
+        case CSSMERR_APPLETP_INVALID_AUTHORITY_ID:
+        case CSSMERR_TP_INVALID_CERTIFICATE:
+        case CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN:
+            return 2;
+        case CSSMERR_TP_CERT_EXPIRED:
+            return 3;
+        /* doesn't chain to trusted root */
+        case CSSMERR_TP_NOT_TRUSTED:
+        case CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH:
+            return 4;
+        /* all others are policy-specific failures */
+        default:
+            return 5;
+    }
+}
+
+static bool isSoftwareUpdateDevelopment(SecTrustRef trust) {
+    bool isPolicy = false, isEKU = false;
+    CFArrayRef policies = NULL;
+
+    /* Policy used to evaluate was SWUpdateSigning */
+    SecTrustCopyPolicies(trust, &policies);
+    if (policies) {
+        SecPolicyRef swUpdatePolicy = SecPolicyCreateAppleSWUpdateSigning();
+        if (swUpdatePolicy && CFArrayContainsValue(policies, CFRangeMake(0, CFArrayGetCount(policies)),
+                                                   swUpdatePolicy)) {
+            isPolicy = true;
+        }
+        if (swUpdatePolicy) { CFRelease(swUpdatePolicy); }
+        CFRelease(policies);
+    }
+    if (!isPolicy) {
+        return false;
+    }
+
+    /* Only error was EKU on the leaf */
+    CFArrayRef details = SecTrustCopyFilteredDetails(trust);
+    CFIndex ix, count = CFArrayGetCount(details);
+    bool hasDisqualifyingError = false;
+    for (ix = 0; ix < count; ix++) {
+        CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
+        if (ix == 0) { // Leaf
+            if (CFDictionaryGetCount(detail) != 1 || // One error
+                CFDictionaryGetValue(detail, CFSTR("ExtendedKeyUsage")) != kCFBooleanFalse) { // kSecPolicyCheckExtendedKeyUsage
+                hasDisqualifyingError = true;
+                break;
+            }
+        } else {
+            if (CFDictionaryGetCount(detail) > 0) { // No errors on other certs
+                hasDisqualifyingError = true;
+                break;
+            }
+        }
+    }
+    CFReleaseSafe(details);
+    if (hasDisqualifyingError) {
+        return false;
+    }
+
+    /* EKU on the leaf is the Apple Development Code Signing OID */
+    SecCertificateRef leaf = SecTrustGetCertificateAtIndex(trust, 0);
+    CSSM_DATA *fieldValue = NULL;
+    if (errSecSuccess != SecCertificateCopyFirstFieldValue(leaf, &CSSMOID_ExtendedKeyUsage, &fieldValue)) {
+        return false;
+    }
+    if (fieldValue && fieldValue->Data && fieldValue->Length == sizeof(CSSM_X509_EXTENSION)) {
+        const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)fieldValue->Data;
+        if (ext->format == CSSM_X509_DATAFORMAT_PARSED) {
+            const CE_ExtendedKeyUsage *ekus = (const CE_ExtendedKeyUsage *)ext->value.parsedValue;
+            if (ekus && (ekus->numPurposes == 1) && ekus->purposes[0].Data &&
+                (ekus->purposes[0].Length == CSSMOID_APPLE_EKU_CODE_SIGNING_DEV.Length) &&
+                (memcmp(ekus->purposes[0].Data, CSSMOID_APPLE_EKU_CODE_SIGNING_DEV.Data,
+                        ekus->purposes[0].Length) == 0)) {
+                isEKU = true;
+            }
+        }
+    }
+    SecCertificateReleaseFirstFieldValue(leaf, &CSSMOID_ExtendedKeyUsage, fieldValue);
+    return isEKU;
 }
-#endif
 
 //
 // Retrieve CSSM_LEVEL TP return code
@@ -596,15 +263,6 @@ static void applyPropertyToCssmResultCode(const void *_key, const void *_value,
 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
 OSStatus SecTrustGetCssmResultCode(SecTrustRef trustRef, OSStatus *result)
 {
-#if !SECTRUST_OSX
-       BEGIN_SECAPI
-               Trust *trust = Trust::required(trustRef);
-       if (trust->result() == kSecTrustResultInvalid)
-               return errSecParam;
-       else
-               Required(result) = trust->cssmResultCode();
-       END_SECAPI
-#else
        /* bridge to support old functionality */
 #if SECTRUST_DEPRECATION_WARNINGS
     syslog(LOG_ERR, "WARNING: SecTrustGetCssmResultCode has been deprecated since 10.7, and will be removed in a future release. Please use SecTrustCopyProperties instead.");
@@ -612,36 +270,54 @@ OSStatus SecTrustGetCssmResultCode(SecTrustRef trustRef, OSStatus *result)
        if (!trustRef || !result) {
                return errSecParam;
        }
-       CFArrayRef properties = SecTrustCopyProperties(trustRef);
-       if (!properties) {
-               *result = 0;
-               return errSecSuccess;
-       }
-       OSStatus cssmResultCode = 0;
-       CFIndex ix, count = CFArrayGetCount(properties);
-       for (ix = 0; ix < count; ++ix) {
-               CFDictionaryRef property = (CFDictionaryRef)
-                       CFArrayGetValueAtIndex(properties, ix);
-               CFDictionaryApplyFunction(property, applyPropertyToCssmResultCode, &cssmResultCode);
-       }
+
+    SecTrustResultType trustResult = kSecTrustResultInvalid;
+    (void) SecTrustGetTrustResult(trustRef, &trustResult);
+    if (trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified) {
+        if (result) { *result = 0; }
+        return errSecSuccess;
+    }
+
+    /* Development Software Update certs return a special error code when evaluated
+     * against the AppleSWUpdateSigning policy. See <rdar://27362805>. */
+    if (isSoftwareUpdateDevelopment(trustRef)) {
+        if (result) {
+            *result = CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT;
+        }
+        return errSecSuccess;
+    }
+
+    OSStatus cssmResultCode = errSecSuccess;
+    uint8_t resultCodePriority = 0xFF;
+    CFIndex ix, count = SecTrustGetCertificateCount(trustRef);
+    for (ix = 0; ix < count; ix++) {
+        CFIndex numStatusCodes;
+        CSSM_RETURN *statusCodes = NULL;
+        statusCodes = (CSSM_RETURN*)SecTrustCopyStatusCodes(trustRef, ix, &numStatusCodes);
+        if (statusCodes && numStatusCodes > 0) {
+            unsigned int statusIX;
+            for (statusIX = 0; statusIX < numStatusCodes; statusIX++) {
+                CSSM_RETURN currStatus = statusCodes[statusIX];
+                uint8_t currPriority = convertCssmResultToPriority(currStatus);
+                if (resultCodePriority > currPriority) {
+                    cssmResultCode = currStatus;
+                    resultCodePriority = currPriority;
+                }
+            }
+        }
+        if (statusCodes) { free(statusCodes); }
+        if (resultCodePriority == 1) { break; }
+    }
+
        if (result) {
                *result = cssmResultCode;
        }
-       if (properties) {
-               CFRelease(properties);
-       }
        return errSecSuccess;
-#endif
 }
 
 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
 OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle)
 {
-#if !SECTRUST_OSX
-       BEGIN_SECAPI
-               Required(handle) = Trust::required(trust)->getTPHandle();
-       END_SECAPI
-#else
        /* this function is unsupported in unified SecTrust */
 #if SECTRUST_DEPRECATION_WARNINGS
        syslog(LOG_ERR, "WARNING: SecTrustGetTPHandle has been deprecated since 10.7, and cannot return CSSM objects in 10.11. Please stop using it.");
@@ -650,75 +326,8 @@ OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle)
                *handle = NULL;
        }
        return errSecServiceNotAvailable;
-#endif
 }
 
-#if !SECTRUST_OSX
-OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies)
-{
-       BEGIN_SECAPI
-               CFArrayRef currentPolicies = Trust::required(trust)->policies();
-       if (currentPolicies != NULL)
-       {
-               CFRetain(currentPolicies);
-       }
-
-       Required(policies) = currentPolicies;
-       END_SECAPI
-}
-#endif
-
-#if !SECTRUST_OSX
-OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, Boolean allowFetch)
-{
-       BEGIN_SECAPI
-       Trust *trustObj = Trust::required(trust);
-       Trust::NetworkPolicy netPolicy = (allowFetch) ?
-               Trust::useNetworkEnabled : Trust::useNetworkDisabled;
-       trustObj->networkPolicy(netPolicy);
-       END_SECAPI
-}
-#endif
-
-#if !SECTRUST_OSX
-OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, Boolean *allowFetch)
-{
-       BEGIN_SECAPI
-       Boolean allowed = false;
-       Trust *trustObj = Trust::required(trust);
-       Trust::NetworkPolicy netPolicy = trustObj->networkPolicy();
-       if (netPolicy == Trust::useNetworkDefault) {
-               // network fetch is enabled by default for SSL only
-               allowed = trustObj->policySpecified(trustObj->policies(), CSSMOID_APPLE_TP_SSL);
-       } else {
-               // caller has explicitly set the network policy
-               allowed = (netPolicy == Trust::useNetworkEnabled);
-       }
-       Required(allowFetch) = allowed;
-       END_SECAPI
-}
-#endif
-
-#if !SECTRUST_OSX
-OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData)
-{
-       BEGIN_SECAPI
-       Trust::required(trust)->responses(responseData);
-       END_SECAPI
-}
-#endif
-
-#if !SECTRUST_OSX
-OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchorCertificates)
-{
-       BEGIN_SECAPI
-       CFArrayRef customAnchors = Trust::required(trust)->anchors();
-       Required(anchorCertificates) = (customAnchors) ?
-               (const CFArrayRef)CFRetain(customAnchors) : (const CFArrayRef)NULL;
-       END_SECAPI
-}
-#endif
-
 //
 // Get the user's default anchor certificate set
 //
@@ -726,15 +335,53 @@ OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anc
 OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchorCertificates)
 {
        BEGIN_SECAPI
-
-       return SecTrustSettingsCopyUnrestrictedRoots(
+    CFArrayRef outArray;
+       OSStatus status = SecTrustSettingsCopyUnrestrictedRoots(
                        true, true, true,               /* all domains */
-                       anchorCertificates);
-
+                       &outArray);
+    if (status != errSecSuccess) {
+        return status;
+    }
+    CFIndex count = outArray ? CFArrayGetCount(outArray) : 0;
+    if(count == 0) {
+        return errSecNoTrustSettings;
+    }
+    
+    /* Go through outArray and do a SecTrustEvaluate */
+    CFIndex i;
+    SecPolicyRef policy = SecPolicyCreateBasicX509();
+    CFMutableArrayRef trustedCertArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    for (i = 0; i < count ; i++) {
+        SecTrustRef trust;
+        SecTrustResultType result;
+        SecCertificateRef certificate = (SecCertificateRef) CFArrayGetValueAtIndex(outArray, i);
+        status = SecTrustCreateWithCertificates(certificate, policy, &trust);
+        if (status != errSecSuccess) {
+            CFReleaseSafe(trustedCertArray);
+            goto out;
+        }
+        status = SecTrustEvaluate(trust, &result);
+        if (status != errSecSuccess) {
+                       CFReleaseSafe(trustedCertArray);
+            goto out;
+        }
+        if (result != kSecTrustResultFatalTrustFailure) {
+            CFArrayAppendValue(trustedCertArray, certificate);
+        }
+    }
+    if (CFArrayGetCount(trustedCertArray) == 0) {
+       status = errSecNoTrustSettings;
+        CFReleaseSafe(trustedCertArray);
+        goto out;
+    }
+    *anchorCertificates = trustedCertArray;
+out:
+       CFReleaseSafe(outArray);
+    CFReleaseSafe(policy);
+    return status;
        END_SECAPI
 }
 
-#if SECTRUST_OSX
 /* We have an iOS-style SecTrustRef, but we need to return a CDSA-based SecKeyRef.
  */
 SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust)
@@ -744,429 +391,364 @@ SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust)
        (void) SecCertificateCopyPublicKey(certificate, &pubKey);
        return pubKey;
 }
-#else
-/* new in 10.6 */
-SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust)
-{
-       SecKeyRef pubKey = NULL;
-       CFArrayRef certChain = NULL;
-       CFArrayRef evidenceChain = NULL;
-       CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
-       OSStatus __secapiresult = errSecSuccess;
-       try {
-               Trust *trustObj = Trust::required(trust);
-               if (trustObj->result() == kSecTrustResultInvalid) {
-                       // Trust hasn't been evaluated; attempt to retrieve public key from leaf.
-                       SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, 0);
-                       __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey);
-                       if (pubKey) {
-                               return pubKey;
-                       }
-                       // Otherwise, we must evaluate first.
-                       trustObj->evaluate();
-                       if (trustObj->result() == kSecTrustResultInvalid) {
-                               MacOSError::throwMe(errSecTrustNotAvailable);
-                       }
-               }
-               if (trustObj->evidence() == nil) {
-                       trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
-               }
-               evidenceChain = trustObj->evidence();
-       }
-       catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
-       catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
-       catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
-       catch (...) { __secapiresult=errSecInternalComponent; }
-
-       if (certChain)
-               CFRelease(certChain);
 
-       if (evidenceChain) {
-               if (CFArrayGetCount(evidenceChain) > 0) {
-                       SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, 0);
-                       __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey);
-               }
-               // do not release evidenceChain, as it is owned by the trust object.
-       }
-       return pubKey;
-}
-#endif
-
-#if !SECTRUST_OSX
-/* new in 10.6 */
-CFIndex SecTrustGetCertificateCount(SecTrustRef trust)
-{
-       CFIndex chainLen = 0;
-       CFArrayRef certChain = NULL;
-       CFArrayRef evidenceChain = NULL;
-       CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
-    OSStatus __secapiresult = errSecSuccess;
-       try {
-               Trust *trustObj = Trust::required(trust);
-               if (trustObj->result() == kSecTrustResultInvalid) {
-                       trustObj->evaluate();
-                       if (trustObj->result() == kSecTrustResultInvalid)
-                               MacOSError::throwMe(errSecTrustNotAvailable);
+// cannot link against the new iOS SecTrust from this implementation,
+// so there are no possible accessors for the fields of this struct
+typedef struct __TSecTrust {
+    CFRuntimeBase           _base;
+    CFArrayRef              _certificates;
+    CFArrayRef              _anchors;
+    CFTypeRef               _policies;
+    CFArrayRef              _responses;
+    CFArrayRef              _SCTs;
+    CFArrayRef              _trustedLogs;
+    CFDateRef               _verifyDate;
+    CFTypeRef               _chain;
+    SecKeyRef               _publicKey;
+    CFArrayRef              _details;
+    CFDictionaryRef         _info;
+    CFArrayRef              _exceptions;
+    SecTrustResultType      _trustResult;
+    bool                    _anchorsOnly;
+    bool                    _keychainsAllowed;
+    void*                   _legacy_info_array;
+    void*                   _legacy_status_array;
+    dispatch_queue_t        _trustQueue;
+} TSecTrust;
+
+CFArrayRef SecTrustCopyInputCertificates(SecTrustRef trust)
+{
+       if (!trust) { return NULL; };
+       TSecTrust *secTrust = (TSecTrust *)trust;
+       if (secTrust->_certificates) {
+               CFRetain(secTrust->_certificates);
+       }
+       return secTrust->_certificates;
+}
+
+CFArrayRef SecTrustCopyInputAnchors(SecTrustRef trust)
+{
+       if (!trust) { return NULL; };
+       TSecTrust *secTrust = (TSecTrust *)trust;
+       if (secTrust->_anchors) {
+               CFRetain(secTrust->_anchors);
+       }
+       return secTrust->_anchors;
+}
+
+// Return the constructed certificate chain for this trust reference,
+// making output certificates pointer-equivalent to any provided input
+// certificates (where possible) for legacy behavioral compatibility.
+// Caller must release this array.
+//
+CFArrayRef SecTrustCopyConstructedChain(SecTrustRef trust)
+{
+       CFMutableArrayRef certChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       CFIndex idx, count = SecTrustGetCertificateCount(trust);
+       for (idx=0; idx < count; idx++) {
+               SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, idx);
+               if (certificate) {
+                       CFArrayAppendValue(certChain, certificate);
                }
-               if (trustObj->evidence() == nil)
-                       trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
-               evidenceChain = trustObj->evidence();
        }
-       catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
-       catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
-       catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
-       catch (...) { __secapiresult=errSecInternalComponent; }
-
-       if (certChain)
-               CFRelease(certChain);
-
-       if (evidenceChain)
-               chainLen = CFArrayGetCount(evidenceChain); // don't release, trust object owns it.
-
-    return chainLen;
-}
-#endif
-
-#if !SECTRUST_OSX
-/* new in 10.6 */
-SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix)
-{
-       SecCertificateRef certificate = NULL;
-       CFArrayRef certChain = NULL;
-       CFArrayRef evidenceChain = NULL;
-       CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
-    OSStatus __secapiresult = errSecSuccess;
-       try {
-               Trust *trustObj = Trust::required(trust);
-               if (trustObj->result() == kSecTrustResultInvalid) {
-                       // If caller is asking for the leaf, we can return it without
-                       // having to evaluate the entire chain. Note that we don't retain
-                       // the cert as it's owned by the trust and this is a 'Get' API.
-                       if (ix == 0) {
-                               CFArrayRef certs = trustObj->certificates();
-                               if (certs && (CFArrayGetCount(certs) > 0)) {
-                                       certificate = (SecCertificateRef) CFArrayGetValueAtIndex(certs, 0);
-                                       if (certificate) {
-                                               return certificate;
-                                       }
+       // <rdar://24393060>
+       // Some callers make the assumption that the certificates in
+       // this chain are pointer-equivalent to ones they passed to the
+       // SecTrustCreateWithCertificates function. We'll maintain that
+       // behavior here for compatibility.
+       //
+       CFArrayRef inputCertArray = SecTrustCopyInputCertificates(trust);
+       CFArrayRef inputAnchorArray = SecTrustCopyInputAnchors(trust);
+       CFIndex inputCertIdx, inputCertCount = (inputCertArray) ? CFArrayGetCount(inputCertArray) : 0;
+       CFIndex inputAnchorIdx, inputAnchorCount = (inputAnchorArray) ? CFArrayGetCount(inputAnchorArray) : 0;
+       for (idx=0; idx < count; idx++) {
+               SecCertificateRef tmpCert = (SecCertificateRef) CFArrayGetValueAtIndex(certChain, idx);
+               if (tmpCert) {
+                       SecCertificateRef matchCert = NULL;
+                       for (inputCertIdx=0; inputCertIdx < inputCertCount && !matchCert; inputCertIdx++) {
+                               SecCertificateRef inputCert = (SecCertificateRef) CFArrayGetValueAtIndex(inputCertArray, inputCertIdx);
+                               if (inputCert && CFEqual(inputCert, tmpCert)) {
+                                       matchCert = inputCert;
                                }
                        }
-                       // Otherwise, we must evaluate first.
-                       trustObj->evaluate();
-                       if (trustObj->result() == kSecTrustResultInvalid) {
-                               MacOSError::throwMe(errSecTrustNotAvailable);
+                       for (inputAnchorIdx=0; inputAnchorIdx < inputAnchorCount && !matchCert; inputAnchorIdx++) {
+                               SecCertificateRef inputAnchor = (SecCertificateRef) CFArrayGetValueAtIndex(inputAnchorArray, inputAnchorIdx);
+                               if (inputAnchor && CFEqual(inputAnchor, tmpCert)) {
+                                       matchCert = inputAnchor;
+                               }
+                       }
+                       if (matchCert) {
+                               CFArraySetValueAtIndex(certChain, idx, matchCert);
                        }
                }
-               if (trustObj->evidence() == nil) {
-                       trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
-               }
-               evidenceChain = trustObj->evidence();
        }
-       catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
-       catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
-       catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
-       catch (...) { __secapiresult=errSecInternalComponent; }
-
-       if (certChain)
-               CFRelease(certChain);
-
-       if (evidenceChain) {
-               if (ix < CFArrayGetCount(evidenceChain)) {
-                       certificate = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, ix);
-                       // note: we do not retain this certificate. The assumption here is
-                       // that the certificate is retained by the trust object, so it is
-                       // valid unil the trust is released (or until re-evaluated.)
-                       // also note: we do not release the evidenceChain, as it is owned
-                       // by the trust object.
-               }
+       if (inputCertArray) {
+               CFRelease(inputCertArray);
        }
-       return certificate;
-}
-#endif
-
-
-#if !SECTRUST_OSX
-static CFStringRef kSecCertificateDetailSHA1Digest = CFSTR("SHA1Digest");
-static CFStringRef kSecCertificateDetailStatusCodes = CFSTR("StatusCodes");
-
-static void
-_AppendStatusCode(CFMutableArrayRef array, OSStatus statusCode)
-{
-       if (!array)
-               return;
-       SInt32 num = statusCode;
-       CFNumberRef numRef = CFNumberCreate(NULL, kCFNumberSInt32Type, &num);
-       if (!numRef)
-               return;
-       CFArrayAppendValue(array, numRef);
-       CFRelease(numRef);
+       if (inputAnchorArray) {
+               CFRelease(inputAnchorArray);
+       }
+       return certChain;
 }
-#endif
 
-#if !SECTRUST_OSX
-CFArrayRef SecTrustCopyDetails(SecTrustRef trust)
+//
+// Here is where backward compatibility gets ugly. CSSM_TP_APPLE_EVIDENCE_INFO does not exist
+// in the unified SecTrust world. Unfortunately, some clients are still calling legacy APIs
+// (e.g. SecTrustGetResult) and grubbing through the info for StatusBits and StatusCodes.
+// SecTrustGetEvidenceInfo builds the legacy evidence info structure as needed, and returns
+// a pointer to it. The evidence data is allocated here and set in the _legacy_* fields
+// of the TSecTrust; the trust object subsequently owns it. The returned pointer is expected
+// to be valid for the lifetime of the SecTrustRef, or until the trust parameters are changed,
+// which would force re-evaluation.
+//
+static CSSM_TP_APPLE_EVIDENCE_INFO *
+SecTrustGetEvidenceInfo(SecTrustRef trust)
 {
-       // This function returns an array of dictionaries, one per certificate,
-       // holding status info for each certificate in the evaluated chain.
-       //
-       CFIndex count, chainLen = 0;
-       CFArrayRef certChain = NULL;
-       CFMutableArrayRef details = NULL;
-       CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
-    OSStatus __secapiresult = errSecSuccess;
-       try {
-               Trust *trustObj = Trust::required(trust);
-               if (trustObj->result() == kSecTrustResultInvalid) {
-                       trustObj->evaluate();
-                       if (trustObj->result() == kSecTrustResultInvalid)
-                               MacOSError::throwMe(errSecTrustNotAvailable);
-               }
-               trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
+       TSecTrust *secTrust = (TSecTrust *)trust;
+       if (!secTrust) {
+               return NULL;
        }
-       catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
-       catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
-       catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
-       catch (...) { __secapiresult=errSecInternalComponent; }
-
-       if (certChain) {
-               chainLen = CFArrayGetCount(certChain);
-               CFRelease(certChain);
+       if (secTrust->_trustResult != kSecTrustResultInvalid &&
+               secTrust->_legacy_info_array) {
+               // we've already got valid evidence info, return it now.
+               return (CSSM_TP_APPLE_EVIDENCE_INFO *)secTrust->_legacy_info_array;
        }
-       if (statusChain) {
-               details = CFArrayCreateMutable(NULL, chainLen, &kCFTypeArrayCallBacks);
-               for (count = 0; count < chainLen; count++) {
-                       CFMutableDictionaryRef certDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
-                               0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-                       CFMutableArrayRef statusCodes = CFArrayCreateMutable(kCFAllocatorDefault,
-                               0, &kCFTypeArrayCallBacks);
-                       CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &statusChain[count];
-                       CSSM_TP_APPLE_CERT_STATUS statBits = evInfo->StatusBits;
 
-                       // translate status bits
-                       if (statBits & CSSM_CERT_STATUS_EXPIRED)
-                               _AppendStatusCode(statusCodes, errSecCertificateExpired);
-                       if (statBits & CSSM_CERT_STATUS_NOT_VALID_YET)
-                               _AppendStatusCode(statusCodes, errSecCertificateNotValidYet);
-                       if (statBits & CSSM_CERT_STATUS_TRUST_SETTINGS_DENY)
-                               _AppendStatusCode(statusCodes, errSecTrustSettingDeny);
+       // Getting the count implicitly evaluates the chain if necessary.
+       CFIndex idx, count = SecTrustGetCertificateCount(trust);
+       CFArrayRef inputCertArray = SecTrustCopyInputCertificates(trust);
+       CFArrayRef inputAnchorArray = SecTrustCopyInputAnchors(trust);
+       CFIndex inputCertIdx, inputCertCount = (inputCertArray) ? CFArrayGetCount(inputCertArray) : 0;
+       CFIndex inputAnchorIdx, inputAnchorCount = (inputAnchorArray) ? CFArrayGetCount(inputAnchorArray) : 0;
 
-                       // translate status codes
-                       unsigned int i;
-                       for (i = 0; i < evInfo->NumStatusCodes; i++) {
-                               CSSM_RETURN scode = evInfo->StatusCodes[i];
-                               _AppendStatusCode(statusCodes, (OSStatus)scode);
-                       }
+       CSSM_TP_APPLE_EVIDENCE_INFO *infoArray = (CSSM_TP_APPLE_EVIDENCE_INFO *)calloc(count, sizeof(CSSM_TP_APPLE_EVIDENCE_INFO));
+       CSSM_RETURN *statusArray = NULL;
+       CFIndex numStatusCodes = 0;
 
-                       CFDictionarySetValue(certDict, kSecCertificateDetailStatusCodes, statusCodes);
-                       CFRelease(statusCodes);
-                       CFArrayAppendValue(details, certDict);
-                       CFRelease(certDict);
+       // Set status codes for each certificate in the constructed chain
+       for (idx=0; idx < count; idx++) {
+               SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, idx);
+               if (!cert) {
+                       continue;
                }
-       }
-       return details;
-}
-#endif
-
-#if !SECTRUST_OSX
-static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix)
-{
-       CFArrayRef exceptions = NULL;
-    OSStatus __secapiresult = errSecSuccess;
-       try {
-               exceptions = Trust::required(trust)->exceptions();
-       }
-       catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
-       catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
-       catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
-       catch (...) { __secapiresult=errSecInternalComponent; }
+               CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &infoArray[idx];
 
-       if (!exceptions || ix >= CFArrayGetCount(exceptions))
-               return NULL;
-       CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
-       if (CFGetTypeID(exception) != CFDictionaryGetTypeID())
-               return NULL;
-
-       SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
-       if (!certificate)
-               return NULL;
-
-       /* If the exception contains the current certificate's sha1Digest in the
-          kSecCertificateDetailSHA1Digest key then we use it otherwise we ignore it. */
-       CFDataRef sha1Digest = SecCertificateGetSHA1Digest(certificate);
-       CFTypeRef digestValue = CFDictionaryGetValue(exception, kSecCertificateDetailSHA1Digest);
-       if (!digestValue || !CFEqual(sha1Digest, digestValue))
-               exception = NULL;
-
-       return exception;
-}
-#endif
-
-#if !SECTRUST_OSX
-static void SecTrustCheckException(const void *key, const void *value, void *context)
-{
-       struct SecTrustCheckExceptionContext *cec = (struct SecTrustCheckExceptionContext *)context;
-       if (cec->exception) {
-               CFTypeRef exceptionValue = CFDictionaryGetValue(cec->exception, key);
-               if (!exceptionValue || !CFEqual(value, exceptionValue)) {
-                       cec->exceptionNotFound = true;
+               /* first the booleans (StatusBits flags) */
+               CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
+               if (secTrust->_verifyDate) {
+                       now = CFDateGetAbsoluteTime(secTrust->_verifyDate);
                }
-       } else {
-               cec->exceptionNotFound = true;
-       }
-}
-#endif
-
-#if !SECTRUST_OSX
-/* new in 10.9 */
-CFDataRef SecTrustCopyExceptions(SecTrustRef trust)
-{
-       CFArrayRef details = SecTrustCopyDetails(trust);
-       CFIndex pathLength = details ? CFArrayGetCount(details) : 0;
-       CFMutableArrayRef exceptions = CFArrayCreateMutable(kCFAllocatorDefault,
-                       pathLength, &kCFTypeArrayCallBacks);
-       CFIndex ix;
-       for (ix = 0; ix < pathLength; ++ix) {
-               CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
-               CFIndex detailCount = CFDictionaryGetCount(detail);
-               CFMutableDictionaryRef exception;
-               if (ix == 0 || detailCount > 0) {
-                       exception = CFDictionaryCreateMutableCopy(kCFAllocatorDefault,
-                               detailCount + 1, detail);
-                       SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
-                       CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
-                       if (digest) {
-                               CFDictionaryAddValue(exception, kSecCertificateDetailSHA1Digest, digest);
+               CFAbsoluteTime na = SecCertificateNotValidAfter(cert);
+               if (na < now) {
+                       evInfo->StatusBits |= CSSM_CERT_STATUS_EXPIRED;
+               }
+               CFAbsoluteTime nb = SecCertificateNotValidBefore(cert);
+               if (nb > now) {
+                       evInfo->StatusBits |= CSSM_CERT_STATUS_NOT_VALID_YET;
+               }
+               for (inputAnchorIdx=0; inputAnchorIdx < inputAnchorCount; inputAnchorIdx++) {
+                       SecCertificateRef inputAnchor = (SecCertificateRef) CFArrayGetValueAtIndex(inputAnchorArray, inputAnchorIdx);
+                       if (inputAnchor && CFEqual(inputAnchor, cert)) {
+                               evInfo->StatusBits |= CSSM_CERT_STATUS_IS_IN_ANCHORS;
+                               break;
                        }
-               } else {
-                       /* Add empty exception dictionaries for non leaf certs which have no exceptions
-                        * to save space.
-                        */
-                       exception = (CFMutableDictionaryRef)CFDictionaryCreate(kCFAllocatorDefault,
-                               NULL, NULL, 0,
-                               &kCFTypeDictionaryKeyCallBacks,
-                               &kCFTypeDictionaryValueCallBacks);
                }
-               CFArrayAppendValue(exceptions, exception);
-               CFReleaseNull(exception);
-       }
-       CFReleaseSafe(details);
-
-       /* Remove any trailing empty dictionaries to save even more space (we skip the leaf
-          since it will never be empty). */
-       for (ix = pathLength; ix-- > 1;) {
-               CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
-               if (CFDictionaryGetCount(exception) == 0) {
-                       CFArrayRemoveValueAtIndex(exceptions, ix);
-               } else {
-                       break;
+               for (inputCertIdx=0; inputCertIdx < inputCertCount; inputCertIdx++) {
+                       SecCertificateRef inputCert = (SecCertificateRef) CFArrayGetValueAtIndex(inputCertArray, inputCertIdx);
+                       if (inputCert && CFEqual(inputCert, cert)) {
+                               evInfo->StatusBits |= CSSM_CERT_STATUS_IS_IN_INPUT_CERTS;
+                               break;
+                       }
                }
-       }
-
-       CFDataRef encodedExceptions = CFPropertyListCreateData(kCFAllocatorDefault,
-                       exceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL);
-       CFRelease(exceptions);
-
-       return encodedExceptions;
-}
-#endif
 
-#if !SECTRUST_OSX
-/* new in 10.9 */
-bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions)
-{
-       CFArrayRef exceptions;
-       exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault,
-               encodedExceptions, kCFPropertyListImmutable, NULL, NULL);
-       if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) {
-               CFRelease(exceptions);
-               exceptions = NULL;
-       }
-
-       OSStatus __secapiresult = errSecSuccess;
-       try {
-               Trust::required(trust)->exceptions(exceptions);
-       }
-       catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
-       catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
-       catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
-       catch (...) { __secapiresult=errSecInternalComponent; }
-
-       /* If there is a valid exception entry for our current leaf we're golden. */
-       if (SecTrustGetExceptionForCertificateAtIndex(trust, 0))
-               return true;
-
-       /* The passed in exceptions didn't match our current leaf, so we discard it. */
-       try {
-               Trust::required(trust)->exceptions(NULL);
-               __secapiresult = errSecSuccess;
-       }
-       catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
-       catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
-       catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
-       catch (...) { __secapiresult=errSecInternalComponent; }
-
-       return false;
-}
-#endif
-
-#if !SECTRUST_OSX
-/* new in 10.9 */
-CFDictionaryRef
-SecTrustCopyResult(SecTrustRef trust)
-{
-       CFDictionaryRef result = NULL;
-       try {
-               result = Trust::required(trust)->results();
-               // merge details into result
-               CFArrayRef details = SecTrustCopyDetails(trust);
-               if (details) {
-                       CFDictionarySetValue((CFMutableDictionaryRef)result,
-                               kSecTrustResultDetails, details);
-                       CFRelease(details);
+               /* See if there are trust settings for this certificate. */
+               CFStringRef hashStr = SecTrustSettingsCertHashStrFromCert(cert);
+               bool foundMatch = false;
+               bool foundAny = false;
+               CSSM_RETURN *errors = NULL;
+               uint32 errorCount = 0;
+               OSStatus status = 0;
+               SecTrustSettingsDomain foundDomain = kSecTrustSettingsDomainUser;
+               SecTrustSettingsResult foundResult = kSecTrustSettingsResultInvalid;
+               bool isSelfSigned = false;
+               if ((count - 1) == idx) {
+                       // Only the last cert in the chain needs to be considered
+                       Boolean selfSigned;
+                       status = SecCertificateIsSelfSigned(cert, &selfSigned);
+                       isSelfSigned = (status) ? false : ((selfSigned) ? true : false);
+                       if (isSelfSigned) {
+                               evInfo->StatusBits |= CSSM_CERT_STATUS_IS_ROOT;
+                       }
                }
-       }
-       catch (...) {
-               if (result) {
-                       CFRelease(result);
-                       result = NULL;
+               // STU: rdar://25554967
+               // %%% need to get policyOID, policyString, and keyUsage here!
+
+               status = SecTrustSettingsEvaluateCert(
+                               hashStr,                /* certHashStr */
+                               NULL,                   /* policyOID (optional) */
+                               NULL,                   /* policyString (optional) */
+                               0,                              /* policyStringLen */
+                               0,                              /* keyUsage */
+                               isSelfSigned,   /* isRootCert */
+                               &foundDomain,   /* foundDomain */
+                               &errors,                /* allowedErrors -- MUST FREE */
+                               &errorCount,    /* numAllowedErrors */
+                               &foundResult,   /* resultType */
+                               &foundMatch,    /* foundMatchingEntry */
+                               &foundAny);             /* foundAnyEntry */
+
+               if (status == errSecSuccess) {
+                       if (foundMatch) {
+                               switch (foundResult) {
+                                       case kSecTrustSettingsResultTrustRoot:
+                                       case kSecTrustSettingsResultTrustAsRoot:
+                                               /* these two can be disambiguated by IS_ROOT */
+                                               evInfo->StatusBits |= CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST;
+                                               break;
+                                       case kSecTrustSettingsResultDeny:
+                                               evInfo->StatusBits |= CSSM_CERT_STATUS_TRUST_SETTINGS_DENY;
+                                               break;
+                                       case kSecTrustSettingsResultUnspecified:
+                                       case kSecTrustSettingsResultInvalid:
+                                       default:
+                                               break;
+                               }
+                       }
+               }
+               if (errors) {
+                       free(errors);
+               }
+               if (hashStr) {
+                       CFRelease(hashStr);
                }
-       }
-       return result;
-}
-#endif
 
-#if !SECTRUST_OSX
-/* new in 10.7 */
-CFArrayRef
-SecTrustCopyProperties(SecTrustRef trust)
-{
-       /* can't use SECAPI macros, since this function does not return OSStatus */
-       CFArrayRef result = NULL;
-       try {
-               result = Trust::required(trust)->properties();
-       }
-       catch (...) {
-               if (result) {
-                       CFRelease(result);
-                       result = NULL;
+               CFIndex numCodes=0;
+               CSSM_RETURN *statusCodes = (CSSM_RETURN*)SecTrustCopyStatusCodes(trust, idx, &numCodes);
+               if (statusCodes) {
+                       // Realloc space for these status codes at end of our status codes block.
+                       // Two important things to note:
+                       // 1. the actual length is numCodes+1 because SecTrustCopyStatusCodes
+                       // allocates one more element at the end for the CrlReason value.
+                       // 2. realloc may cause the pointer to move, which means we will
+                       // need to fix up the StatusCodes fields after we're done with this loop.
+                       CFIndex totalStatusCodes = numStatusCodes + numCodes + 1;
+                       statusArray = (CSSM_RETURN *)realloc(statusArray, totalStatusCodes * sizeof(CSSM_RETURN));
+                       evInfo->StatusCodes = &statusArray[numStatusCodes];
+                       evInfo->NumStatusCodes = (uint32)numCodes;
+                       // Copy the new codes (plus one) into place
+                       for (unsigned int cpix = 0; cpix <= numCodes; cpix++) {
+                               evInfo->StatusCodes[cpix] = statusCodes[cpix];
+                       }
+                       numStatusCodes = totalStatusCodes;
+                       free(statusCodes);
                }
-       }
-       return result;
+
+               if(evInfo->StatusBits & (CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST |
+                                                                CSSM_CERT_STATUS_TRUST_SETTINGS_DENY |
+                                                                CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR)) {
+                       /* Something noteworthy happened involving TrustSettings */
+                       uint32 whichDomain = 0;
+                       switch(foundDomain) {
+                               case kSecTrustSettingsDomainUser:
+                                       whichDomain = CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER;
+                                       break;
+                               case kSecTrustSettingsDomainAdmin:
+                                       whichDomain = CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN;
+                                       break;
+                               case kSecTrustSettingsDomainSystem:
+                                       whichDomain = CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM;
+                                       break;
+                       }
+                       evInfo->StatusBits |= whichDomain;
+               }
+
+               /* index into raw cert group or AnchorCerts depending on IS_IN_ANCHORS */
+               //evInfo->Index = certInfo->index();
+               /* nonzero if cert came from a DLDB */
+               //evInfo->DlDbHandle = certInfo->dlDbHandle();
+               //evInfo->UniqueRecord = certInfo->uniqueRecord();
+       }
+
+       // Now that all the status codes have been allocated in a contiguous block,
+       // refresh the StatusCodes pointer in each array element.
+       numStatusCodes = 0;
+       for (idx=0; idx < count; idx++) {
+               CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &infoArray[idx];
+               evInfo->StatusCodes = &statusArray[numStatusCodes];
+               numStatusCodes += evInfo->NumStatusCodes + 1;
+       }
+
+       secTrust->_legacy_info_array = infoArray;
+       secTrust->_legacy_status_array = statusArray;
+
+       if (inputCertArray) {
+               CFRelease(inputCertArray);
+       }
+       if (inputAnchorArray) {
+               CFRelease(inputAnchorArray);
+       }
+
+       return (CSSM_TP_APPLE_EVIDENCE_INFO *)secTrust->_legacy_info_array;
+}
+
+CFArrayRef SecTrustCopyProperties(SecTrustRef trust) {
+    /* OS X creates a completely different structure with one dictionary for each certificate */
+    CFIndex ix, count = SecTrustGetCertificateCount(trust);
+
+    CFMutableArrayRef properties = CFArrayCreateMutable(kCFAllocatorDefault, count,
+                                                        &kCFTypeArrayCallBacks);
+
+    for (ix = 0; ix < count; ix++) {
+        CFMutableDictionaryRef certDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
+                                                                    &kCFTypeDictionaryValueCallBacks);
+        /* Populate the certificate title */
+        SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, ix);
+        if (cert) {
+            CFStringRef subjectSummary = SecCertificateCopySubjectSummary(cert);
+            if (subjectSummary) {
+                CFDictionaryAddValue(certDict, kSecPropertyTypeTitle, subjectSummary);
+                CFRelease(subjectSummary);
+            }
+        }
+
+        /* Populate a revocation reason if the cert was revoked */
+        CFIndex numStatusCodes;
+        CSSM_RETURN *statusCodes = NULL;
+        statusCodes = (CSSM_RETURN*)SecTrustCopyStatusCodes(trust, ix, &numStatusCodes);
+        if (statusCodes) {
+            SInt32 reason = statusCodes[numStatusCodes];  // stored at end of status codes array
+            if (reason > 0) {
+                CFNumberRef cfreason = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &reason);
+                if (cfreason) {
+                    CFDictionarySetValue(certDict, kSecTrustRevocationReason, cfreason);
+                    CFRelease(cfreason);
+                }
+            }
+            free(statusCodes);
+        }
+
+        /* Populate the error in the leaf dictionary */
+        if (ix == 0) {
+            OSStatus error = errSecSuccess;
+            (void)SecTrustGetCssmResultCode(trust, &error);
+            CFStringRef errorStr = SecCopyErrorMessageString(error, NULL);
+            if (errorStr) {
+                CFDictionarySetValue(certDict, kSecPropertyTypeError, errorStr);
+                CFRelease(errorStr);
+            }
+        }
+
+        CFArrayAppendValue(properties, certDict);
+        CFRelease(certDict);
+    }
+
+    return properties;
 }
-#endif
 
 /* deprecated in 10.5 */
 OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors,
        uint32 *cssmAnchorCount)
 {
-#if !SECTRUST_OSX
-       BEGIN_SECAPI
-       CertGroup certs;
-       Trust::gStore().getCssmRootCertificates(certs);
-       Required(cssmAnchors) = certs.blobCerts();
-       Required(cssmAnchorCount) = certs.count();
-       END_SECAPI
-#else
        /* this function is unsupported in unified SecTrust */
 #if SECTRUST_DEPRECATION_WARNINGS
        syslog(LOG_ERR, "WARNING: SecTrustGetCSSMAnchorCertificates has been deprecated since 10.5, and cannot return CSSM objects in 10.11. Please stop using it.");
@@ -1178,7 +760,6 @@ OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors,
                *cssmAnchorCount = 0;
        }
        return errSecServiceNotAvailable;
-#endif
 }
 
 
@@ -1189,22 +770,11 @@ OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors,
 OSStatus SecTrustGetUserTrust(SecCertificateRef certificate,
     SecPolicyRef policy, SecTrustUserSetting *trustSetting)
 {
-#if !SECTRUST_OSX
-       BEGIN_SECAPI
-       StorageManager::KeychainList searchList;
-       globals().storageManager.getSearchList(searchList);
-       Required(trustSetting) = Trust::gStore().find(
-               Certificate::required(certificate),
-               Policy::required(policy),
-               searchList);
-       END_SECAPI
-#else
        /* this function is unsupported in unified SecTrust */
 #if SECTRUST_DEPRECATION_WARNINGS
        syslog(LOG_ERR, "WARNING: SecTrustGetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
 #endif
        return errSecServiceNotAvailable;
-#endif
 }
 
 //
@@ -1214,53 +784,11 @@ OSStatus SecTrustGetUserTrust(SecCertificateRef certificate,
 OSStatus SecTrustSetUserTrust(SecCertificateRef certificate,
     SecPolicyRef policy, SecTrustUserSetting trustSetting)
 {
-#if !SECTRUST_OSX
-       SecTrustSettingsResult tsResult = kSecTrustSettingsResultInvalid;
-       OSStatus ortn;
-       Boolean isRoot;
-
-       Policy::required(policy);
-       switch(trustSetting) {
-               case kSecTrustResultProceed:
-                       /* different SecTrustSettingsResult depending in root-ness */
-                       ortn = SecCertificateIsSelfSigned(certificate, &isRoot);
-                       if(ortn) {
-                               return ortn;
-                       }
-                       if(isRoot) {
-                               tsResult = kSecTrustSettingsResultTrustRoot;
-                       }
-                       else {
-                               tsResult = kSecTrustSettingsResultTrustAsRoot;
-                       }
-                       break;
-               case kSecTrustResultDeny:
-                       tsResult = kSecTrustSettingsResultDeny;
-                       break;
-               default:
-                       return errSecUnimplemented;
-       }
-
-       /* make a usage constraints dictionary */
-       CFRef<CFMutableDictionaryRef> usageDict(CFDictionaryCreateMutable(NULL,
-               0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
-       CFDictionaryAddValue(usageDict, kSecTrustSettingsPolicy, policy);
-       if(tsResult != kSecTrustSettingsResultTrustRoot) {
-               /* skip if we're specifying the default */
-               SInt32 result = tsResult;
-               CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &result);
-               CFDictionarySetValue(usageDict, kSecTrustSettingsResult, cfNum);
-               CFRelease(cfNum);
-       }
-       return SecTrustSettingsSetTrustSettings(certificate, kSecTrustSettingsDomainUser,
-               usageDict);
-#else
        /* this function is unsupported in unified SecTrust */
 #if SECTRUST_DEPRECATION_WARNINGS
        syslog(LOG_ERR, "WARNING: SecTrustSetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
 #endif
        return errSecServiceNotAvailable;
-#endif
 }
 
 //
@@ -1271,27 +799,9 @@ OSStatus SecTrustSetUserTrust(SecCertificateRef certificate,
 OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate,
     SecPolicyRef policy, SecTrustUserSetting trustSetting)
 {
-#if !SECTRUST_OSX
-       BEGIN_SECAPI
-       switch (trustSetting) {
-    case kSecTrustResultProceed:
-    case kSecTrustResultConfirm:
-    case kSecTrustResultDeny:
-    case kSecTrustResultUnspecified:
-               break;
-       default:
-               MacOSError::throwMe(errSecInvalidTrustSetting);
-       }
-       Trust::gStore().assign(
-               Certificate::required(certificate),
-               Policy::required(policy),
-               trustSetting);
-       END_SECAPI
-#else
        /* this function is unsupported in unified SecTrust */
 #if SECTRUST_DEPRECATION_WARNINGS
        syslog(LOG_ERR, "WARNING: SecTrustSetUserTrustLegacy does nothing in 10.11. Please stop using it.");
 #endif
        return errSecServiceNotAvailable;
-#endif
 }