#include <Security/SecPolicyInternal.h>
#include <Security/SecPolicyPriv.h>
#include <AssertMacros.h>
#include <pthread.h>
#include <utilities/debugging.h>
#include <Security/SecInternal.h>
#include <CoreFoundation/CFDictionary.h>
#include <CoreFoundation/CFNumber.h>
#include <CoreFoundation/CFRuntime.h>
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CFTimeZone.h>
#include <Security/SecCertificateInternal.h>
#include <Security/SecCertificatePriv.h>
#include <libDER/oids.h>
#include <utilities/SecCFError.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/array_size.h>
#include <securityd_client.h>
#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v));
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 kSecPolicyCheckSubjectOrganizationalUnit = CFSTR("SubjectOrganizationalUnit");
CFStringRef kSecPolicyCheckNotValidBefore = CFSTR("NotValidBefore");
CFStringRef kSecPolicyCheckEAPTrustedServerNames = CFSTR("EAPTrustedServerNames");
CFStringRef kSecPolicyCheckCertificatePolicy = CFSTR("CertificatePolicy");
#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 kSecPolicyCheckGrayListedLeaf = CFSTR("GrayListedLeaf");
CFStringRef kSecPolicyCheckGrayListedKey = CFSTR("GrayListedKey");
CFStringRef kSecPolicyCheckBlackListedKey = CFSTR("BlackListedKey");
CFStringRef kSecPolicyCheckLeafMarkerOid = CFSTR("CheckLeafMarkerOid");
CFStringRef kSecPolicyCheckIntermediateMarkerOid = CFSTR("CheckIntermediateMarkerOid");
SEC_CONST_DECL (kSecPolicyAppleX509Basic, "1.2.840.113635.100.1.2");
SEC_CONST_DECL (kSecPolicyAppleSSL, "1.2.840.113635.100.1.3");
SEC_CONST_DECL (kSecPolicyAppleSMIME, "1.2.840.113635.100.1.8");
SEC_CONST_DECL (kSecPolicyAppleEAP, "1.2.840.113635.100.1.9");
SEC_CONST_DECL (kSecPolicyAppleIPsec, "1.2.840.113635.100.1.11");
SEC_CONST_DECL (kSecPolicyApplePKINITClient, "1.2.840.113635.100.1.14");
SEC_CONST_DECL (kSecPolicyApplePKINITServer, "1.2.840.113635.100.1.15");
SEC_CONST_DECL (kSecPolicyAppleCodeSigning, "1.2.840.113635.100.1.16");
SEC_CONST_DECL (kSecPolicyApplePackageSigning, "1.2.840.113635.100.1.17");
SEC_CONST_DECL (kSecPolicyAppleIDValidation, "1.2.840.113635.100.1.18");
SEC_CONST_DECL (kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19");
SEC_CONST_DECL (kSecPolicyAppleTimeStamping, "1.2.840.113635.100.1.20");
SEC_CONST_DECL (kSecPolicyAppleRevocation, "1.2.840.113635.100.1.21");
SEC_CONST_DECL (kSecPolicyApplePassbookSigning, "1.2.840.113635.100.1.22");
SEC_CONST_DECL (kSecPolicyAppleMobileStore, "1.2.840.113635.100.1.23");
SEC_CONST_DECL (kSecPolicyAppleEscrowService, "1.2.840.113635.100.1.24");
SEC_CONST_DECL (kSecPolicyAppleProfileSigner, "1.2.840.113635.100.1.25");
SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner, "1.2.840.113635.100.1.26");
SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27");
#if TARGET_OS_IPHONE
SEC_CONST_DECL (kSecPolicyAppleOTAPKISigner, "1.2.840.113635.100.1.28");
SEC_CONST_DECL (kSecPolicyAppleTestOTAPKISigner, "1.2.840.113635.100.1.29");
SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113625.100.1.30");
#endif
SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid");
SEC_CONST_DECL (kSecPolicyName, "SecPolicyName");
SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient");
SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags");
SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier");
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");
static CFStringRef kSecPolicyOIDAppleShoebox = CFSTR("AppleShoebox");
static CFStringRef kSecPolicyOIDApplePassbook = CFSTR("ApplePassbook");
static CFStringRef kSecPolicyOIDAppleMobileStore = CFSTR("AppleMobileStore");
static CFStringRef kSecPolicyOIDAppleTestMobileStore = CFSTR("AppleTestMobileStore");
static CFStringRef kSecPolicyOIDAppleEscrowService = CFSTR("AppleEscrowService");
static CFStringRef kSecPolicyOIDAppleProfileSigner = CFSTR("AppleProfileSigner");
static CFStringRef kSecPolicyOIDAppleQAProfileSigner = CFSTR("AppleQAProfileSigner");
static CFStringRef kSecPolicyOIDAppleOTAPKIAssetSigner = CFSTR("AppleOTAPKIAssetSigner");
static CFStringRef kSecPolicyOIDAppleTestOTAPKIAssetSigner = CFSTR("AppleTestOTAPKIAssetSigner");
static CFStringRef kSecPolicyOIDAppleIDValidationRecordSigningPolicy = CFSTR("AppleIDValidationRecordSigningPolicy");
#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
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 kAppleTESTCASHA1[kSecPolicySHA1Size] = {
0xbc, 0x30, 0x55, 0xc8, 0xc8, 0xd3, 0x48, 0x3f, 0xf4, 0x8d,
0xfe, 0x3d, 0x51, 0x75, 0x31, 0xc9, 0xf4, 0xd7, 0x4a, 0xf7
};
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
};
static const UInt8 kApplePKISettingsAuthority[kSecPolicySHA1Size] = {
0x1D, 0x0C, 0xBA, 0xAD, 0x17, 0xFD, 0x7E, 0x9E, 0x9F, 0xF1,
0xC9, 0xA2, 0x66, 0x79, 0x60, 0x00, 0x8B, 0xAE, 0x70, 0xB8
};
static const UInt8 kAppleTestPKISettingsAuthority[kSecPolicySHA1Size] = {
0xDB, 0xBA, 0x25, 0x0B, 0xD8, 0x62, 0x71, 0x87, 0x54, 0x7E,
0xD7, 0xEF, 0x11, 0x94, 0x7E, 0x82, 0xE6, 0xD8, 0x1C, 0x9A
};
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 CF_RETURNS_RETAINED 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;
}
SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier,
CFDictionaryRef properties) {
SecPolicyRef policy = NULL;
CFStringRef name = NULL;
CFStringRef teamID = NULL;
Boolean client = false;
require(policyIdentifier && (CFStringGetTypeID() == CFGetTypeID(policyIdentifier)), errOut);
if (properties) {
name = CFDictionaryGetValue(properties, kSecPolicyName);
teamID = CFDictionaryGetValue(properties, kSecPolicyTeamIdentifier);
CFBooleanRef dictionaryClientValue;
client = (CFDictionaryGetValueIfPresent(properties, kSecPolicyClient, (const void **)&dictionaryClientValue) &&
(dictionaryClientValue != NULL) && CFEqual(kCFBooleanTrue, dictionaryClientValue));
}
if (CFEqual(policyIdentifier, kSecPolicyAppleX509Basic)) {
policy = SecPolicyCreateBasicX509();
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleSSL)) {
policy = SecPolicyCreateSSL(!client, name);
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleEAP)) {
CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, (const void **)&name, 1,
&kCFTypeArrayCallBacks);
policy = SecPolicyCreateEAP(!client, array);
CFReleaseSafe(array);
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleIPsec)) {
policy = SecPolicyCreateIPSec(!client, name);
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleRevocation)) {
policy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod);
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleSMIME)) {
policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, name);
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleCodeSigning)) {
policy = SecPolicyCreateCodeSigning();
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleIDValidation)) {
policy = SecPolicyCreateAppleIDAuthorityPolicy();
}
else if (CFEqual(policyIdentifier, kSecPolicyApplePassbookSigning)) {
policy = SecPolicyCreatePassbookCardSigner(name, teamID);
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleMobileStore)) {
policy = SecPolicyCreateMobileStoreSigner();
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleTestMobileStore)) {
policy = SecPolicyCreateTestMobileStoreSigner();
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleEscrowService)) {
policy = SecPolicyCreateEscrowServiceSigner();
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleProfileSigner)) {
policy = SecPolicyCreateConfigurationProfileSigner();
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleQAProfileSigner)) {
policy = SecPolicyCreateQAConfigurationProfileSigner();
}
#if TARGET_OS_IPHONE
else if (CFEqual(policyIdentifier, kSecPolicyAppleOTAPKISigner)) {
policy = SecPolicyCreateOTAPKISigner();
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleTestOTAPKISigner)) {
policy = SecPolicyCreateTestOTAPKISigner();
}
else if (CFEqual(policyIdentifier, kSecPolicyAppleIDValidationRecordSigningPolicy)) {
policy = SecPolicyCreateAppleIDValidationRecordSigningPolicy();
}
#endif
errOut:
return policy;
}
CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) {
if (!policyRef) return NULL;
CFMutableDictionaryRef properties = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (!properties) return NULL;
CFStringRef oid = (CFStringRef) CFRetain(policyRef->_oid);
CFTypeRef nameKey = NULL;
CFStringRef outOid = oid;
if (CFEqual(oid, kSecPolicyOIDBasicX509)) {
outOid = kSecPolicyAppleX509Basic;
}
else if (CFEqual(oid, kSecPolicyOIDSSLServer) ||
CFEqual(oid, kSecPolicyOIDSSLClient)) {
outOid = kSecPolicyAppleSSL;
nameKey = kSecPolicyCheckSSLHostname;
}
else if (CFEqual(oid, kSecPolicyEAPServer) ||
CFEqual(oid, kSecPolicyEAPClient)) {
outOid = kSecPolicyAppleEAP;
nameKey = kSecPolicyCheckEAPTrustedServerNames;
}
else if (CFEqual(oid, kSecPolicyOIDIPSecServer) ||
CFEqual(oid, kSecPolicyOIDIPSecClient)) {
outOid = kSecPolicyAppleIPsec;
nameKey = kSecPolicyCheckSSLHostname;
}
else if (CFEqual(oid, kSecPolicyOIDRevocation)) {
outOid = kSecPolicyAppleRevocation;
}
else if (CFEqual(oid, kSecPolicyOIDSMIME)) {
outOid = kSecPolicyAppleSMIME;
nameKey = kSecPolicyCheckEmail;
}
else if (CFEqual(oid, kSecPolicyOIDCodeSigning)) {
outOid = kSecPolicyAppleCodeSigning;
}
else if (CFEqual(oid, kSecPolicyOIDAppleIDAuthority)) {
outOid = kSecPolicyAppleIDValidation;
}
else if (CFEqual(oid, kSecPolicyOIDApplePassbook)) {
outOid = kSecPolicyApplePassbookSigning;
}
else if (CFEqual(oid, kSecPolicyOIDAppleMobileStore)) {
outOid = kSecPolicyAppleMobileStore;
}
else if (CFEqual(oid, kSecPolicyOIDAppleTestMobileStore)) {
outOid = kSecPolicyAppleTestMobileStore;
}
else if (CFEqual(oid, kSecPolicyOIDAppleEscrowService)) {
outOid = kSecPolicyAppleEscrowService;
}
else if (CFEqual(oid, kSecPolicyOIDAppleProfileSigner)) {
outOid = kSecPolicyAppleProfileSigner;
}
else if (CFEqual(oid, kSecPolicyOIDAppleQAProfileSigner)) {
outOid = kSecPolicyAppleQAProfileSigner;
}
#if TARGET_OS_IPHONE
else if (CFEqual(oid, kSecPolicyOIDAppleOTAPKIAssetSigner)) {
outOid = kSecPolicyAppleOTAPKISigner;
}
else if (CFEqual(oid, kSecPolicyOIDAppleTestOTAPKIAssetSigner)) {
outOid = kSecPolicyAppleTestOTAPKISigner;
}
else if (CFEqual(oid, kSecPolicyOIDAppleIDValidationRecordSigningPolicy)) {
outOid = kSecPolicyAppleIDValidationRecordSigningPolicy;
}
#endif
CFDictionarySetValue(properties, (const void *)kSecPolicyOid,
(const void *)outOid);
if (nameKey && policyRef->_options) {
CFTypeRef name = (CFTypeRef) CFDictionaryGetValue(policyRef->_options,
nameKey);
if (name) {
CFDictionarySetValue(properties, (const void *)kSecPolicyName,
(const void *)name);
}
}
if (CFEqual(oid, kSecPolicyOIDSSLClient) ||
CFEqual(oid, kSecPolicyOIDIPSecClient) ||
CFEqual(oid, kSecPolicyEAPClient)) {
CFDictionarySetValue(properties, (const void *)kSecPolicyClient,
(const void *)kCFBooleanTrue);
}
CFRelease(oid);
return properties;
}
#if TARGET_OS_MAC && !TARGET_OS_IPHONE
static void SecPolicySetOid(SecPolicyRef policy, CFStringRef oid) {
if (!policy || !oid) return;
CFStringRef temp = policy->_oid;
CFRetain(oid);
policy->_oid = oid;
CFReleaseSafe(temp);
}
static void SecPolicySetOptionsValue(SecPolicyRef policy, CFStringRef key, CFTypeRef value) {
if (!policy || !key) return;
CFMutableDictionaryRef options = (CFMutableDictionaryRef) policy->_options;
if (!options) {
options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (!options) return;
policy->_options = options;
}
CFDictionarySetValue(options, key, value);
}
OSStatus SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properties) {
if (!(policyRef && properties && (CFDictionaryGetTypeID() == CFGetTypeID(properties)))) {
return errSecParam;
}
CFStringRef oid = (CFStringRef) CFRetain(policyRef->_oid);
OSStatus result = errSecSuccess;
CFTypeRef name = NULL;
if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyName,
(const void **)&name) && name) {
CFTypeID typeID = CFGetTypeID(name);
if (CFEqual(oid, kSecPolicyOIDSSLServer) ||
CFEqual(oid, kSecPolicyOIDSSLClient) ||
CFEqual(oid, kSecPolicyOIDIPSecServer) ||
CFEqual(oid, kSecPolicyOIDIPSecClient)) {
if (CFStringGetTypeID() == typeID) {
SecPolicySetOptionsValue(policyRef, kSecPolicyCheckSSLHostname, name);
}
else result = errSecParam;
}
else if (CFEqual(oid, kSecPolicyEAPServer) ||
CFEqual(oid, kSecPolicyEAPClient)) {
if ((CFStringGetTypeID() == typeID) ||
(CFArrayGetTypeID() == typeID)) {
SecPolicySetOptionsValue(policyRef, kSecPolicyCheckEAPTrustedServerNames, name);
}
else result = errSecParam;
}
else if (CFEqual(oid, kSecPolicyOIDSMIME)) {
if (CFStringGetTypeID() == typeID) {
SecPolicySetOptionsValue(policyRef, kSecPolicyCheckEmail, name);
}
else result = errSecParam;
}
}
CFTypeRef client = NULL;
if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyClient,
(const void **)&client) && client) {
if (!(CFBooleanGetTypeID() == CFGetTypeID(client))) {
result = errSecParam;
}
else if (CFEqual(client, kCFBooleanTrue)) {
if (CFEqual(oid, kSecPolicyOIDSSLServer)) {
SecPolicySetOid(policyRef, kSecPolicyOIDSSLClient);
}
else if (CFEqual(oid, kSecPolicyOIDIPSecServer)) {
SecPolicySetOid(policyRef, kSecPolicyOIDIPSecClient);
}
else if (CFEqual(oid, kSecPolicyEAPServer)) {
SecPolicySetOid(policyRef, kSecPolicyEAPClient);
}
}
else {
if (CFEqual(oid, kSecPolicyOIDSSLClient)) {
SecPolicySetOid(policyRef, kSecPolicyOIDSSLServer);
}
else if (CFEqual(oid, kSecPolicyOIDIPSecClient)) {
SecPolicySetOid(policyRef, kSecPolicyOIDIPSecServer);
}
else if (CFEqual(oid, kSecPolicyEAPClient)) {
SecPolicySetOid(policyRef, kSecPolicyEAPServer);
}
}
}
CFRelease(oid);
return result;
}
#endif
static xpc_object_t SecPolicyCopyXPCObject(SecPolicyRef policy, CFErrorRef *error) {
xpc_object_t xpc_policy = NULL;
xpc_object_t data[2] = {};
require_action_quiet(data[0] = _CFXPCCreateXPCObjectFromCFObject(policy->_oid), exit,
SecError(errSecParam, error, CFSTR("failed to create xpc_object from policy oid")));
require_action_quiet(data[1] = _CFXPCCreateXPCObjectFromCFObject(policy->_options), exit,
SecError(errSecParam, error, CFSTR("failed to create xpc_object from policy options")));
require_action_quiet(xpc_policy = xpc_array_create(data, array_size(data)), exit,
SecError(errSecAllocate, error, CFSTR("failed to create xpc_array for policy")));
exit:
if (data[0]) xpc_release(data[0]);
if (data[1]) xpc_release(data[1]);
return xpc_policy;
}
static bool SecPolicyAppendToXPCArray(SecPolicyRef policy, xpc_object_t policies, CFErrorRef *error) {
if (!policy)
return true;
xpc_object_t xpc_policy = SecPolicyCopyXPCObject(policy, error);
if (!xpc_policy)
return false;
xpc_array_append_value(policies, xpc_policy);
xpc_release(xpc_policy);
return true;
}
xpc_object_t SecPolicyArrayCopyXPCArray(CFArrayRef policies, CFErrorRef *error) {
xpc_object_t xpc_policies;
require_action_quiet(xpc_policies = xpc_array_create(NULL, 0), exit,
SecError(errSecAllocate, error, CFSTR("failed to create xpc_array")));
CFIndex ix, count = CFArrayGetCount(policies);
for (ix = 0; ix < count; ++ix) {
if (!SecPolicyAppendToXPCArray((SecPolicyRef)CFArrayGetValueAtIndex(policies, ix), xpc_policies, error)) {
xpc_release(xpc_policies);
return NULL;
}
}
exit:
return xpc_policies;
}
static SecPolicyRef SecPolicyCreateWithXPCObject(xpc_object_t xpc_policy, CFErrorRef *error) {
SecPolicyRef policy = NULL;
CFTypeRef oid = NULL;
CFTypeRef options = NULL;
require_action_quiet(xpc_policy, exit, SecError(errSecParam, error, CFSTR("policy xpc value is NULL")));
require_action_quiet(xpc_get_type(xpc_policy) == XPC_TYPE_ARRAY, exit, SecError(errSecDecode, error, CFSTR("policy xpc value is not an array")));
require_action_quiet(xpc_array_get_count(xpc_policy) == 2, exit, SecError(errSecDecode, error, CFSTR("policy xpc array count != 2")));
oid = _CFXPCCreateCFObjectFromXPCObject(xpc_array_get_value(xpc_policy, 0));
require_action_quiet(isString(oid), exit,
SecError(errSecParam, error, CFSTR("failed to convert xpc policy[0]=%@ to CFString"), oid));
options = _CFXPCCreateCFObjectFromXPCObject(xpc_array_get_value(xpc_policy, 1));
require_action_quiet(isDictionary(options), exit,
SecError(errSecParam, error, CFSTR("failed to convert xpc policy[1]=%@ to CFDictionary"), options));
require_action_quiet(policy = SecPolicyCreate(oid, options), exit, SecError(errSecDecode, error, CFSTR("Failed to create policy")));
exit:
CFReleaseSafe(oid);
CFReleaseSafe(options);
return policy;
}
CFArrayRef SecPolicyXPCArrayCopyArray(xpc_object_t xpc_policies, CFErrorRef *error) {
CFMutableArrayRef policies = NULL;
require_action_quiet(xpc_get_type(xpc_policies) == XPC_TYPE_ARRAY, exit,
SecError(errSecParam, error, CFSTR("policies xpc value is not an array")));
size_t count = xpc_array_get_count(xpc_policies);
require_action_quiet(policies = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks), exit,
SecError(errSecAllocate, error, CFSTR("failed to create CFArray of capacity %zu"), count));
size_t ix;
for (ix = 0; ix < count; ++ix) {
SecPolicyRef policy = SecPolicyCreateWithXPCObject(xpc_array_get_value(xpc_policies, ix), error);
if (!policy) {
CFRelease(policies);
return NULL;
}
CFArraySetValueAtIndex(policies, ix, policy);
CFRelease(policy);
}
exit:
return policies;
}
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 add_leaf_marker_value(CFMutableDictionaryRef options, const DERItem *markerOid, CFStringRef string_value) {
CFTypeRef policyData = NULL;
if (NULL == string_value) {
policyData = CFDataCreate(kCFAllocatorDefault,
markerOid ? markerOid->data : NULL,
markerOid ? markerOid->length : 0);
} else {
CFStringRef oid_as_string = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, markerOid);
const void *key[1] = { oid_as_string };
const void *value[1] = { string_value };
policyData = CFDictionaryCreate(kCFAllocatorDefault,
key, value, 1,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFReleaseNull(oid_as_string);
}
add_element(options, kSecPolicyCheckLeafMarkerOid, policyData);
CFReleaseNull(policyData);
}
static void add_leaf_marker(CFMutableDictionaryRef options, const DERItem *markerOid) {
add_leaf_marker_value(options, markerOid, NULL);
}
static void add_certificate_policy_oid(CFMutableDictionaryRef options, const DERItem *certificatePolicyOid, CFStringRef string_value) {
CFTypeRef certificatePolicyData = NULL;
if (NULL == string_value) {
certificatePolicyData = CFDataCreate(kCFAllocatorDefault,
certificatePolicyOid ? certificatePolicyOid->data : NULL,
certificatePolicyOid ? certificatePolicyOid->length : 0);
} else {
CFStringRef oid_as_string = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, certificatePolicyOid);
const void *key[1] = { oid_as_string };
const void *value[1] = { string_value };
certificatePolicyData = CFDictionaryCreate(kCFAllocatorDefault,
key, value, 1,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFReleaseNull(oid_as_string);
}
add_element(options, kSecPolicyCheckCertificatePolicy, certificatePolicyData);
CFReleaseNull(certificatePolicyData);
}
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);
CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf, kCFBooleanTrue);
CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, 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);
add_element(options, kSecPolicyCheckAnchorSHA1, anchorData);
success = true;
errOut:
CFReleaseSafe(anchorData);
return success;
}
static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef options)
{
return SecPolicyAddAnchorSHA1Options(options, kAppleCASHA1);
}
#if 0
static bool SecPolicyAddAppleTESTAnchorOptions(CFMutableDictionaryRef options)
{
return SecPolicyAddAnchorSHA1Options(options, kAppleTESTCASHA1);
}
#endif
SecPolicyRef SecPolicyCreateBasicX509(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
CFDictionaryAddValue(options, kSecPolicyCheckNoNetworkAccess,
kCFBooleanTrue);
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);
CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, 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(CFOptionFlags revocationFlags) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
if (revocationFlags & kSecRevocationOCSPMethod) {
CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
}
else if (revocationFlags & kSecRevocationCRLMethod) {
CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanTrue);
}
require(((revocationFlags >> 5) == 0), errOut);
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, NULL);
add_eku(options, &oidAnyExtendedKeyUsage);
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_leaf_marker(options, &oidAppleExtendedKeyUsageAppleID);
add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID);
add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID2);
require(result = SecPolicyCreate(kSecPolicyOIDAppleIDAuthority, options), out);
out:
CFReleaseSafe(options);
return result;
}
static SecPolicyRef _SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, CFStringRef teamIdentifier, bool requireTeamID)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), out);
SecPolicyAddBasicX509Options(options);
SecPolicyAddAppleAnchorOptions(options);
if (teamIdentifier) {
CFDictionaryAddValue(options, kSecPolicyCheckSubjectOrganizationalUnit, teamIdentifier);
}
else {
require(!requireTeamID, out);
}
add_leaf_marker_value(options, &oidAppleInstallerPackagingSigningExternal, cardIssuer);
add_eku(options, &oidAppleExtendedKeyUsageShoebox);
require(result = SecPolicyCreate(kSecPolicyOIDApplePassbook, options), out);
out:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, CFStringRef teamIdentifier)
{
return _SecPolicyCreatePassbookCardSigner(cardIssuer, teamIdentifier, true);
}
SecPolicyRef SecPolicyCreateShoeboxCardSigner(CFStringRef cardIssuer)
{
return _SecPolicyCreatePassbookCardSigner(cardIssuer, nil, false);
}
static SecPolicyRef CreateMobileStoreSigner(Boolean forTest)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
SecPolicyAddAppleAnchorOptions(options);
require(SecPolicyAddChainLengthOptions(options, 3), errOut);
CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
CFSTR("Apple System Integration 2 Certification Authority"));
add_ku(options, kSecKeyUsageDigitalSignature);
const DERItem* pOID = (forTest) ? &oidApplePolicyTestMobileStore : &oidApplePolicyMobileStore;
add_certificate_policy_oid(options, pOID, NULL);
require(result = SecPolicyCreate(kSecPolicyOIDAppleMobileStore, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateMobileStoreSigner(void)
{
return CreateMobileStoreSigner(false);
}
SecPolicyRef SecPolicyCreateTestMobileStoreSigner(void)
{
return CreateMobileStoreSigner(true);
}
CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateEscrowServiceSigner(void)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
add_ku(options, kSecKeyUsageKeyEncipherment);
require(SecPolicyAddChainLengthOptions(options, 2), errOut);
Boolean anchorAdded = false;
CFArrayRef anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot);
CFIndex numRoots = 0;
if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray)))
{
goto errOut;
}
for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++)
{
SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt);
if (NULL != aCert)
{
CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert);
if (NULL != sha_data)
{
const UInt8* pSHAData = CFDataGetBytePtr(sha_data);
if (NULL != pSHAData)
{
SecPolicyAddAnchorSHA1Options(options, pSHAData);
anchorAdded = true;
}
}
}
}
CFRelease(anArray);
if (!anchorAdded)
{
goto errOut;
}
require(result = SecPolicyCreate(kSecPolicyOIDAppleEscrowService, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecCertificateRef SecPolicyCopyEscrowRootCertificate(void)
{
SecCertificateRef result = NULL;
return result;
}
SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
SecPolicyAddAppleAnchorOptions(options);
add_eku(options, &oidAppleExtendedKeyUsageProfileSigning);
require(result = SecPolicyCreate(kSecPolicyOIDAppleProfileSigner, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
SecPolicyAddAppleAnchorOptions(options);
add_eku(options, &oidAppleExtendedKeyUsageQAProfileSigning);
require(result = SecPolicyCreate(kSecPolicyOIDAppleQAProfileSigner, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
#if TARGET_OS_IPHONE
SecPolicyRef SecPolicyCreateOTAPKISigner(void)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
SecPolicyAddAnchorSHA1Options(options, kApplePKISettingsAuthority);
require(SecPolicyAddChainLengthOptions(options, 2), errOut);
require(result = SecPolicyCreate(kSecPolicyOIDAppleOTAPKIAssetSigner, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateTestOTAPKISigner(void)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
SecPolicyAddAnchorSHA1Options(options, kAppleTestPKISettingsAuthority);
require(SecPolicyAddChainLengthOptions(options, 2), errOut);
require(result = SecPolicyCreate(kSecPolicyOIDAppleTestOTAPKIAssetSigner, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicX509Options(options);
require(SecPolicyAddAppleAnchorOptions(options), errOut);
add_leaf_marker(options, &oidAppleCertExtensionAppleIDRecordValidationSigning);
add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID);
add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntg2);
CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
require(result = SecPolicyCreate(kSecPolicyOIDAppleIDValidationRecordSigningPolicy, options), errOut);
errOut:
CFReleaseSafe(options);
return result;
}
#endif // TARGET_OS_IPHONE