#include <Security/SecPolicyInternal.h>
#include <Security/SecPolicyPriv.h>
#include <AssertMacros.h>
#include <pthread.h>
#include <security_utilities/debugging.h>
#include <Security/SecInternal.h>
#include <CoreFoundation/CFNumber.h>
#include <CoreFoundation/CFRuntime.h>
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CFTimeZone.h>
#include <Security/SecCertificateInternal.h>
#include <libDER/oids.h>
#pragma mark -
#pragma mark SecPolicy Constants
CFStringRef kSecPolicyCheckSSLHostname = CFSTR("SSLHostname");
CFStringRef kSecPolicyCheckEmail = CFSTR("email");
CFStringRef kSecPolicyCheckIssuerCommonName = CFSTR("IssuerCommonName");
CFStringRef kSecPolicyCheckSubjectCommonName = CFSTR("SubjectCommonName");
CFStringRef kSecPolicyCheckSubjectCommonNamePrefix = CFSTR("SubjectCommonNamePrefix");
CFStringRef kSecPolicyCheckSubjectCommonNameTEST = CFSTR("SubjectCommonNameTEST");
CFStringRef kSecPolicyCheckSubjectOrganization = CFSTR("SubjectOrganization");
CFStringRef kSecPolicyCheckNotValidBefore = CFSTR("NotValidBefore");
CFStringRef kSecPolicyCheckEAPTrustedServerNames = CFSTR("EAPTrustedServerNames");
#if 0
CFStringRef kSecPolicyCheckLeafBasicConstraints = CFSTR("LeafBasicContraints");
#endif
CFStringRef kSecPolicyCheckKeyUsage = CFSTR("KeyUsage");
CFStringRef kSecPolicyCheckExtendedKeyUsage = CFSTR("ExtendedKeyUsage");
CFStringRef kSecPolicyCheckBasicContraints = CFSTR("BasicContraints");
CFStringRef kSecPolicyCheckQualifiedCertStatements =
CFSTR("QualifiedCertStatements");
CFStringRef kSecPolicyCheckAnchorSHA1 = CFSTR("AnchorSHA1");
CFStringRef kSecPolicyCheckAnchorTrusted = CFSTR("AnchorTrusted");
CFStringRef kSecPolicyCheckNonEmptySubject = CFSTR("NonEmptySubject");
CFStringRef kSecPolicyCheckIdLinkage = CFSTR("IdLinkage");
#if 0
CFStringRef kSecPolicyCheckValidityStarted = CFSTR("ValidStarted");
CFStringRef kSecPolicyCheckValidityExpired = CFSTR("ValidExpired");
#else
CFStringRef kSecPolicyCheckValidIntermediates = CFSTR("ValidIntermediates");
CFStringRef kSecPolicyCheckValidLeaf = CFSTR("ValidLeaf");
CFStringRef kSecPolicyCheckValidRoot = CFSTR("ValidRoot");
#endif
CFStringRef kSecPolicyCheckCriticalExtensions = CFSTR("CriticalExtensions");
CFStringRef kSecPolicyCheckChainLength = CFSTR("ChainLength");
CFStringRef kSecPolicyCheckBasicCertificateProcessing =
CFSTR("BasicCertificateProcessing");
CFStringRef kSecPolicyCheckExtendedValidation = CFSTR("ExtendedValidation");
CFStringRef kSecPolicyCheckRevocation = CFSTR("Revocation");
CFStringRef kSecPolicyCheckNoNetworkAccess = CFSTR("NoNetworkAccess");
CFStringRef kSecPolicyCheckBlackListedLeaf = CFSTR("BlackListedLeaf");
CFStringRef kSecPolicyCheckBlackListedKey = CFSTR("BlackListedKey");
CFStringRef kSecPolicyCheckLeafMarkerOid = CFSTR("CheckLeafMarkerOid");
CFStringRef kSecPolicyCheckIntermediateMarkerOid = CFSTR("CheckIntermediateMarkerOid");
static CFStringRef kSecPolicyOIDBasicX509 = CFSTR("basicX509");
static CFStringRef kSecPolicyOIDSSLServer = CFSTR("sslServer");
static CFStringRef kSecPolicyOIDSSLClient = CFSTR("sslClient");
static CFStringRef kSecPolicyOIDiPhoneActivation = CFSTR("iPhoneActivation");
static CFStringRef kSecPolicyOIDiPhoneDeviceCertificate =
CFSTR("iPhoneDeviceCertificate");
static CFStringRef kSecPolicyOIDFactoryDeviceCertificate =
CFSTR("FactoryDeviceCertificate");
static CFStringRef kSecPolicyOIDiAP = CFSTR("iAP");
static CFStringRef kSecPolicyOIDiTunesStoreURLBag = CFSTR("iTunesStoreURLBag");
static CFStringRef kSecPolicyEAPServer = CFSTR("eapServer");
static CFStringRef kSecPolicyEAPClient = CFSTR("eapClient");
static CFStringRef kSecPolicyOIDIPSecServer = CFSTR("ipsecServer");
static CFStringRef kSecPolicyOIDIPSecClient = CFSTR("ipsecClient");
static CFStringRef kSecPolicyOIDiPhoneApplicationSigning =
CFSTR("iPhoneApplicationSigning");
static CFStringRef kSecPolicyOIDiPhoneProfileApplicationSigning =
CFSTR("iPhoneProfileApplicationSigning");
static CFStringRef kSecPolicyOIDiPhoneProvisioningProfileSigning =
CFSTR("iPhoneProvisioningProfileSigning");
static CFStringRef kSecPolicyOIDRevocation = CFSTR("revocation");
static CFStringRef kSecPolicyOIDOCSPSigner = CFSTR("OCSPSigner");
static CFStringRef kSecPolicyOIDSMIME = CFSTR("SMIME");
static CFStringRef kSecPolicyOIDCodeSigning = CFSTR("CodeSigning");
static CFStringRef kSecPolicyOIDLockdownPairing = CFSTR("LockdownPairing");
static CFStringRef kSecPolicyOIDURLBag = CFSTR("URLBag");
static CFStringRef kSecPolicyOIDOTATasking = CFSTR("OTATasking");
static CFStringRef kSecPolicyOIDMobileAsset = CFSTR("MobileAsset");
static CFStringRef kSecPolicyOIDAppleIDAuthority = CFSTR("AppleIDAuthority");
#if 0
{
new builder(verifyTime, certificates, anchors, anchorsOnly, policies);
chain = builder.subscriber_only_chain;
foreach (policy in policies{kSecPolicySLCheck}) {
foreach(check in policy)
SecPolicyRunCheck(builder, chain, check, details);
foreach (subpolicy in policy) {
check_policy(builder, chain, subpolicy, details{subpolicy.name})
}
propagate_subpolicy_results(builder, chain, details);
}
while (chain = builder.next) {
for (depth = 0; p_d = policies.at_depth(depth),
d_p_d = dynamic_policies.at_depth(depth), p_d || d_p_d; ++depth)
{
foreach (policy in p_d) {
check_policy(builder, chain, policy, kSecPolicySICheck, depth);
}
d_p_d = dynamic_policies.at_depth(depth);
foreach (policy in d_p_d) {
check_policy(builder, chain, policy, kSecPolicySICheck, depth);
}
if (chain.is_anchored) {
foreach (policy in p_d) {
check_policy(builder, chain, policy, kSecPolicySACheck, depth);
}
foreach (policy in d_p_d) {
check_policy(builder, chain, policy, kSecPolicySACheck, depth);
}
foreach (policy in p_d) {
check_policy(builder, chain, policy, kSecPolicyDACheck, depth);
}
foreach (policy in d_p_d) {
check_policy(builder, chain, policy, kSecPolicyDACheck, depth);
}
}
foreach (policy in policies) {
check_policy(builder, chain, policy, kSecPolicySACheck, depth);
check_policy(builder, chain, policy, kSecPolicyDACheck, depth);
}
foreach (policy in policies{kSecPolicySDCheck}) {
}
}
}
check_policy(builder, chain, policy, check_class, details, depth) {
if (depth == 0) {
foreach(check in policy{check_class}) {
SecPolicyRunCheck(builder, chain, check, details);
}
} else {
depth--;
foreach (subpolicy in policy) {
if (!check_policy(builder, chain, subpolicy, check_class,
details{subpolicy.name}) && subpolicy.is_required, depth)
secpvcsetresult()
}
}
propagate_subpolicy_results(builder, chain, details);
}
#endif
#define kSecPolicySHA1Size 20
static const UInt8 kAppleCASHA1[kSecPolicySHA1Size] = {
0x61, 0x1E, 0x5B, 0x66, 0x2C, 0x59, 0x3A, 0x08, 0xFF, 0x58,
0xD1, 0x4A, 0xE2, 0x24, 0x52, 0xD1, 0x98, 0xDF, 0x6C, 0x60
};
static const UInt8 kITMSCASHA1[kSecPolicySHA1Size] = {
0x1D, 0x33, 0x42, 0x46, 0x8B, 0x10, 0xBD, 0xE6, 0x45, 0xCE,
0x44, 0x6E, 0xBB, 0xE8, 0xF5, 0x03, 0x5D, 0xF8, 0x32, 0x22
};
static const UInt8 kFactoryDeviceCASHA1[kSecPolicySHA1Size] = {
0xef, 0x68, 0x73, 0x17, 0xa4, 0xf8, 0xf9, 0x4b, 0x7b, 0x21,
0xe2, 0x2f, 0x09, 0x8f, 0xfd, 0x6a, 0xae, 0xc0, 0x0d, 0x63
};
#pragma mark -
#pragma mark SecPolicy
static pthread_once_t kSecPolicyRegisterClass = PTHREAD_ONCE_INIT;
static CFTypeID kSecPolicyTypeID = _kCFRuntimeNotATypeID;
static void SecPolicyDestroy(CFTypeRef cf) {
SecPolicyRef policy = (SecPolicyRef) cf;
CFRelease(policy->_oid);
CFRelease(policy->_options);
}
static Boolean SecPolicyEqual(CFTypeRef cf1, CFTypeRef cf2) {
SecPolicyRef policy1 = (SecPolicyRef) cf1;
SecPolicyRef policy2 = (SecPolicyRef) cf2;
return CFEqual(policy1->_oid, policy2->_oid) &&
CFEqual(policy1->_options, policy2->_options);
}
static CFHashCode SecPolicyHash(CFTypeRef cf) {
SecPolicyRef policy = (SecPolicyRef) cf;
return CFHash(policy->_oid) + CFHash(policy->_options);
}
static CFStringRef SecPolicyDescribe(CFTypeRef cf) {
SecPolicyRef policy = (SecPolicyRef) cf;
CFMutableStringRef desc = CFStringCreateMutable(kCFAllocatorDefault, 0);
CFStringRef typeStr = CFCopyTypeIDDescription(CFGetTypeID(cf));
CFStringAppendFormat(desc, NULL,
CFSTR("<%@ %@: oid: %@ options %@"), typeStr,
policy->_oid, policy->_options);
CFRelease(typeStr);
CFStringAppend(desc, CFSTR(" >"));
return desc;
}
static void SecPolicyRegisterClass(void) {
static const CFRuntimeClass kSecPolicyClass = {
0,
"SecPolicy",
NULL,
NULL,
SecPolicyDestroy,
SecPolicyEqual,
SecPolicyHash,
NULL,
SecPolicyDescribe
};
kSecPolicyTypeID = _CFRuntimeRegisterClass(&kSecPolicyClass);
}
CFTypeID SecPolicyGetTypeID(void) {
pthread_once(&kSecPolicyRegisterClass, SecPolicyRegisterClass);
return kSecPolicyTypeID;
}
SecPolicyRef SecPolicyCreate(CFStringRef oid, CFDictionaryRef options) {
SecPolicyRef result = NULL;
require(oid, errOut);
require(options, errOut);
require(result =
(SecPolicyRef)_CFRuntimeCreateInstance(kCFAllocatorDefault,
SecPolicyGetTypeID(),
sizeof(struct __SecPolicy) - sizeof(CFRuntimeBase), 0), errOut);
CFRetain(oid);
result->_oid = oid;
CFRetain(options);
result->_options = options;
errOut:
return result;
}
static CFArrayRef SecPolicyCopyArray(SecPolicyRef policy) {
const void *values[] = { policy->_oid, policy->_options };
return CFArrayCreate(kCFAllocatorDefault, values, 2, &kCFTypeArrayCallBacks);
}
static void serializePolicy(const void *value, void *context) {
CFTypeRef serializedPolicy = SecPolicyCopyArray((SecPolicyRef)value);
CFArrayAppendValue((CFMutableArrayRef)context, serializedPolicy);
CFRelease(serializedPolicy);
}
CFArrayRef SecPolicyArraySerialize(CFArrayRef policies) {
CFMutableArrayRef result = NULL;
require_quiet(policies && CFGetTypeID(policies) == CFArrayGetTypeID(), errOut);
CFIndex count = CFArrayGetCount(policies);
result = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks);
CFRange all_policies = { 0, count };
CFArrayApplyFunction(policies, all_policies, serializePolicy, result);
errOut:
return result;
}
static void add_element(CFMutableDictionaryRef options, CFStringRef key,
CFTypeRef value) {
CFTypeRef old_value = CFDictionaryGetValue(options, key);
if (old_value) {
CFMutableArrayRef array;
if (CFGetTypeID(old_value) == CFArrayGetTypeID()) {
array = (CFMutableArrayRef)old_value;
} else {
array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeArrayCallBacks);
CFArrayAppendValue(array, old_value);
CFDictionarySetValue(options, key, array);
CFRelease(array);
}
CFArrayAppendValue(array, value);
} else {
CFDictionaryAddValue(options, key, value);
}
}
static void add_eku(CFMutableDictionaryRef options, const DERItem *ekuOid) {
CFDataRef eku = CFDataCreate(kCFAllocatorDefault,
ekuOid ? ekuOid->data : NULL,
ekuOid ? ekuOid->length : 0);
if (eku) {
add_element(options, kSecPolicyCheckExtendedKeyUsage, eku);
CFRelease(eku);
}
}
static void add_ku(CFMutableDictionaryRef options, SecKeyUsage keyUsage) {
SInt32 dku = keyUsage;
CFNumberRef ku = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
&dku);
if (ku) {
add_element(options, kSecPolicyCheckKeyUsage, ku);
CFRelease(ku);
}
}
static void add_oid(CFMutableDictionaryRef options, CFStringRef policy_key, const DERItem *oid) {
CFDataRef oid_data = CFDataCreate(kCFAllocatorDefault,
oid ? oid->data : NULL,
oid ? oid->length : 0);
if (oid_data) {
add_element(options, policy_key, oid_data);
CFRelease(oid_data);
}
}
static void SecPolicyAddBasicCertOptions(CFMutableDictionaryRef options)
{
CFDictionaryAddValue(options, kSecPolicyCheckCriticalExtensions, kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckIdLinkage, kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckBasicContraints, kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckNonEmptySubject, kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckQualifiedCertStatements, kCFBooleanTrue);
}
static void SecPolicyAddBasicX509Options(CFMutableDictionaryRef options)
{
SecPolicyAddBasicCertOptions(options);
CFDictionaryAddValue(options, kSecPolicyCheckValidIntermediates, kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckValidLeaf, kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckValidRoot, kCFBooleanTrue);
}
static bool SecPolicyAddChainLengthOptions(CFMutableDictionaryRef options, CFIndex length)
{
bool result = false;
CFNumberRef lengthAsCF = NULL;
require(lengthAsCF = CFNumberCreate(kCFAllocatorDefault,
kCFNumberCFIndexType, &length), errOut);
CFDictionaryAddValue(options, kSecPolicyCheckChainLength, lengthAsCF);
result = true;
errOut:
CFReleaseSafe(lengthAsCF);
return result;
}
static bool SecPolicyAddAnchorSHA1Options(CFMutableDictionaryRef options,
const UInt8 anchorSha1[kSecPolicySHA1Size])
{
bool success = false;
CFDataRef anchorData = NULL;
require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha1, kSecPolicySHA1Size), errOut);
CFDictionaryAddValue(options, kSecPolicyCheckAnchorSHA1, anchorData);
success = true;
errOut:
CFReleaseSafe(anchorData);
return success;
}
static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef options)
{
return SecPolicyAddAnchorSHA1Options(options, kAppleCASHA1);
}
SecPolicyRef SecPolicyCreateBasicX509(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
require(result = SecPolicyCreate(kSecPolicyOIDBasicX509, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
#if 0
CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
kCFBooleanTrue);
#endif
if (hostname) {
CFDictionaryAddValue(options, kSecPolicyCheckSSLHostname, hostname);
}
CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf,
kCFBooleanTrue);
add_eku(options, NULL);
add_eku(options, &oidAnyExtendedKeyUsage);
if (server) {
add_eku(options, &oidExtendedKeyUsageServerAuth);
add_eku(options, &oidExtendedKeyUsageMicrosoftSGC);
add_eku(options, &oidExtendedKeyUsageNetscapeSGC);
} else {
add_eku(options, &oidExtendedKeyUsageClientAuth);
}
require(result = SecPolicyCreate(
server ? kSecPolicyOIDSSLServer : kSecPolicyOIDSSLClient,
options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateiPhoneActivation(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicCertOptions(options);
#if 0
CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
kCFBooleanTrue);
#endif
CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
CFSTR("Apple iPhone Certification Authority"));
CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName,
CFSTR("Apple iPhone Activation"));
require(SecPolicyAddChainLengthOptions(options, 3), errOut);
require(SecPolicyAddAppleAnchorOptions(options), errOut);
require(result = SecPolicyCreate(kSecPolicyOIDiPhoneActivation, options),
errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateiPhoneDeviceCertificate(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicCertOptions(options);
#if 0
CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
kCFBooleanTrue);
#endif
CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
CFSTR("Apple iPhone Device CA"));
require(SecPolicyAddChainLengthOptions(options, 4), errOut);
require(SecPolicyAddAppleAnchorOptions(options), errOut);
require(result = SecPolicyCreate(kSecPolicyOIDiPhoneDeviceCertificate, options),
errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicCertOptions(options);
#if 0
CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
kCFBooleanTrue);
#endif
require(SecPolicyAddAnchorSHA1Options(options, kFactoryDeviceCASHA1), errOut);
require(result = SecPolicyCreate(kSecPolicyOIDFactoryDeviceCertificate, options),
errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateiAP(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
CFTimeZoneRef tz = NULL;
CFDateRef date = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicCertOptions(options);
CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNamePrefix,
CFSTR("IPA_"));
CFGregorianDate gd = {
2006,
5,
31,
0,
0,
0.0
};
require(tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0), errOut);
CFAbsoluteTime at = CFGregorianDateGetAbsoluteTime(gd, tz);
require(date = CFDateCreate(kCFAllocatorDefault, at), errOut);
CFDictionaryAddValue(options, kSecPolicyCheckNotValidBefore, date);
require(result = SecPolicyCreate(kSecPolicyOIDiAP, options),
errOut);
errOut:
CFReleaseSafe(date);
CFReleaseSafe(tz);
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicCertOptions(options);
CFDictionaryAddValue(options, kSecPolicyCheckSubjectOrganization,
CFSTR("Apple Inc."));
CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName,
CFSTR("iTunes Store URL Bag"));
require(SecPolicyAddChainLengthOptions(options, 2), errOut);
require(SecPolicyAddAnchorSHA1Options(options, kITMSCASHA1), errOut);
require(result = SecPolicyCreate(kSecPolicyOIDiTunesStoreURLBag, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateEAP(Boolean server, CFArrayRef trustedServerNames) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
#if 0
CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
kCFBooleanTrue);
#endif
CFDictionaryAddValue(options, kSecPolicyCheckNoNetworkAccess,
kCFBooleanTrue);
if (trustedServerNames) {
CFDictionaryAddValue(options, kSecPolicyCheckEAPTrustedServerNames, trustedServerNames);
}
require(result = SecPolicyCreate(
server ? kSecPolicyEAPServer : kSecPolicyEAPClient,
options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateIPSec(Boolean server, CFStringRef hostname) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
if (hostname) {
CFDictionaryAddValue(options, kSecPolicyCheckSSLHostname, hostname);
}
require(result = SecPolicyCreate(
server ? kSecPolicyOIDIPSecServer : kSecPolicyOIDIPSecClient,
options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateiPhoneApplicationSigning(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicCertOptions(options);
CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
CFSTR("Apple iPhone Certification Authority"));
CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNameTEST,
CFSTR("Apple iPhone OS Application Signing"));
require(SecPolicyAddChainLengthOptions(options, 3), errOut);
require(SecPolicyAddAppleAnchorOptions(options), errOut);
add_eku(options, NULL);
add_eku(options, &oidAnyExtendedKeyUsage);
add_eku(options, &oidExtendedKeyUsageCodeSigning);
require(result = SecPolicyCreate(kSecPolicyOIDiPhoneApplicationSigning, options),
errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateiPhoneProfileApplicationSigning(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
CFDictionaryAddValue(options, kSecPolicyCheckValidLeaf, kCFBooleanFalse);
require(result = SecPolicyCreate(kSecPolicyOIDiPhoneProfileApplicationSigning,
options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateiPhoneProvisioningProfileSigning(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicCertOptions(options);
CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
CFSTR("Apple iPhone Certification Authority"));
CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNameTEST,
CFSTR("Apple iPhone OS Provisioning Profile Signing"));
require(SecPolicyAddChainLengthOptions(options, 3), errOut);
require(SecPolicyAddAppleAnchorOptions(options), errOut);
require(result = SecPolicyCreate(kSecPolicyOIDiPhoneProvisioningProfileSigning, options),
errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateOCSPSigner(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
add_eku(options, &oidExtendedKeyUsageOCSPSigning);
require(result = SecPolicyCreate(kSecPolicyOIDOCSPSigner, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateRevocation(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
require(result = SecPolicyCreate(kSecPolicyOIDRevocation, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
if (smimeUsage & kSecSignSMIMEUsage) {
add_ku(options, kSecKeyUsageUnspecified);
add_ku(options, kSecKeyUsageDigitalSignature);
add_ku(options, kSecKeyUsageNonRepudiation);
}
if (smimeUsage & kSecKeyEncryptSMIMEUsage) {
add_ku(options, kSecKeyUsageKeyEncipherment);
}
if (smimeUsage & kSecDataEncryptSMIMEUsage) {
add_ku(options, kSecKeyUsageDataEncipherment);
}
if (smimeUsage & kSecKeyExchangeDecryptSMIMEUsage) {
add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageDecipherOnly);
}
if (smimeUsage & kSecKeyExchangeEncryptSMIMEUsage) {
add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly);
}
if (smimeUsage & kSecKeyExchangeBothSMIMEUsage) {
add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly | kSecKeyUsageDecipherOnly);
}
if (email) {
CFDictionaryAddValue(options, kSecPolicyCheckEmail, email);
}
add_eku(options, &oidExtendedKeyUsageEmailProtection);
require(result = SecPolicyCreate(kSecPolicyOIDSMIME, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateCodeSigning(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
add_ku(options, kSecKeyUsageDigitalSignature);
add_ku(options, kSecKeyUsageNonRepudiation);
add_eku(options, &oidAnyExtendedKeyUsage);
add_eku(options, &oidExtendedKeyUsageCodeSigning);
require(result = SecPolicyCreate(kSecPolicyOIDCodeSigning, options),
errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateLockdownPairing(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
CFDictionaryAddValue(options, kSecPolicyCheckCriticalExtensions,
kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckIdLinkage,
kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckBasicContraints,
kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckQualifiedCertStatements,
kCFBooleanTrue);
require(result = SecPolicyCreate(kSecPolicyOIDLockdownPairing, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateURLBag(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicCertOptions(options);
add_eku(options, &oidExtendedKeyUsageCodeSigning);
require(result = SecPolicyCreate(kSecPolicyOIDURLBag, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
static bool SecPolicyAddAppleCertificationAuthorityOptions(CFMutableDictionaryRef options, bool honorValidity)
{
bool success = false;
if (honorValidity)
SecPolicyAddBasicX509Options(options);
else
SecPolicyAddBasicCertOptions(options);
#if 0
CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
kCFBooleanTrue);
#endif
CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
CFSTR("Apple iPhone Certification Authority"));
require(SecPolicyAddChainLengthOptions(options, 3), errOut);
require(SecPolicyAddAppleAnchorOptions(options), errOut);
success = true;
errOut:
return success;
}
static SecPolicyRef SecPolicyCreateAppleCertificationAuthorityPolicy(CFStringRef policyOID, CFStringRef leafName, bool honorValidity)
{
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
require(SecPolicyAddAppleCertificationAuthorityOptions(options, honorValidity), errOut);
CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName, leafName);
require(result = SecPolicyCreate(policyOID, options),
errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateOTATasking(void)
{
return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDOTATasking, CFSTR("OTA Task Signing"), true);
}
SecPolicyRef SecPolicyCreateMobileAsset(void)
{
return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDMobileAsset, CFSTR("Asset Manifest Signing"), false);
}
SecPolicyRef SecPolicyCreateAppleIDAuthorityPolicy(void)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), out);
SecPolicyAddBasicX509Options(options);
require(SecPolicyAddAppleAnchorOptions(options), out);
add_oid(options, kSecPolicyCheckLeafMarkerOid, &oidAppleExtendedKeyUsageAppleID);
add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID);
add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID2);
require(result = SecPolicyCreate(kSecPolicyOIDAppleIDAuthority, options), out);
out:
CFReleaseSafe(options);
return result;
}