]> git.saurik.com Git - apple/security.git/blobdiff - sec/Security/SecTrust.c
Security-57031.1.35.tar.gz
[apple/security.git] / sec / Security / SecTrust.c
diff --git a/sec/Security/SecTrust.c b/sec/Security/SecTrust.c
deleted file mode 100644 (file)
index d7f4775..0000000
+++ /dev/null
@@ -1,1582 +0,0 @@
-/*
- * Copyright (c) 2006-2013 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@
- *
- * SecTrust.c - CoreFoundation based certificate trust evaluator
- *
- * Created by Michael Brouwer on 10/17/06.
- */
-
-#include <Security/SecTrustPriv.h>
-#include <Security/SecItemPriv.h>
-#include <Security/SecCertificateInternal.h>
-#include <Security/SecCertificatePath.h>
-#include <Security/SecFramework.h>
-#include <Security/SecPolicyInternal.h>
-#include <utilities/SecIOFormat.h>
-#include <CoreFoundation/CFRuntime.h>
-#include <CoreFoundation/CFSet.h>
-#include <CoreFoundation/CFString.h>
-#include <CoreFoundation/CFNumber.h>
-#include <CoreFoundation/CFArray.h>
-#include <CoreFoundation/CFPropertyList.h>
-#include <AssertMacros.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <Security/SecBasePriv.h>
-#include <utilities/SecCFError.h>
-#include <utilities/SecCFWrappers.h>
-#include <utilities/SecCertificateTrace.h>
-
-#include "SecRSAKey.h"
-#include <libDER/oids.h>
-#include <utilities/debugging.h>
-#include <Security/SecInternal.h>
-#include <ipc/securityd_client.h>
-#include <SecuritydXPC.h>
-#include <securityd/SecTrustServer.h>
-
-#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v));
-
-SEC_CONST_DECL (kSecTrustInfoExtendedValidationKey, "ExtendedValidation");
-SEC_CONST_DECL (kSecTrustInfoCompanyNameKey, "CompanyName");
-SEC_CONST_DECL (kSecTrustInfoRevocationKey, "Revocation");
-SEC_CONST_DECL (kSecTrustInfoRevocationValidUntilKey, "RevocationValidUntil");
-
-/* Public trust result constants */
-SEC_CONST_DECL (kSecTrustEvaluationDate, "TrustEvaluationDate");
-SEC_CONST_DECL (kSecTrustExtendedValidation, "TrustExtendedValidation");
-SEC_CONST_DECL (kSecTrustOrganizationName, "Organization");
-SEC_CONST_DECL (kSecTrustResultValue, "TrustResultValue");
-SEC_CONST_DECL (kSecTrustRevocationChecked, "TrustRevocationChecked");
-SEC_CONST_DECL (kSecTrustRevocationValidUntilDate, "TrustExpirationDate");
-SEC_CONST_DECL (kSecTrustResultDetails, "TrustResultDetails");
-
-#pragma mark -
-#pragma mark SecTrust
-
-/********************************************************
- ****************** SecTrust object *********************
- ********************************************************/
-struct __SecTrust {
-       CFRuntimeBase                   _base;
-       CFArrayRef                              _certificates;
-       CFArrayRef                              _anchors;
-       CFTypeRef                               _policies;
-       CFArrayRef                              _responses;
-       CFDateRef                               _verifyDate;
-       SecCertificatePathRef   _chain;
-       SecKeyRef                               _publicKey;
-       CFArrayRef              _details;
-       CFDictionaryRef         _info;
-       CFArrayRef              _exceptions;
-
-    /* Note that a value of kSecTrustResultInvalid (0)
-     * indicates the trust must be (re)evaluated; any
-     * functions which modify trust parameters in a way
-     * that would invalidate the current result must set
-     * this value back to kSecTrustResultInvalid.
-     */
-    SecTrustResultType      _trustResult;
-
-    /* If true we don't trust any anchors other than the ones in _anchors. */
-    bool                    _anchorsOnly;
-
-       /* Master switch to permit or disable network use in policy evaluation */
-       SecNetworkPolicy                _networkPolicy;
-};
-
-/* CFRuntime registration data. */
-static pthread_once_t kSecTrustRegisterClass = PTHREAD_ONCE_INIT;
-static CFTypeID kSecTrustTypeID = _kCFRuntimeNotATypeID;
-
-/* Forward declarations of static functions. */
-static CFStringRef SecTrustDescribe(CFTypeRef cf);
-static void SecTrustDestroy(CFTypeRef cf);
-static OSStatus SecTrustEvaluateIfNecessary(SecTrustRef trust);
-
-/* Static functions. */
-static CF_RETURNS_RETAINED CFStringRef SecTrustDescribe(CFTypeRef cf) {
-    SecTrustRef trust = (SecTrustRef)cf;
-    return CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
-        CFSTR("<SecTrustRef: %p>"), trust);
-}
-
-static void SecTrustDestroy(CFTypeRef cf) {
-    SecTrustRef trust = (SecTrustRef)cf;
-       CFReleaseSafe(trust->_certificates);
-       CFReleaseSafe(trust->_policies);
-       CFReleaseSafe(trust->_responses);
-       CFReleaseSafe(trust->_verifyDate);
-       CFReleaseSafe(trust->_anchors);
-       CFReleaseSafe(trust->_chain);
-       CFReleaseSafe(trust->_publicKey);
-       CFReleaseSafe(trust->_details);
-       CFReleaseSafe(trust->_info);
-    CFReleaseSafe(trust->_exceptions);
-}
-
-static void SecTrustRegisterClass(void) {
-       static const CFRuntimeClass kSecTrustClass = {
-               0,                                                                                              /* version */
-        "SecTrust",                                     /* class name */
-               NULL,                                                                                   /* init */
-               NULL,                                                                                   /* copy */
-               SecTrustDestroy,                                /* dealloc */
-               NULL,                                           /* equal */
-               NULL,                                                                                   /* hash */
-               NULL,                                                                                   /* copyFormattingDesc */
-               SecTrustDescribe                                /* copyDebugDesc */
-       };
-
-    kSecTrustTypeID = _CFRuntimeRegisterClass(&kSecTrustClass);
-}
-
-/* Public API functions. */
-CFTypeID SecTrustGetTypeID(void) {
-    pthread_once(&kSecTrustRegisterClass, SecTrustRegisterClass);
-    return kSecTrustTypeID;
-}
-
-OSStatus SecTrustCreateWithCertificates(CFTypeRef certificates,
-    CFTypeRef policies, SecTrustRef *trust) {
-    OSStatus status = errSecParam;
-    CFAllocatorRef allocator = kCFAllocatorDefault;
-    CFArrayRef l_certs = NULL, l_policies = NULL;
-    SecTrustRef result = NULL;
-
-       check(certificates);
-       check(trust);
-    CFTypeID certType = CFGetTypeID(certificates);
-    if (certType == CFArrayGetTypeID()) {
-        /* We need at least 1 certificate. */
-        require_quiet(CFArrayGetCount(certificates) > 0, errOut);
-        l_certs = CFArrayCreateCopy(allocator, certificates);
-    } else if (certType == SecCertificateGetTypeID()) {
-        l_certs = CFArrayCreate(allocator, &certificates, 1,
-            &kCFTypeArrayCallBacks);
-    } else {
-        goto errOut;
-    }
-    if (!l_certs) {
-        status = errSecAllocate;
-        goto errOut;
-    }
-
-       if (!policies) {
-               CFTypeRef policy = SecPolicyCreateBasicX509();
-               l_policies = CFArrayCreate(allocator, &policy, 1,
-                       &kCFTypeArrayCallBacks);
-               CFRelease(policy);
-       } else if (CFGetTypeID(policies) == CFArrayGetTypeID()) {
-               l_policies = CFArrayCreateCopy(allocator, policies);
-       } else if (CFGetTypeID(policies) == SecPolicyGetTypeID()) {
-               l_policies = CFArrayCreate(allocator, &policies, 1,
-                       &kCFTypeArrayCallBacks);
-    } else {
-        goto errOut;
-    }
-    if (!l_policies) {
-        status = errSecAllocate;
-        goto errOut;
-    }
-
-    CFIndex size = sizeof(struct __SecTrust);
-    require_quiet(result = (SecTrustRef)_CFRuntimeCreateInstance(allocator,
-        SecTrustGetTypeID(), size - sizeof(CFRuntimeBase), 0), errOut);
-    memset((char*)result + sizeof(result->_base), 0,
-        sizeof(*result) - sizeof(result->_base));
-    status = errSecSuccess;
-
-errOut:
-    if (status) {
-        CFReleaseSafe(result);
-        CFReleaseSafe(l_certs);
-        CFReleaseSafe(l_policies);
-    } else {
-        result->_certificates = l_certs;
-        result->_policies = l_policies;
-        *trust = result;
-    }
-    return status;
-}
-
-static void SetTrustSetNeedsEvaluation(SecTrustRef trust) {
-    check(trust);
-    if (trust) {
-        trust->_trustResult = kSecTrustResultInvalid;
-    }
-}
-
-OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust,
-    Boolean anchorCertificatesOnly) {
-    if (!trust) {
-        return errSecParam;
-    }
-    SetTrustSetNeedsEvaluation(trust);
-    trust->_anchorsOnly = anchorCertificatesOnly;
-
-    return errSecSuccess;
-}
-
-OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust,
-    CFArrayRef anchorCertificates) {
-    if (!trust) {
-        return errSecParam;
-    }
-    SetTrustSetNeedsEvaluation(trust);
-    if (anchorCertificates)
-        CFRetain(anchorCertificates);
-    if (trust->_anchors)
-        CFRelease(trust->_anchors);
-    trust->_anchors = anchorCertificates;
-    trust->_anchorsOnly = (anchorCertificates != NULL);
-
-    return errSecSuccess;
-}
-
-OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust,
-    CFArrayRef *anchors) {
-       if (!trust|| !anchors) {
-               return errSecParam;
-       }
-       CFArrayRef anchorsArray = NULL;
-       if (trust->_anchors) {
-               anchorsArray = CFArrayCreateCopy(kCFAllocatorDefault, trust->_anchors);
-               if (!anchorsArray) {
-                       return errSecAllocate;
-               }
-       }
-       *anchors = anchorsArray;
-       return errSecSuccess;
-}
-
-OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData) {
-    if (!trust) {
-        return errSecParam;
-    }
-       SetTrustSetNeedsEvaluation(trust);
-       CFArrayRef responseArray = NULL;
-       if (responseData) {
-               if (CFGetTypeID(responseData) == CFArrayGetTypeID()) {
-            responseArray = CFArrayCreateCopy(kCFAllocatorDefault, responseData);
-        } else if (CFGetTypeID(responseData) == CFDataGetTypeID()) {
-            responseArray = CFArrayCreate(kCFAllocatorDefault, &responseData, 1,
-                                          &kCFTypeArrayCallBacks);
-        } else {
-            return errSecParam;
-        }
-    }
-       if (trust->_responses)
-               CFRelease(trust->_responses);
-       trust->_responses = responseArray;
-
-       return errSecSuccess;
-}
-
-OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate) {
-    if (!trust) {
-        return errSecParam;
-    }
-    SetTrustSetNeedsEvaluation(trust);
-    check(verifyDate);
-    CFRetainSafe(verifyDate);
-    if (trust->_verifyDate)
-        CFRelease(trust->_verifyDate);
-    trust->_verifyDate = verifyDate;
-
-    return errSecSuccess;
-}
-
-OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef newPolicies) {
-    if (!trust || !newPolicies) {
-        return errSecParam;
-    }
-    SetTrustSetNeedsEvaluation(trust);
-    check(newPolicies);
-
-    CFArrayRef policyArray = NULL;
-    if (CFGetTypeID(newPolicies) == CFArrayGetTypeID()) {
-               policyArray = CFArrayCreateCopy(kCFAllocatorDefault, newPolicies);
-       } else if (CFGetTypeID(newPolicies) == SecPolicyGetTypeID()) {
-               policyArray = CFArrayCreate(kCFAllocatorDefault, &newPolicies, 1,
-                       &kCFTypeArrayCallBacks);
-    } else {
-        return errSecParam;
-    }
-
-    if (trust->_policies)
-        CFRelease(trust->_policies);
-    trust->_policies = policyArray;
-
-    return errSecSuccess;
-}
-
-OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies) {
-       if (!trust|| !policies) {
-               return errSecParam;
-       }
-       if (!trust->_policies) {
-               return errSecInternal;
-       }
-       CFArrayRef policyArray = CFArrayCreateCopy(kCFAllocatorDefault, trust->_policies);
-       if (!policyArray) {
-               return errSecAllocate;
-       }
-       *policies = policyArray;
-       return errSecSuccess;
-}
-
-OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, Boolean allowFetch) {
-       if (!trust) {
-               return errSecParam;
-       }
-       trust->_networkPolicy = (allowFetch) ? useNetworkEnabled : useNetworkDisabled;
-       return errSecSuccess;
-}
-
-OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, Boolean *allowFetch) {
-       if (!trust || !allowFetch) {
-               return errSecParam;
-       }
-       Boolean allowed = false;
-       SecNetworkPolicy netPolicy = trust->_networkPolicy;
-       if (netPolicy == useNetworkDefault) {
-               // network fetch is enabled by default for SSL only
-               CFIndex idx, count = (trust->_policies) ? CFArrayGetCount(trust->_policies) : 0;
-               for (idx=0; idx<count; idx++) {
-                       SecPolicyRef policy = (SecPolicyRef)CFArrayGetValueAtIndex(trust->_policies, idx);
-                       if (policy) {
-                               CFDictionaryRef props = SecPolicyCopyProperties(policy);
-                               if (props) {
-                                       CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(props, kSecPolicyOid);
-                                       if (value) {
-                                               if (CFEqual(value, kSecPolicyAppleSSL)) {
-                                                       allowed = true;
-                                               }
-                                       }
-                                       CFRelease(props);
-                               }
-                       }
-               }
-       } else {
-               // caller has explicitly set the network policy
-               allowed = (netPolicy == useNetworkEnabled);
-       }
-       *allowFetch = allowed;
-       return errSecSuccess;
-}
-
-CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust) {
-    CFAbsoluteTime verifyTime;
-    if (trust && trust->_verifyDate) {
-        verifyTime = CFDateGetAbsoluteTime(trust->_verifyDate);
-    } else {
-        verifyTime = CFAbsoluteTimeGetCurrent();
-               /* Record the verifyDate we ended up using. */
-        if (trust) {
-            trust->_verifyDate = CFDateCreate(CFGetAllocator(trust), verifyTime);
-        }
-    }
-    return verifyTime;
-}
-
-CFArrayRef SecTrustGetDetails(SecTrustRef trust) {
-       if (!trust) {
-               return NULL;
-       }
-    SecTrustEvaluateIfNecessary(trust);
-    return trust->_details;
-}
-
-OSStatus SecTrustGetTrustResult(SecTrustRef trust,
-    SecTrustResultType *result) {
-       if (!trust || !result) {
-               return errSecParam;
-       }
-       *result = trust->_trustResult;
-       return errSecSuccess;
-}
-
-static CFStringRef kSecCertificateDetailSHA1Digest = CFSTR("SHA1Digest");
-
-static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix) {
-    if (!trust->_exceptions || ix >= CFArrayGetCount(trust->_exceptions))
-        return NULL;
-    CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(trust->_exceptions, ix);
-    if (CFGetTypeID(exception) != CFDictionaryGetTypeID())
-        return NULL;
-
-       SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
-    if (!certificate)
-        return NULL;
-
-    /* If the exception contains the current certificates 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;
-}
-
-struct SecTrustCheckExceptionContext {
-    CFDictionaryRef exception;
-    bool exceptionNotFound;
-};
-
-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;
-        }
-    } else {
-        cec->exceptionNotFound = true;
-    }
-}
-
-
-OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *result) {
-    if (!trust) {
-        return errSecParam;
-    }
-    OSStatus status = SecTrustEvaluateIfNecessary(trust);
-    if (status || !result)
-        return status;
-
-    /* post-process trust result based on exceptions */
-    SecTrustResultType trustResult = trust->_trustResult;
-    if (trustResult == kSecTrustResultUnspecified) {
-        /* If leaf is in exceptions -> proceed, otherwise unspecified. */
-        if (SecTrustGetExceptionForCertificateAtIndex(trust, 0))
-            trustResult = kSecTrustResultProceed;
-    } else if (trustResult == kSecTrustResultRecoverableTrustFailure) {
-        /* If we have exceptions get details and match to exceptions. */
-        CFIndex pathLength = CFArrayGetCount(trust->_details);
-        struct SecTrustCheckExceptionContext context = {};
-        CFIndex ix;
-        for (ix = 0; ix < pathLength; ++ix) {
-            CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(trust->_details, ix);
-
-                       if ((ix == 0) && CFDictionaryContainsKey(detail, kSecPolicyCheckBlackListedLeaf))
-                       {
-                               trustResult = kSecTrustResultFatalTrustFailure;
-                               goto DoneCheckingTrust;
-                       }
-
-                       if (CFDictionaryContainsKey(detail, kSecPolicyCheckBlackListedKey))
-                       {
-                               trustResult = kSecTrustResultFatalTrustFailure;
-                               goto DoneCheckingTrust;
-                       }
-
-            context.exception = SecTrustGetExceptionForCertificateAtIndex(trust, ix);
-            CFDictionaryApplyFunction(detail, SecTrustCheckException, &context);
-            if (context.exceptionNotFound) {
-                break;
-            }
-        }
-        if (!context.exceptionNotFound)
-            trustResult = kSecTrustResultProceed;
-    }
-DoneCheckingTrust:
-       trust->_trustResult = trustResult;
-
-#if DEBUG
-    /* log to syslog when there is a trust failure */
-    if (trustResult != kSecTrustResultProceed &&
-        trustResult != kSecTrustResultConfirm &&
-        trustResult != kSecTrustResultUnspecified) {
-        CFStringRef failureDesc = SecTrustCopyFailureDescription(trust);
-        secerror("%@", failureDesc);
-        CFRelease(failureDesc);
-    }
-#endif
-
-
-    *result = trustResult;
-
-    return status;
-}
-
-OSStatus SecTrustEvaluateAsync(SecTrustRef trust,
-       dispatch_queue_t queue, SecTrustCallback result)
-{
-       dispatch_async(queue, ^{
-               SecTrustResultType trustResult;
-               if (errSecSuccess != SecTrustEvaluate(trust, &trustResult)) {
-                       trustResult = kSecTrustResultInvalid;
-               }
-               result(trust, trustResult);
-       });
-       return errSecSuccess;
-}
-
-static bool SecXPCDictionarySetCertificates(xpc_object_t message, const char *key, CFArrayRef certificates, CFErrorRef *error) {
-    xpc_object_t xpc_certificates = SecCertificateArrayCopyXPCArray(certificates, error);
-    if (!xpc_certificates)
-        return false;
-
-    xpc_dictionary_set_value(message, key, xpc_certificates);
-    xpc_release(xpc_certificates);
-
-    return true;
-}
-
-static bool SecXPCDictionarySetPolicies(xpc_object_t message, const char *key, CFArrayRef policies, CFErrorRef *error) {
-    xpc_object_t xpc_policies = SecPolicyArrayCopyXPCArray(policies, error);
-    if (!xpc_policies)
-        return false;
-    xpc_dictionary_set_value(message, key, xpc_policies);
-    xpc_release(xpc_policies);
-    return true;
-}
-
-static bool SecXPCDictionaryCopyChainOptional(xpc_object_t message, const char *key, SecCertificatePathRef *path, CFErrorRef *error) {
-    xpc_object_t xpc_path = xpc_dictionary_get_value(message, key);
-    if (!xpc_path) {
-        *path = NULL;
-        return true;
-    }
-    *path = SecCertificatePathCreateWithXPCArray(xpc_path, error);
-    return *path;
-}
-
-static int SecXPCDictionaryGetNonZeroInteger(xpc_object_t message, const char *key, CFErrorRef *error) {
-    int64_t value = xpc_dictionary_get_int64(message, key);
-    if (!value) {
-        SecError(errSecInternal, error, CFSTR("object for key %s is 0"), key);
-    }
-    return (int)value;
-}
-
-static SecTrustResultType certs_anchors_bool_policies_date_ag_to_details_info_chain_int_error_request(enum SecXPCOperation op, CFArrayRef certificates, CFArrayRef anchors, bool anchorsOnly, CFArrayRef policies, CFAbsoluteTime verifyTime, __unused CFArrayRef accessGroups, CFArrayRef *details, CFDictionaryRef *info, SecCertificatePathRef *chain, CFErrorRef *error)
-{
-    __block SecTrustResultType tr = kSecTrustResultInvalid;
-    securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
-        if (!SecXPCDictionarySetCertificates(message, kSecTrustCertificatesKey, certificates, error))
-            return false;
-        if (anchors && !SecXPCDictionarySetCertificates(message, kSecTrustAnchorsKey, anchors, error))
-            return false;
-        if (anchorsOnly)
-            xpc_dictionary_set_bool(message, kSecTrustAnchorsOnlyKey, anchorsOnly);
-        if (!SecXPCDictionarySetPolicies(message, kSecTrustPoliciesKey, policies, error))
-            return false;
-        xpc_dictionary_set_double(message, kSecTrustVerifyDateKey, verifyTime);
-        return true;
-    }, ^bool(xpc_object_t response, CFErrorRef *error) {
-        secdebug("trust", "response: %@", response);
-        return SecXPCDictionaryCopyArrayOptional(response, kSecTrustDetailsKey, details, error) &&
-        SecXPCDictionaryCopyDictionaryOptional(response, kSecTrustInfoKey, info, error) &&
-        SecXPCDictionaryCopyChainOptional(response, kSecTrustChainKey, chain, error) &&
-        ((tr = SecXPCDictionaryGetNonZeroInteger(response, kSecTrustResultKey, error)) != kSecTrustResultInvalid);
-    });
-    return tr;
-}
-
-static OSStatus SecTrustEvaluateIfNecessary(SecTrustRef trust) {
-    check(trust);
-    if (!trust)
-        return errSecParam;
-
-    if (trust->_trustResult != kSecTrustResultInvalid)
-        return errSecSuccess;
-
-    trust->_trustResult = kSecTrustResultOtherError; /* to avoid potential recursion */
-
-    CFReleaseNull(trust->_chain);
-    CFReleaseNull(trust->_details);
-    CFReleaseNull(trust->_info);
-
-    /* @@@ Consider an optimization where we keep a side dictionary with the SHA1 hash of ever SecCertificateRef we send, so we only send potential duplicates once, and have the server respond with either just the SHA1 hash of a certificate, or the complete certificate in the response depending on whether the client already sent it, so we don't send back certificates to the client it already has. */
-    return SecOSStatusWith(^bool (CFErrorRef *error) {
-        trust->_trustResult = SECURITYD_XPC(sec_trust_evaluate, certs_anchors_bool_policies_date_ag_to_details_info_chain_int_error_request, trust->_certificates, trust->_anchors, trust->_anchorsOnly, trust->_policies, SecTrustGetVerifyTime(trust), SecAccessGroupsGetCurrent(), &trust->_details, &trust->_info, &trust->_chain, error);
-        if (trust->_trustResult == kSecTrustResultInvalid /* TODO check domain */ &&
-            SecErrorGetOSStatus(*error) == errSecNotAvailable &&
-            CFArrayGetCount(trust->_certificates)) {
-        /* We failed to talk to securityd.  The only time this should
-           happen is when we are running prior to launchd enabling
-           registration of services.  This currently happens when we
-           are running from the ramdisk.   To make ASR happy we initialize
-           _chain and return success with a failure as the trustResult, to
-           make it seem like we did a cert evaluation, so ASR can extract
-           the public key from the leaf. */
-            trust->_chain = SecCertificatePathCreate(NULL, (SecCertificateRef)CFArrayGetValueAtIndex(trust->_certificates, 0));
-            if (error)
-                CFReleaseNull(*error);
-            return true;
-    }
-        return trust->_trustResult != kSecTrustResultInvalid;
-    });
-    }
-
-/* Helper for the qsort below. */
-static int compare_strings(const void *a1, const void *a2) {
-    CFStringRef s1 = *(CFStringRef *)a1;
-    CFStringRef s2 = *(CFStringRef *)a2;
-    return (int) CFStringCompare(s1, s2, kCFCompareForcedOrdering);
-}
-
-CFStringRef SecTrustCopyFailureDescription(SecTrustRef trust) {
-    CFMutableStringRef reason = CFStringCreateMutable(NULL, 0);
-    CFArrayRef details = SecTrustGetDetails(trust);
-    CFIndex pathLength = details ? CFArrayGetCount(details) : 0;
-    for (CFIndex ix = 0; ix < pathLength; ++ix) {
-        CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
-        CFIndex dCount = CFDictionaryGetCount(detail);
-        if (dCount) {
-            if (ix == 0)
-                CFStringAppend(reason, CFSTR(" [leaf"));
-            else if (ix == pathLength - 1)
-                CFStringAppend(reason, CFSTR(" [root"));
-            else
-                CFStringAppendFormat(reason, NULL, CFSTR(" [ca%" PRIdCFIndex ), ix);
-
-            const void *keys[dCount];
-            CFDictionaryGetKeysAndValues(detail, &keys[0], NULL);
-            qsort(&keys[0], dCount, sizeof(keys[0]), compare_strings);
-            for (CFIndex kix = 0; kix < dCount; ++kix) {
-                CFStringRef key = keys[kix];
-                const void *value = CFDictionaryGetValue(detail, key);
-                CFStringAppendFormat(reason, NULL, CFSTR(" %@%@"), key,
-                                     (CFGetTypeID(value) == CFBooleanGetTypeID()
-                                      ? CFSTR("") : value));
-            }
-            CFStringAppend(reason, CFSTR("]"));
-        }
-    }
-    return reason;
-}
-
-SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) {
-    if (!trust) {
-        return NULL;
-    }
-       if (!trust->_publicKey) {
-        if (!trust->_chain) {
-            /* Trust hasn't been evaluated yet, first attempt to retrieve public key from leaf cert as is. */
-            trust->_publicKey = SecCertificateCopyPublicKey(SecTrustGetCertificateAtIndex(trust, 0));
-#if 0
-            if (!trust->_publicKey) {
-                /* If this fails use the passed in certs in order as if they are a valid cert path an attempt to extract the key. */
-                SecCertificatePathRef path;
-                // SecCertificatePathCreateWithArray Would have crashed if this code was every called
-                // since it expected an array of CFDataRefs not an array of certificates.
-                path = SecCertificatePathCreateWithArray(trust->_certificates);
-                trust->_publicKey = SecCertificatePathCopyPublicKeyAtIndex(path, 0);
-                CFRelease(path);
-            }
-#endif
-            if (!trust->_publicKey) {
-                /* Last resort, we evaluate the trust to get a _chain. */
-                SecTrustEvaluateIfNecessary(trust);
-            }
-        }
-        if (trust->_chain) {
-            trust->_publicKey = SecCertificatePathCopyPublicKeyAtIndex(trust->_chain, 0);
-        }
-       }
-
-       if (trust->_publicKey)
-               CFRetain(trust->_publicKey);
-
-       return trust->_publicKey;
-}
-
-CFIndex SecTrustGetCertificateCount(SecTrustRef trust) {
-    if (!trust) {
-        return 0;
-    }
-    SecTrustEvaluateIfNecessary(trust);
-       return (trust->_chain) ? SecCertificatePathGetCount(trust->_chain) : 1;
-}
-
-SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust,
-    CFIndex ix) {
-    if (!trust) {
-        return NULL;
-    }
-    if (ix == 0) {
-        return (SecCertificateRef)CFArrayGetValueAtIndex(trust->_certificates, 0);
-    }
-    SecTrustEvaluateIfNecessary(trust);
-    return (trust->_chain) ? SecCertificatePathGetCertificateAtIndex(trust->_chain, ix) : NULL;
-}
-
-CFDictionaryRef SecTrustCopyInfo(SecTrustRef trust) {
-    if (!trust) {
-        return NULL;
-    }
-    SecTrustEvaluateIfNecessary(trust);
-    CFDictionaryRef info = trust->_info;
-    if (info)
-        CFRetain(info);
-    return info;
-}
-
-CFDataRef SecTrustCopyExceptions(SecTrustRef trust) {
-    CFArrayRef details = SecTrustGetDetails(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);
-            CFDictionaryAddValue(exception, kSecCertificateDetailSHA1Digest, digest);
-        } 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);
-        CFRelease(exception);
-    }
-
-    /* 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;
-        }
-    }
-
-    CFDataRef encodedExceptions = CFPropertyListCreateData(kCFAllocatorDefault,
-        exceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL);
-    CFRelease(exceptions);
-
-    return encodedExceptions;
-}
-
-bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions) {
-       if (!trust) {
-               return false;
-       }
-       CFArrayRef exceptions = NULL;
-
-       if (NULL != encodedExceptions) {
-               exceptions = CFPropertyListCreateWithData(kCFAllocatorDefault,
-                       encodedExceptions, kCFPropertyListImmutable, NULL, NULL);
-       }
-
-    if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) {
-        CFRelease(exceptions);
-        exceptions = NULL;
-    }
-    CFReleaseSafe(trust->_exceptions);
-    trust->_exceptions = exceptions;
-
-    /* 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. */
-    CFReleaseNull(trust->_exceptions);
-    return false;
-}
-
-CFArrayRef SecTrustCopySummaryPropertiesAtIndex(SecTrustRef trust, CFIndex ix) {
-    CFMutableArrayRef summary;
-       SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
-    summary = SecCertificateCopySummaryProperties(certificate,
-        SecTrustGetVerifyTime(trust));
-    /* FIXME Add more details in the failure case. */
-
-    return summary;
-}
-
-CFArrayRef SecTrustCopyDetailedPropertiesAtIndex(SecTrustRef trust, CFIndex ix) {
-    CFArrayRef summary;
-       SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
-    summary = SecCertificateCopyProperties(certificate);
-
-    return summary;
-}
-
-#if 0
-
-
-
-/* Valid chain.
-   Can be on any non root cert in the chain.
-   Priority: Top down
-   Short circuit: Yes (No other errors matter after this one)
-   Non recoverable error
-   Trust UI: Invalid certificate chain linkage
-   Cert UI: Invalid linkage to parent certificate
-*/
-CFStringRef kSecPolicyCheckIdLinkage = CFSTR("IdLinkage");
-
-/* X.509 required checks.
-   Can be on any cert in the chain
-   Priority: Top down
-   Short circuit: Yes (No other errors matter after this one)
-   Non recoverable error
-   Trust UI: (One or more) unsupported critical extensions found.
-*/
-/* If we have no names for the extention oids use:
-   Cert UI: One or more unsupported critical extensions found (Non recoverable error).
-   Cert UI: Unsupported 'foo', 'bar', baz' critical extensions found.
-*/
-CFStringRef kSecPolicyCheckCriticalExtensions = CFSTR("CriticalExtensions");
-/* Cert UI: Unsupported critical Qualified Certificate Statements extension found (Non recoverable error). */
-CFStringRef kSecPolicyCheckQualifiedCertStatements = CFSTR("QualifiedCertStatements");
-/* Cert UI: Certificate has an empty subject (and no critial subjectAltname). */
-
-/* Trusted root.
-   Only apply to the anchor.
-   Priority: N/A
-   Short circuit: No (Under discussion)
-   Recoverable
-   Trust UI: Root certificate is not trusted (for this policy/app/host/whatever?)
-   Cert UI: Not a valid anchor
-*/
-CFStringRef kSecPolicyCheckAnchorTrusted = CFSTR("AnchorTrusted");
-CFStringRef kSecPolicyCheckAnchorSHA1 = CFSTR("AnchorSHA1");
-
-/* Binding.
-   Only applies to leaf
-   Priority: N/A
-   Short Circuit: No
-   Recoverable
-   Trust UI: (Hostname|email address) mismatch
-*/
-CFStringRef kSecPolicyCheckSSLHostname = CFSTR("SSLHostname");
-
-/* Policy specific checks.
-   Can be on any cert in the chain
-   Priority: Top down
-   Short Circuit: No
-   Recoverable
-   Trust UI: Certificate chain is not valid for the current policy.
-   OR: (One or more) certificates in the chain are not valid for the current policy/application
-*/
-CFStringRef kSecPolicyCheckNonEmptySubject = CFSTR("NonEmptySubject");
-/* Cert UI: Non CA certificate used as CA.
-   Cert UI: CA certificate used as leaf.
-   Cert UI: Cert chain length exceeded.
-   Cert UI: Basic constraints extension not critical (non fatal).
-   Cert UI: Leaf certificate has basic constraints extension (non fatal).
- */
-CFStringRef kSecPolicyCheckBasicContraints = CFSTR("BasicContraints");
-CFStringRef kSecPolicyCheckKeyUsage = CFSTR("KeyUsage");
-CFStringRef kSecPolicyCheckExtendedKeyUsage = CFSTR("ExtendedKeyUsage");
-/* Checks that the issuer of the leaf has exactly one Common Name and that it
-   matches the specified string. */
-CFStringRef kSecPolicyCheckIssuerCommonName = CFSTR("IssuerCommonName");
-/* Checks that the leaf has exactly one Common Name and that it has the
-   specified string as a prefix. */
-CFStringRef kSecPolicyCheckSubjectCommonNamePrefix = CFSTR("SubjectCommonNamePrefix");
-/* Check that the certificate chain length matches the specificed CFNumberRef
-   length. */
-CFStringRef kSecPolicyCheckChainLength = CFSTR("ChainLength");
-CFStringRef kSecPolicyCheckNotValidBefore = CFSTR("NotValidBefore");
-
-/* Expiration.
-   Can be on any cert in the chain
-   Priority: Top down
-   Short Circuit: No
-   Recoverable
-   Trust UI: One or more certificates have expired or are not valid yet.
-   OS: The (root|intermidate|leaf) certificate (expired on 'date'|is not valid until 'date')
-   Cert UI: Certificate (expired on 'date'|is not valid until 'date')
-*/
-CFStringRef kSecPolicyCheckValidIntermediates = CFSTR("ValidIntermediates");
-CFStringRef kSecPolicyCheckValidLeaf = CFSTR("ValidLeaf");
-CFStringRef kSecPolicyCheckValidRoot = CFSTR("ValidRoot");
-
-#endif
-
-struct TrustFailures {
-    bool badLinkage;
-    bool unknownCritExtn;
-    bool untrustedAnchor;
-    bool hostnameMismatch;
-    bool policyFail;
-    bool invalidCert;
-};
-
-static void applyDetailProperty(const void *_key, const void *_value,
-    void *context) {
-    CFStringRef key = (CFStringRef)_key;
-    struct TrustFailures *tf = (struct TrustFailures *)context;
-    if (CFGetTypeID(_value) != CFBooleanGetTypeID()) {
-        /* Value isn't a CFBooleanRef, oh no! */
-        return;
-    }
-    CFBooleanRef value = (CFBooleanRef)_value;
-    if (CFBooleanGetValue(value)) {
-        /* Not an actual failure so we don't report it. */
-        return;
-    }
-
-    /* @@@ FIXME: Report a different return value when something is in the
-       details but masked out by an exception and use that below for display
-       purposes. */
-    if (CFEqual(key, kSecPolicyCheckIdLinkage)) {
-        tf->badLinkage = true;
-    } else if (CFEqual(key, kSecPolicyCheckCriticalExtensions)
-        || CFEqual(key, kSecPolicyCheckQualifiedCertStatements)) {
-        tf->unknownCritExtn = true;
-    } else if (CFEqual(key, kSecPolicyCheckAnchorTrusted)
-        || CFEqual(key, kSecPolicyCheckAnchorSHA1)) {
-        tf->untrustedAnchor = true;
-    } else if (CFEqual(key, kSecPolicyCheckSSLHostname)) {
-        tf->hostnameMismatch = true;
-    } else if (CFEqual(key, kSecPolicyCheckValidIntermediates)
-        || CFEqual(key, kSecPolicyCheckValidLeaf)
-        || CFEqual(key, kSecPolicyCheckValidLeaf)) {
-        tf->invalidCert = true;
-    } else
-    /* Anything else is a policy failure. */
-#if 0
-    if (CFEqual(key, kSecPolicyCheckNonEmptySubject)
-        || CFEqual(key, kSecPolicyCheckBasicContraints)
-        || CFEqual(key, kSecPolicyCheckKeyUsage)
-        || CFEqual(key, kSecPolicyCheckExtendedKeyUsage)
-        || CFEqual(key, kSecPolicyCheckIssuerCommonName)
-        || CFEqual(key, kSecPolicyCheckSubjectCommonNamePrefix)
-        || CFEqual(key, kSecPolicyCheckChainLength)
-        || CFEqual(key, kSecPolicyCheckNotValidBefore))
-#endif
-    {
-        tf->policyFail = true;
-    }
-}
-
-static void appendError(CFMutableArrayRef properties, CFStringRef error) {
-    CFStringRef localizedError = SecFrameworkCopyLocalizedString(error,
-        CFSTR("SecCertificate"));
-    appendProperty(properties, kSecPropertyTypeError, NULL, NULL,
-                   localizedError);
-    CFReleaseNull(localizedError);
-}
-
-CFArrayRef SecTrustCopyProperties(SecTrustRef trust) {
-    CFArrayRef details = SecTrustGetDetails(trust);
-    if (!details)
-        return NULL;
-
-    struct TrustFailures tf = {};
-
-    CFIndex ix, count = CFArrayGetCount(details);
-    for (ix = 0; ix < count; ++ix) {
-        CFDictionaryRef detail = (CFDictionaryRef)
-            CFArrayGetValueAtIndex(details, ix);
-        /* We now have a detail dictionary for certificate at index ix, with
-           a key value pair for each failed policy check.  Let's convert it
-           from Ro-Man form into something a Hu-Man can understand. */
-        CFDictionaryApplyFunction(detail, applyDetailProperty, &tf);
-    }
-
-    CFMutableArrayRef properties = CFArrayCreateMutable(kCFAllocatorDefault, 0,
-        &kCFTypeArrayCallBacks);
-    /* The badLinkage and unknownCritExtn failures are short circuited, since
-       you can't recover from those errors. */
-    if (tf.badLinkage) {
-        appendError(properties, CFSTR("Invalid certificate chain linkage."));
-    } else if (tf.unknownCritExtn) {
-        appendError(properties, CFSTR("One or more unsupported critical extensions found."));
-    } else {
-        if (tf.untrustedAnchor) {
-            appendError(properties, CFSTR("Root certificate is not trusted."));
-        }
-        if (tf.hostnameMismatch) {
-            appendError(properties, CFSTR("Hostname mismatch."));
-        }
-        if (tf.policyFail) {
-            appendError(properties, CFSTR("Policy requirements not met."));
-        }
-        if (tf.invalidCert) {
-            appendError(properties, CFSTR("One or more certificates have expired or are not valid yet."));
-        }
-    }
-
-    if (CFArrayGetCount(properties) == 0) {
-        /* The certificate chain is trusted, return an empty plist */
-        CFReleaseNull(properties);
-    }
-
-    return properties;
-}
-
-CFDictionaryRef SecTrustCopyResult(SecTrustRef trust) {
-       // Builds and returns a dictionary of evaluation results.
-       if (!trust) {
-               return NULL;
-       }
-       CFMutableDictionaryRef results = CFDictionaryCreateMutable(NULL, 0,
-                       &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
-       // kSecTrustResultDetails (per-cert results)
-       CFArrayRef details = SecTrustGetDetails(trust);
-       if (details) {
-               CFDictionarySetValue(results, (const void *)kSecTrustResultDetails, (const void *)details);
-       }
-
-       // kSecTrustResultValue (overall trust result)
-       CFNumberRef numValue = CFNumberCreate(NULL, kCFNumberSInt32Type, &trust->_trustResult);
-       if (numValue) {
-               CFDictionarySetValue(results, (const void *)kSecTrustResultValue, (const void *)numValue);
-               CFRelease(numValue);
-       }
-       if (trust->_trustResult == kSecTrustResultInvalid || !trust->_info)
-               return results; // we have nothing more to add
-
-       // kSecTrustEvaluationDate
-       CFDateRef evaluationDate = trust->_verifyDate;
-       if (evaluationDate) {
-               CFDictionarySetValue(results, (const void *)kSecTrustEvaluationDate, (const void *)evaluationDate);
-       }
-
-       // kSecTrustExtendedValidation, kSecTrustOrganizationName
-       CFDictionaryRef info = trust->_info;
-       if (info) {
-               CFBooleanRef evValue;
-               if (CFDictionaryGetValueIfPresent(info, kSecTrustInfoExtendedValidationKey, (const void **)&evValue)) {
-                       CFDictionarySetValue(results, (const void *)kSecTrustExtendedValidation, (const void *)evValue);
-               }
-               CFStringRef organizationName;
-               if (CFDictionaryGetValueIfPresent(info, kSecTrustInfoCompanyNameKey, (const void **)&organizationName)) {
-                       CFDictionarySetValue(results, (const void *)kSecTrustOrganizationName, (const void *)organizationName);
-               }
-       }
-
-#if 0
-//FIXME: need to add revocation results here
-       // kSecTrustRevocationChecked, kSecTrustRevocationValidUntilDate
-       CFTypeRef expirationDate;
-       if (CFDictionaryGetValueIfPresent(mExtendedResult, kSecTrustExpirationDate, (const void **)&expirationDate)) {
-               CFDictionarySetValue(results, (const void *)kSecTrustRevocationValidUntilDate, (const void *)expirationDate);
-               CFDictionarySetValue(results, (const void *)kSecTrustRevocationChecked, (const void *)kCFBooleanTrue);
-       }
-#endif
-
-       return results;
-}
-
-// Return 0 upon error.
-static int to_int_error_request(enum SecXPCOperation op, CFErrorRef *error) {
-    __block int64_t result = 0;
-    securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
-        result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
-        if (!result)
-            return SecError(errSecInternal, error, CFSTR("int64 missing in response"));
-        return true;
-    });
-    return (int)result;
-}
-
-// version 0 -> error, so we need to start at version 1 or later.
-OSStatus SecTrustGetOTAPKIAssetVersionNumber(int* versionNumber)
-{
-    return SecOSStatusWith(^bool(CFErrorRef *error) {
-        if (!versionNumber)
-            return SecError(errSecParam, error, CFSTR("versionNumber is NULL"));
-
-        return (*versionNumber = SECURITYD_XPC(sec_ota_pki_asset_version, to_int_error_request, error)) != 0;
-    });
-}
-
-#define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); }
-
-static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *key, xpc_type_t type)
-{
-    xpc_object_t value = xpc_dictionary_get_value(dictionary, key);
-
-    return value && (xpc_get_type(value) == type);
-}
-
-OSStatus SecTrustOTAPKIGetUpdatedAsset(int* didUpdateAsset)
-{
-       CFErrorRef error = NULL;
-       do_if_registered(sec_ota_pki_get_new_asset, &error);
-
-       int64_t num = 0;
-    xpc_object_t message = securityd_create_message(kSecXPCOpOTAPKIGetNewAsset, &error);
-    if (message)
-       {
-        xpc_object_t response = securityd_message_with_reply_sync(message, &error);
-
-        if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64))
-               {
-            num = (int64_t) xpc_dictionary_get_int64(response, kSecXPCKeyResult);
-                       xpc_release(response);
-        }
-
-        xpc_release(message);
-       }
-
-       if (NULL != didUpdateAsset)
-       {
-               *didUpdateAsset = (int)num;
-       }
-       return noErr;
-}
-
-
-#if 0
-// MARK: -
-// MARK: SecTrustNode
-/********************************************************
- **************** SecTrustNode object *******************
- ********************************************************/
-typedef uint8_t SecFetchingState;
-enum {
-    kSecFetchingStatePassedIn = 0,
-    kSecFetchingStateLocal,
-    kSecFetchingStateFromURL,
-    kSecFetchingStateDone,
-};
-
-typedef uint8_t SecTrustState;
-enum {
-    kSecTrustStateUnknown = 0,
-    kSecTrustStateNotSigner,
-    kSecTrustStateValidSigner,
-};
-
-typedef struct __SecTrustNode *SecTrustNodeRef;
-struct __SecTrustNode {
-       SecTrustNodeRef         _child;
-       SecCertificateRef       _certificate;
-
-    /* Cached information about _certificate */
-    bool                _isAnchor;
-    bool                _isSelfSigned;
-
-    /* Set of all certificates we have ever considered as a parent.  We use
-       this to avoid having to recheck certs when we go to the next phase. */
-    CFMutableSet        _certificates;
-
-    /* Parents that are still partial chains we haven't yet considered. */
-    CFMutableSet        _partials;
-    /* Parents that are still partial chains we have rejected.  We reconsider
-      these if we get to the final phase and we still haven't found a valid
-      candidate. */
-    CFMutableSet        _rejected_partials;
-
-    /* Parents that are complete chains we haven't yet considered. */
-    CFMutableSet        _candidates;
-    /* Parents that are complete chains we have rejected. */
-    CFMutableSet        _rejected_candidates;
-
-    /* State of candidate fetching. */
-    SecFetchingState    _fetchingState;
-
-    /* Trust state of _candidates[_candidateIndex] */
-    SecTrustState       _trustState;
-};
-typedef struct __SecTrustNode SecTrustNode;
-
-/* CFRuntime registration data. */
-static pthread_once_t kSecTrustNodeRegisterClass = PTHREAD_ONCE_INIT;
-static CFTypeID kSecTrustNodeTypeID = _kCFRuntimeNotATypeID;
-
-/* Forward declarations of static functions. */
-static CFStringRef SecTrustNodeDescribe(CFTypeRef cf);
-static void SecTrustNodeDestroy(CFTypeRef cf);
-
-/* Static functions. */
-static CFStringRef SecTrustNodeDescribe(CFTypeRef cf) {
-    SecTrustNodeRef node = (SecTrustNodeRef)cf;
-    return CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
-        CFSTR("<SecTrustNodeRef: %p>"), node);
-}
-
-static void SecTrustNodeDestroy(CFTypeRef cf) {
-    SecTrustNodeRef trust = (SecTrustNodeRef)cf;
-    if (trust->_child) {
-        free(trust->_child);
-    }
-    if (trust->_certificate) {
-        free(trust->_certificate);
-    }
-       if (trust->_candidates) {
-               CFRelease(trust->_candidates);
-       }
-}
-
-static void SecTrustNodeRegisterClass(void) {
-       static const CFRuntimeClass kSecTrustNodeClass = {
-               0,                                                                                              /* version */
-        "SecTrustNode",                                 /* class name */
-               NULL,                                                                                   /* init */
-               NULL,                                                                                   /* copy */
-               SecTrustNodeDestroy,                            /* dealloc */
-               NULL,                                           /* equal */
-               NULL,                                                                                   /* hash */
-               NULL,                                                                                   /* copyFormattingDesc */
-               SecTrustNodeDescribe                            /* copyDebugDesc */
-       };
-
-    kSecTrustNodeTypeID = _CFRuntimeRegisterClass(&kSecTrustNodeClass);
-}
-
-/* SecTrustNode API functions. */
-CFTypeID SecTrustNodeGetTypeID(void) {
-    pthread_once(&kSecTrustNodeRegisterClass, SecTrustNodeRegisterClass);
-    return kSecTrustNodeTypeID;
-}
-
-SecTrustNodeRef SecTrustNodeCreate(SecTrustRef trust,
-    SecCertificateRef certificate, SecTrustNodeRef child) {
-    CFAllocatorRef allocator = kCFAllocatorDefault;
-       check(trust);
-       check(certificate);
-
-    CFIndex size = sizeof(struct __SecTrustNode);
-    SecTrustNodeRef result = (SecTrustNodeRef)_CFRuntimeCreateInstance(
-               allocator, SecTrustNodeGetTypeID(), size - sizeof(CFRuntimeBase), 0);
-       if (!result)
-        return NULL;
-
-    memset((char*)result + sizeof(result->_base), 0,
-        sizeof(*result) - sizeof(result->_base));
-    if (child) {
-        CFRetain(child);
-        result->_child = child;
-    }
-    CFRetain(certificate);
-    result->_certificate = certificate;
-    result->_isAnchor = SecTrustCertificateIsAnchor(certificate);
-
-    return result;
-}
-
-SecCertificateRef SecTrustGetCertificate(SecTrustNodeRef node) {
-       check(node);
-    return node->_certificate;
-}
-
-CFArrayRef SecTrustNodeCopyProperties(SecTrustNodeRef node,
-    SecTrustRef trust) {
-       check(node);
-    check(trust);
-    CFMutableArrayRef summary = SecCertificateCopySummaryProperties(
-        node->_certificate, SecTrustGetVerifyTime(trust));
-    /* FIXME Add more details in the failure case. */
-    return summary;
-}
-
-/* Attempt to verify this node's signature chain down to the child. */
-SecTrustState SecTrustNodeVerifySignatureChain(SecTrustNodeRef node) {
-    /* FIXME */
-    return kSecTrustStateUnknown;
-}
-
-
-/* See if the next candidate works. */
-SecTrustNodeRef SecTrustNodeCopyNextCandidate(SecTrustNodeRef node,
-    SecTrustRef trust, SecFetchingState fetchingState) {
-    check(node);
-    check(trust);
-
-    CFAbsoluteTime verifyTime = SecTrustGetVerifyTime(trust);
-
-    for (;;) {
-        /* If we have any unconsidered candidates left check those first. */
-        while (node->_candidateIndex < CFArrayGetCount(node->_candidates)) {
-            SecCertificateRef candidate = (SecCertificateRef)
-                CFArrayGetValueAtIndex(node->_candidates, node->_candidateIndex);
-            if (node->_fetchingState != kSecFetchingStateDone) {
-                /* If we still have potential sources to fetch other candidates
-                   from we ignore expired candidates. */
-                if (!SecCertificateIsValidOn(candidate, verifyTime)) {
-                    node->_candidateIndex++;
-                    continue;
-                }
-            }
-
-            SecTrustNodeRef parent = SecTrustNodeCreate(candidate, node);
-            CFArrayRemoveValueAtIndex(node->_candidates, node->_candidateIndex);
-            if (SecTrustNodeVerifySignatureChain(parent) ==
-                kSecTrustStateNotSigner) {
-                /* This candidate parent is not a valid signer of its
-                   child. */
-                CFRelease(parent);
-                /* If another signature failed further down the chain we need
-                   to backtrack down to whatever child is still a valid
-                   candidate and has additional candidates to consider.
-                   @@@ We really want to make the fetchingState a global of
-                   SecTrust itself as well and not have any node go beyond the
-                   current state of SecTrust if there are other (read cheap)
-                   options to consider. */
-                continue;
-            }
-            return parent;
-        }
-
-        /* We've run out of candidates in our current state so let's try to
-           find some more. Note we fetch candidates in increasing order of
-           cost in the hope we won't ever get to the more expensive fetching
-           methods.  */
-        SecCertificateRef certificate = node->_certificate;
-        switch (node->_fetchingState) {
-        case kSecFetchingStatePassedIn:
-            /* Get the list of candidates from SecTrust. */
-            CFDataRef akid = SecCertificateGetAuthorityKeyID(certificate);
-            if (akid) {
-                SecTrustAppendCandidatesWithAuthorityKeyID(akid, node->_candidates);
-            } else {
-                CFDataRef issuer =
-                    SecCertificateGetNormalizedIssuerContent(certificate);
-                SecTrustAppendCandidatesWithSubject(issuer, node->_candidates);
-            }
-            node->_fetchingState = kSecFetchingStateLocal;
-            break;
-        case kSecFetchingStateLocal:
-            /* Lookup candidates in the local database. */
-            node->_fetchingState = kSecFetchingStateFromURL;
-            break;
-        case kSecFetchingStateFromURL:
-            node->_fetchingState = kSecFetchingStateCheckExpired;
-            break;
-        case kSecFetchingStateCheckExpired:
-            /* Time to start considering expired candidates as well. */
-            node->_candidateIndex = 0;
-            node->_fetchingState = kSecFetchingStateDone;
-            break;
-        case kSecFetchingStateDone;
-            return NULL;
-        }
-    }
-
-    CFAllocatorRef allocator = CFGetAllocator(node);
-
-    /* A trust node has a number of states.
-       1) Look for issuing certificates by asking SecTrust about known
-          parent certificates.
-       2) Look for issuing certificates in certificate databases (keychains)
-       3) Look for issuing certificates by going out to the web if the nodes
-          certificate has a issuer location URL.
-       4) Look through expired or not yet valid candidates we have put aside.
-
-       We go though the stages 1 though 3 looking for candidate issuer
-       certificates.  If a candidate certificate is not valid at verifyTime
-       we put it in a to be examined later queue.  If a candidate certificate
-       is valid we verify if it actually signed our certificate (if possible).
-       If not we discard it and continue on to the next candidate certificate.
-       If it is we return a new SecTrustNodeRef for that certificate.  */
-
-    CFMutableArrayRef issuers = CFArrayCreateMutable(allocator, 0,
-        &kCFTypeArrayCallBacks);
-
-    /* Find a node's parent. */
-    certificate = node->_certificate;
-    CFDataRef akid = SecCertificateGetAuthorityKeyID(certificate);
-    CFTypeRef candidates = NULL;
-    if (akid) {
-        candidates = (CFTypeRef)CFDictionaryGetValueForKey(skidDict, akid);
-        if (candidates) {
-            addValidIssuersFrom(issuers, certificate, candidates, true);
-        }
-    }
-    if (!candidates) {
-        CFDataRef issuer =
-            SecCertificateGetNormalizedIssuerContent(certificate);
-        candidates = (CFTypeRef)
-            CFDictionaryGetValueForKey(subjectDict, issuer);
-        addValidIssuersFrom(issuers, certificate, candidates, false);
-    }
-
-    if (CFArrayGetCount(issuers) == 0) {
-        /* O no! we can't find an issuer for this certificate.  Let's see
-           if we can find one in the local database. */
-    }
-
-    return errSecSuccess;
-}
-
-CFArrayRef SecTrustNodeCopyNextChain(SecTrustNodeRef node,
-    SecTrustRef trust) {
-    /* Return the next full chain that isn't a reject unless we are in
-       a state where we consider returning rejects. */
-
-    switch (node->_fetchingState) {
-    case kSecFetchingStatePassedIn:
-        /* Get the list of candidates from SecTrust. */
-        CFDataRef akid = SecCertificateGetAuthorityKeyID(certificate);
-        if (akid) {
-            SecTrustAppendCandidatesWithAuthorityKeyID(akid, node->_candidates);
-        } else {
-            CFDataRef issuer =
-                SecCertificateGetNormalizedIssuerContent(certificate);
-            SecTrustAppendCandidatesWithSubject(issuer, node->_candidates);
-        }
-        node->_fetchingState = kSecFetchingStateLocal;
-        break;
-    case kSecFetchingStateLocal:
-        /* Lookup candidates in the local database. */
-        node->_fetchingState = kSecFetchingStateFromURL;
-        break;
-    case kSecFetchingStateFromURL:
-        node->_fetchingState = kSecFetchingStateCheckExpired;
-        break;
-    case kSecFetchingStateCheckExpired:
-        /* Time to start considering expired candidates as well. */
-        node->_candidateIndex = 0;
-        node->_fetchingState = kSecFetchingStateDone;
-        break;
-    case kSecFetchingStateDone;
-        return NULL;
-    }
-}
-
-class Source {
-       Iterator parentIterator(Cert);
-};
-
-class NodeCache {
-       Set nodes;
-
-       static bool unique(Node node) {
-               if (nodes.contains(node))
-                       return false;
-               nodes.add(node);
-               return true;
-       }
-
-       static bool isAnchor(Cert cert);
-};
-
-class Node {
-       Cert cert;
-       Node child;
-       int nextSource;
-       Iterator parentIterator; /* For current source of parents. */
-
-       Node(Cert inCert) : child(nil), cert(inCert), nextSource(0) {}
-       Node(Node inChild, Cert inCert) : child(inChild), cert(inCert),
-               nextSource(0) {}
-
-       CertPath certPath() {
-               CertPath path;
-               Node node = this;
-               while (node) {
-                       path.add(node.cert);
-                       node = node.child;
-               }
-               return path;
-       }
-
-       void contains(Cert cert) {
-               Node node = this;
-               while (node) {
-                       if (cert == node.cert)
-                               return true;
-                       node = node.child;
-               }
-               return false;
-       }
-
-       Node nextParent(Array currentSources) {
-               for (;;) {
-                       if (!nextSource ||
-                               parentIterator == currentSources[nextSource - 1].end()) {
-                               if (nextSource == currentSources.count) {
-                                       /* We ran out of parent sources. */
-                                       return nil;
-                               }
-                               parentIterator = currentSources[nextSource++].begin();
-                       }
-                       Certificate cert = *parentIterator++;
-                       /* Check for cycles and self signed chains. */
-                       if (!contains(cert)) {
-                               Node node = Node(this, parent);
-                               if (!NodeCache.unique(node))
-                                       return node;
-                       }
-               }
-       }
-};
-
-
-class PathBuilder {
-       List nodes;
-       List rejects;
-       Array currentSources;
-       Iterator nit;
-       Array allSources;
-       Iterator sourceIT;
-       CertPath chain;
-
-       PathBuilder(Cert cert) {
-               nodes.append(Node(cert));
-               nit = nodes.begin();
-               sourceIT = allSources.begin();
-       }
-
-       nextAnchoredPath() {
-               if (nit == nodes.end()) {
-                       /* We should add another source to the list of sources to
-                          search. */
-                       if (sourceIT == allSources.end()) {
-                               /* No more sources to add. */
-                       }
-                       currentSources += *sourceIT++;
-                       /* Resort nodes by size. */
-                       Nodes.sortBySize();
-                       nit = nodes.begin();
-                       /* Set the source list for all nodes. */
-
-               }
-               while (Node node = *nit) {
-                       Node candidate = node.nextParent(currentSources);
-                       if (!candidate) {
-                               /* The current node has no more candidate parents so move
-                                  along. */
-                               nit++;
-                               continue;
-                       }
-
-                       if (candidate.isAnchored) {
-                               candidates.append(candidate);
-                       } else
-                               nodes.insert(candidate, nit);
-               }
-       }
-
-       findValidPath() {
-               while (Node node = nextAnchoredPath()) {
-                       if (node.isValid()) {
-                               chain = node.certPath;
-                               break;
-                       }
-                       rejects.append(node);
-               }
-       }
-}
-
-
-#endif