#include "SecTrust.h"
#include "SecTrustPriv.h"
#include "Trust.h"
#include <security_keychain/SecTrustSettingsPriv.h>
#include "SecBridge.h"
#include "SecTrustSettings.h"
#include "SecCertificatePriv.h"
#include <security_utilities/cfutilities.h>
#include <CoreFoundation/CoreFoundation.h>
CFTypeID SecTrustGetTypeID(void)
{
BEGIN_SECAPI
return gTypes().Trust.typeID;
END_SECAPI1(_kCFRuntimeNotATypeID)
}
OSStatus SecTrustCreateWithCertificates(
CFArrayRef certificates,
CFTypeRef policies,
SecTrustRef *trustRef)
{
BEGIN_SECAPI
Required(trustRef);
*trustRef = (new Trust(certificates, policies))->handle();
END_SECAPI
}
OSStatus
SecTrustSetPolicies(SecTrustRef trustRef, CFTypeRef policies)
{
BEGIN_SECAPI
Trust::required(trustRef)->policies(policies);
END_SECAPI
}
OSStatus
SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options)
{
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
}
OSStatus SecTrustSetParameters(
SecTrustRef trustRef,
CSSM_TP_ACTION action,
CFDataRef actionData)
{
BEGIN_SECAPI
Trust *trust = Trust::required(trustRef);
trust->action(action);
trust->actionData(actionData);
END_SECAPI
}
OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, CFArrayRef anchorCertificates)
{
BEGIN_SECAPI
Trust::required(trust)->anchors(anchorCertificates);
END_SECAPI
}
OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, Boolean anchorCertificatesOnly)
{
BEGIN_SECAPI
Trust::AnchorPolicy policy = (anchorCertificatesOnly) ? Trust::useAnchorsOnly : Trust::useAnchorsAndBuiltIns;
Trust::required(trust)->anchorPolicy(policy);
END_SECAPI
}
OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray)
{
BEGIN_SECAPI
StorageManager::KeychainList keychains;
if (!( (keychainOrArray != NULL) &&
(CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) &&
(CFArrayGetCount((CFArrayRef)keychainOrArray) == 0) )) {
globals().storageManager.optionalSearchList(keychainOrArray, keychains);
}
Trust::required(trust)->searchLibs(keychains);
END_SECAPI
}
OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate)
{
BEGIN_SECAPI
Trust::required(trust)->time(verifyDate);
END_SECAPI
}
CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust)
{
CFAbsoluteTime verifyTime = 0;
OSStatus __secapiresult;
try {
CFRef<CFDateRef> verifyDate = Trust::required(trust)->time();
verifyTime = CFDateGetAbsoluteTime(verifyDate);
__secapiresult=noErr;
}
catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
catch (...) { __secapiresult=internalComponentErr; }
return verifyTime;
}
OSStatus SecTrustEvaluate(SecTrustRef trustRef, SecTrustResultType *resultP)
{
BEGIN_SECAPI
Trust *trust = Trust::required(trustRef);
trust->evaluate();
if (resultP) {
*resultP = trust->result();
secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)*resultP);
}
END_SECAPI
}
OSStatus SecTrustEvaluateAsync(SecTrustRef trust,
dispatch_queue_t queue, SecTrustCallback result)
{
BEGIN_SECAPI
dispatch_async(queue, ^{
try {
Trust *trustObj = Trust::required(trust);
trustObj->evaluate();
result(trust, trustObj->result());
}
catch (...) {
result(trust, kSecTrustResultInvalid);
};
});
END_SECAPI
}
OSStatus SecTrustGetResult(
SecTrustRef trustRef,
SecTrustResultType *result,
CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain)
{
BEGIN_SECAPI
Trust *trust = Trust::required(trustRef);
if (result)
*result = trust->result();
if (certChain && statusChain)
trust->buildEvidence(*certChain, TPEvidenceInfo::overlayVar(*statusChain));
END_SECAPI
}
OSStatus SecTrustGetTrustResult(SecTrustRef trustRef,
SecTrustResultType *result)
{
BEGIN_SECAPI
Trust *trust = Trust::required(trustRef);
if (result) *result = trust->result();
END_SECAPI
}
OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result)
{
BEGIN_SECAPI
Trust *trustObj = Trust::required(trust);
if (result == nil)
return paramErr;
trustObj->extendedResult(*result);
END_SECAPI
}
OSStatus SecTrustGetCssmResult(SecTrustRef trust, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result)
{
BEGIN_SECAPI
Required(result) = Trust::required(trust)->cssmResult();
END_SECAPI
}
OSStatus SecTrustGetCssmResultCode(SecTrustRef trustRef, OSStatus *result)
{
BEGIN_SECAPI
Trust *trust = Trust::required(trustRef);
if (trust->result() == kSecTrustResultInvalid)
return paramErr;
else
Required(result) = trust->cssmResultCode();
END_SECAPI
}
OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle)
{
BEGIN_SECAPI
Required(handle) = Trust::required(trust)->getTPHandle();
END_SECAPI
}
OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies)
{
BEGIN_SECAPI
CFArrayRef currentPolicies = Trust::required(trust)->policies();
if (currentPolicies != NULL)
{
CFRetain(currentPolicies);
}
Required(policies) = currentPolicies;
END_SECAPI
}
OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchorCertificates)
{
BEGIN_SECAPI
CFRef<CFArrayRef> customAnchors(Trust::required(trust)->anchors());
Required(anchorCertificates) = (customAnchors) ?
(const CFArrayRef)CFRetain(customAnchors) : (const CFArrayRef)NULL;
END_SECAPI
}
OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchorCertificates)
{
BEGIN_SECAPI
return SecTrustSettingsCopyUnrestrictedRoots(
true, true, true,
anchorCertificates);
END_SECAPI
}
SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust)
{
SecKeyRef pubKey = NULL;
CFArrayRef certChain = NULL;
CFArrayRef evidenceChain = NULL;
CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
OSStatus __secapiresult;
try {
Trust *trustObj = Trust::required(trust);
if (trustObj->result() == kSecTrustResultInvalid)
MacOSError::throwMe(errSecTrustNotAvailable);
if (trustObj->evidence() == nil)
trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
evidenceChain = trustObj->evidence();
__secapiresult=noErr;
}
catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
catch (...) { __secapiresult=internalComponentErr; }
if (certChain)
CFRelease(certChain);
if (evidenceChain) {
if (CFArrayGetCount(evidenceChain) > 0) {
SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, 0);
__secapiresult = SecCertificateCopyPublicKey(cert, &pubKey);
}
}
return pubKey;
}
CFIndex SecTrustGetCertificateCount(SecTrustRef trust)
{
CFIndex chainLen = 0;
CFArrayRef certChain = NULL;
CFArrayRef evidenceChain = NULL;
CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
OSStatus __secapiresult;
try {
Trust *trustObj = Trust::required(trust);
if (trustObj->result() == kSecTrustResultInvalid)
MacOSError::throwMe(errSecTrustNotAvailable);
if (trustObj->evidence() == nil)
trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
evidenceChain = trustObj->evidence();
__secapiresult=noErr;
}
catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
catch (...) { __secapiresult=internalComponentErr; }
if (certChain)
CFRelease(certChain);
if (evidenceChain)
chainLen = CFArrayGetCount(evidenceChain);
return chainLen;
}
SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix)
{
SecCertificateRef certificate = NULL;
CFArrayRef certChain = NULL;
CFArrayRef evidenceChain = NULL;
CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
OSStatus __secapiresult;
try {
Trust *trustObj = Trust::required(trust);
if (trustObj->result() == kSecTrustResultInvalid)
MacOSError::throwMe(errSecTrustNotAvailable);
if (trustObj->evidence() == nil)
trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
evidenceChain = trustObj->evidence();
__secapiresult=noErr;
}
catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
catch (...) { __secapiresult=internalComponentErr; }
if (certChain)
CFRelease(certChain);
if (evidenceChain) {
if (ix < CFArrayGetCount(evidenceChain)) {
certificate = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, ix);
}
}
return certificate;
}
CFArrayRef
SecTrustCopyProperties(SecTrustRef trust)
{
CFArrayRef result = NULL;
try {
result = Trust::required(trust)->properties();
}
catch (...) {
if (result) {
CFRelease(result);
result = NULL;
}
};
return result;
}
OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors,
uint32 *cssmAnchorCount)
{
BEGIN_SECAPI
CertGroup certs;
Trust::gStore().getCssmRootCertificates(certs);
Required(cssmAnchors) = certs.blobCerts();
Required(cssmAnchorCount) = certs.count();
END_SECAPI
}
OSStatus SecTrustGetUserTrust(SecCertificateRef certificate,
SecPolicyRef policy, SecTrustUserSetting *trustSetting)
{
BEGIN_SECAPI
StorageManager::KeychainList searchList;
globals().storageManager.getSearchList(searchList);
Required(trustSetting) = Trust::gStore().find(
Certificate::required(certificate),
Policy::required(policy),
searchList);
END_SECAPI
}
OSStatus SecTrustSetUserTrust(SecCertificateRef certificate,
SecPolicyRef policy, SecTrustUserSetting trustSetting)
{
SecTrustSettingsResult tsResult = kSecTrustSettingsResultInvalid;
OSStatus ortn;
Boolean isRoot;
Policy::required(policy);
switch(trustSetting) {
case kSecTrustResultProceed:
ortn = SecCertificateIsSelfSigned(certificate, &isRoot);
if(ortn) {
return ortn;
}
if(isRoot) {
tsResult = kSecTrustSettingsResultTrustRoot;
}
else {
tsResult = kSecTrustSettingsResultTrustAsRoot;
}
break;
case kSecTrustResultDeny:
tsResult = kSecTrustSettingsResultDeny;
break;
default:
return unimpErr;
}
CFRef<CFMutableDictionaryRef> usageDict(CFDictionaryCreateMutable(NULL,
0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
CFDictionaryAddValue(usageDict, kSecTrustSettingsPolicy, policy);
if(tsResult != kSecTrustSettingsResultTrustRoot) {
SInt32 result = tsResult;
CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &result);
CFDictionarySetValue(usageDict, kSecTrustSettingsResult, cfNum);
CFRelease(cfNum);
}
return SecTrustSettingsSetTrustSettings(certificate, kSecTrustSettingsDomainUser,
usageDict);
}
OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate,
SecPolicyRef policy, SecTrustUserSetting trustSetting)
{
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
}