1/* 2 * Copyright (c) 2007-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * SecPolicy.c - Implementation of various X.509 certificate trust policies 26 */ 27 28#include <Security/SecPolicyInternal.h> 29#include <Security/SecPolicyPriv.h> 30#include <AssertMacros.h> 31#include <pthread.h> 32#include <utilities/debugging.h> 33#include <Security/SecInternal.h> 34#include <CoreFoundation/CFDictionary.h> 35#include <CoreFoundation/CFNumber.h> 36#include <CoreFoundation/CFRuntime.h> 37#include <CoreFoundation/CFString.h> 38#include <CoreFoundation/CFTimeZone.h> 39#include <Security/SecCertificateInternal.h> 40#include <Security/SecCertificatePriv.h> 41#include <libDER/oids.h> 42#include <utilities/SecCFError.h> 43#include <utilities/SecCFWrappers.h> 44#include <utilities/array_size.h> 45#include <ipc/securityd_client.h> 46 47/******************************************************** 48 **************** SecPolicy Constants ******************* 49 ********************************************************/ 50// MARK: - 51// MARK: SecPolicy Constants 52 53#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); 54 55/******************************************************** 56 ************** Unverified Leaf Checks ****************** 57 ********************************************************/ 58CFStringRef kSecPolicyCheckSSLHostname = CFSTR("SSLHostname"); 59 60CFStringRef kSecPolicyCheckEmail = CFSTR("email"); 61 62/* Checks that the issuer of the leaf has exactly one Common Name and that it 63 matches the specified string. */ 64CFStringRef kSecPolicyCheckIssuerCommonName = CFSTR("IssuerCommonName"); 65 66/* Checks that the leaf has exactly one Common Name and that it 67 matches the specified string. */ 68CFStringRef kSecPolicyCheckSubjectCommonName = CFSTR("SubjectCommonName"); 69 70/* Checks that the leaf has exactly one Common Name and that it has the 71 specified string as a prefix. */ 72CFStringRef kSecPolicyCheckSubjectCommonNamePrefix = CFSTR("SubjectCommonNamePrefix"); 73 74/* Checks that the leaf has exactly one Common Name and that it 75 matches the specified "<string>" or "TEST <string> TEST". */ 76CFStringRef kSecPolicyCheckSubjectCommonNameTEST = CFSTR("SubjectCommonNameTEST"); 77 78/* Checks that the leaf has exactly one Organization and that it 79 matches the specified string. */ 80CFStringRef kSecPolicyCheckSubjectOrganization = CFSTR("SubjectOrganization"); 81 82/* Checks that the leaf has exactly one Organizational Unit and that it 83 matches the specified string. */ 84CFStringRef kSecPolicyCheckSubjectOrganizationalUnit = CFSTR("SubjectOrganizationalUnit"); 85 86/* Check that the leaf is not valid before the specified date (or verifyDate 87 if none is provided?). */ 88CFStringRef kSecPolicyCheckNotValidBefore = CFSTR("NotValidBefore"); 89 90CFStringRef kSecPolicyCheckEAPTrustedServerNames = CFSTR("EAPTrustedServerNames"); 91 92CFStringRef kSecPolicyCheckCertificatePolicy = CFSTR("CertificatePolicy"); 93 94#if 0 95/* Check for basic constraints on leaf to be valid. (rfc5280 check) */ 96CFStringRef kSecPolicyCheckLeafBasicConstraints = CFSTR("LeafBasicContraints"); 97#endif 98 99/******************************************************** 100 *********** Unverified Intermediate Checks ************* 101 ********************************************************/ 102CFStringRef kSecPolicyCheckKeyUsage = CFSTR("KeyUsage"); /* (rfc5280 check) */ 103CFStringRef kSecPolicyCheckExtendedKeyUsage = CFSTR("ExtendedKeyUsage"); /* (rfc5280 check) */ 104CFStringRef kSecPolicyCheckBasicContraints = CFSTR("BasicContraints"); /* (rfc5280 check) */ 105CFStringRef kSecPolicyCheckQualifiedCertStatements = 106 CFSTR("QualifiedCertStatements"); /* (rfc5280 check) */ 107 108/******************************************************** 109 ************** Unverified Anchor Checks **************** 110 ********************************************************/ 111CFStringRef kSecPolicyCheckAnchorSHA1 = CFSTR("AnchorSHA1"); 112 113/* Fake key for isAnchored check. */ 114CFStringRef kSecPolicyCheckAnchorTrusted = CFSTR("AnchorTrusted"); 115 116/******************************************************** 117 *********** Unverified Certificate Checks ************** 118 ********************************************************/ 119/* Unverified Certificate Checks (any of the above) */ 120CFStringRef kSecPolicyCheckNonEmptySubject = CFSTR("NonEmptySubject"); 121CFStringRef kSecPolicyCheckIdLinkage = CFSTR("IdLinkage"); /* (rfc5280 check) */ 122#if 0 123CFStringRef kSecPolicyCheckValidityStarted = CFSTR("ValidStarted"); 124CFStringRef kSecPolicyCheckValidityExpired = CFSTR("ValidExpired"); 125#else 126CFStringRef kSecPolicyCheckValidIntermediates = CFSTR("ValidIntermediates"); 127CFStringRef kSecPolicyCheckValidLeaf = CFSTR("ValidLeaf"); 128CFStringRef kSecPolicyCheckValidRoot = CFSTR("ValidRoot"); 129#endif 130 131 132/******************************************************** 133 **************** Verified Path Checks ****************** 134 ********************************************************/ 135/* (rfc5280 check) Ideally we should dynamically track all the extensions 136 we processed for each certificate and fail this test if any critical 137 extensions remain. */ 138CFStringRef kSecPolicyCheckCriticalExtensions = CFSTR("CriticalExtensions"); 139 140/* Check that the certificate chain length matches the specificed CFNumberRef 141 length. */ 142CFStringRef kSecPolicyCheckChainLength = CFSTR("ChainLength"); 143 144/* (rfc5280 check) */ 145CFStringRef kSecPolicyCheckBasicCertificateProcessing = 146 CFSTR("BasicCertificateProcessing"); 147 148/******************************************************** 149 ******************* Feature toggles ******************** 150 ********************************************************/ 151 152/* Check revocation if specified. */ 153CFStringRef kSecPolicyCheckExtendedValidation = CFSTR("ExtendedValidation"); 154CFStringRef kSecPolicyCheckRevocation = CFSTR("Revocation"); 155 156/* If present and true, we never go out to the network for anything 157 (OCSP, CRL or CA Issuer checking) but just used cached data instead. */ 158CFStringRef kSecPolicyCheckNoNetworkAccess = CFSTR("NoNetworkAccess"); 159 160/* Hack to quickly blacklist certain certs. */ 161CFStringRef kSecPolicyCheckBlackListedLeaf = CFSTR("BlackListedLeaf"); 162CFStringRef kSecPolicyCheckGrayListedLeaf = CFSTR("GrayListedLeaf"); 163CFStringRef kSecPolicyCheckGrayListedKey = CFSTR("GrayListedKey"); 164CFStringRef kSecPolicyCheckBlackListedKey = CFSTR("BlackListedKey"); 165 166CFStringRef kSecPolicyCheckLeafMarkerOid = CFSTR("CheckLeafMarkerOid"); 167CFStringRef kSecPolicyCheckIntermediateMarkerOid = CFSTR("CheckIntermediateMarkerOid"); 168 169/* Public policy names. */ 170SEC_CONST_DECL (kSecPolicyAppleX509Basic, "1.2.840.113635.100.1.2"); 171SEC_CONST_DECL (kSecPolicyAppleSSL, "1.2.840.113635.100.1.3"); 172SEC_CONST_DECL (kSecPolicyAppleSMIME, "1.2.840.113635.100.1.8"); 173SEC_CONST_DECL (kSecPolicyAppleEAP, "1.2.840.113635.100.1.9"); 174SEC_CONST_DECL (kSecPolicyAppleIPsec, "1.2.840.113635.100.1.11"); 175SEC_CONST_DECL (kSecPolicyApplePKINITClient, "1.2.840.113635.100.1.14"); 176SEC_CONST_DECL (kSecPolicyApplePKINITServer, "1.2.840.113635.100.1.15"); 177SEC_CONST_DECL (kSecPolicyAppleCodeSigning, "1.2.840.113635.100.1.16"); 178SEC_CONST_DECL (kSecPolicyApplePackageSigning, "1.2.840.113635.100.1.17"); 179SEC_CONST_DECL (kSecPolicyAppleIDValidation, "1.2.840.113635.100.1.18"); 180SEC_CONST_DECL (kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19"); 181SEC_CONST_DECL (kSecPolicyAppleTimeStamping, "1.2.840.113635.100.1.20"); 182SEC_CONST_DECL (kSecPolicyAppleRevocation, "1.2.840.113635.100.1.21"); 183SEC_CONST_DECL (kSecPolicyApplePassbookSigning, "1.2.840.113635.100.1.22"); 184SEC_CONST_DECL (kSecPolicyAppleMobileStore, "1.2.840.113635.100.1.23"); 185SEC_CONST_DECL (kSecPolicyAppleEscrowService, "1.2.840.113635.100.1.24"); 186SEC_CONST_DECL (kSecPolicyAppleProfileSigner, "1.2.840.113635.100.1.25"); 187SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner, "1.2.840.113635.100.1.26"); 188SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27"); 189#if TARGET_OS_IPHONE 190SEC_CONST_DECL (kSecPolicyAppleOTAPKISigner, "1.2.840.113635.100.1.28"); 191SEC_CONST_DECL (kSecPolicyAppleTestOTAPKISigner, "1.2.840.113635.100.1.29"); 192/* FIXME: this policy name should be deprecated and replaced with "kSecPolicyAppleIDValidationRecordSigning" */ 193SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113625.100.1.30"); 194SEC_CONST_DECL (kSecPolicyAppleSMPEncryption, "1.2.840.113625.100.1.31"); 195SEC_CONST_DECL (kSecPolicyAppleTestSMPEncryption, "1.2.840.113625.100.1.32"); 196#endif 197SEC_CONST_DECL (kSecPolicyAppleServerAuthentication, "1.2.840.113635.100.1.33"); 198SEC_CONST_DECL (kSecPolicyApplePCSEscrowService, "1.2.840.113635.100.1.34"); 199 200SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid"); 201SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); 202SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient"); 203SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags"); 204SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier"); 205 206/* Private policy names */ 207static CFStringRef kSecPolicyOIDBasicX509 = CFSTR("basicX509"); 208static CFStringRef kSecPolicyOIDSSLServer = CFSTR("sslServer"); 209static CFStringRef kSecPolicyOIDSSLClient = CFSTR("sslClient"); 210static CFStringRef kSecPolicyOIDiPhoneActivation = CFSTR("iPhoneActivation"); 211static CFStringRef kSecPolicyOIDiPhoneDeviceCertificate = 212 CFSTR("iPhoneDeviceCertificate"); 213static CFStringRef kSecPolicyOIDFactoryDeviceCertificate = 214 CFSTR("FactoryDeviceCertificate"); 215static CFStringRef kSecPolicyOIDiAP = CFSTR("iAP"); 216static CFStringRef kSecPolicyOIDiTunesStoreURLBag = CFSTR("iTunesStoreURLBag"); 217static CFStringRef kSecPolicyEAPServer = CFSTR("eapServer"); 218static CFStringRef kSecPolicyEAPClient = CFSTR("eapClient"); 219static CFStringRef kSecPolicyOIDIPSecServer = CFSTR("ipsecServer"); 220static CFStringRef kSecPolicyOIDIPSecClient = CFSTR("ipsecClient"); 221static CFStringRef kSecPolicyOIDiPhoneApplicationSigning = 222 CFSTR("iPhoneApplicationSigning"); 223static CFStringRef kSecPolicyOIDiPhoneProfileApplicationSigning = 224 CFSTR("iPhoneProfileApplicationSigning"); 225static CFStringRef kSecPolicyOIDiPhoneProvisioningProfileSigning = 226 CFSTR("iPhoneProvisioningProfileSigning"); 227static CFStringRef kSecPolicyOIDRevocation = CFSTR("revocation"); 228static CFStringRef kSecPolicyOIDOCSPSigner = CFSTR("OCSPSigner"); 229static CFStringRef kSecPolicyOIDSMIME = CFSTR("SMIME"); 230static CFStringRef kSecPolicyOIDCodeSigning = CFSTR("CodeSigning"); 231static CFStringRef kSecPolicyOIDLockdownPairing = CFSTR("LockdownPairing"); 232static CFStringRef kSecPolicyOIDURLBag = CFSTR("URLBag"); 233static CFStringRef kSecPolicyOIDOTATasking = CFSTR("OTATasking"); 234static CFStringRef kSecPolicyOIDMobileAsset = CFSTR("MobileAsset"); 235static CFStringRef kSecPolicyOIDAppleIDAuthority = CFSTR("AppleIDAuthority"); 236static CFStringRef kSecPolicyOIDAppleShoebox = CFSTR("AppleShoebox"); 237static CFStringRef kSecPolicyOIDApplePassbook = CFSTR("ApplePassbook"); 238static CFStringRef kSecPolicyOIDAppleMobileStore = CFSTR("AppleMobileStore"); 239static CFStringRef kSecPolicyOIDAppleTestMobileStore = CFSTR("AppleTestMobileStore"); 240static CFStringRef kSecPolicyOIDAppleEscrowService = CFSTR("AppleEscrowService"); 241static CFStringRef kSecPolicyOIDApplePCSEscrowService = CFSTR("ApplePCSEscrowService"); 242static CFStringRef kSecPolicyOIDAppleProfileSigner = CFSTR("AppleProfileSigner"); 243static CFStringRef kSecPolicyOIDAppleQAProfileSigner = CFSTR("AppleQAProfileSigner"); 244static CFStringRef kSecPolicyOIDAppleOTAPKIAssetSigner = CFSTR("AppleOTAPKIAssetSigner"); 245static CFStringRef kSecPolicyOIDAppleTestOTAPKIAssetSigner = CFSTR("AppleTestOTAPKIAssetSigner"); 246static CFStringRef kSecPolicyOIDAppleIDValidationRecordSigningPolicy = CFSTR("AppleIDValidationRecordSigningPolicy"); 247 248 249/* Policies will now change to multiple categories of checks. 250 251 IDEA Store partial valid policy tree in each chain? Result tree pruning might make this not feasible unless you can pretend to prune the tree without actually deleting nodes and somehow still have shable nodes with parent chains (this assumes that chains will be built as cached things from the root down), and we can build something equivalent to rfc5280 in a tree of certs. So we need to maintain a cache of leaf->chain with this certificate as any_ca_cert->tree. Revocation status caching can be done in this cache as well, so maybe the cache should be in sqlite3, or at least written there before exit and querying of the cache could be done first on the in core (possibly CF or custom tree like structure) and secondarly on the sqlite3 backed store. We should choose the lowest memory footprint solution in my mind, while choosing a sqlite3 cache size that gives us a resonable io usage pattern. 252 NOTE no certificate can be an intermediate unless it is X.509V3 and it has a basicConstraints extension with isCA set to true. This can be used to classify certs for caching purposes. 253 254 kSecPolicySLCheck Static Subscriber Certificate Checks 255 kSecPolicySICheck Static Subsidiary CA Checks 256 kSecPolicySACheck Static Anchor Checks 257 258 kSecPolicyDLCheck Dynamic Subscriber Certificate Checks 259 kSecPolicyDICheck Dynamic Subsidiary CA Checks 260 kSecPolicyDACheck Dynamic Anchor Checks ? not yet needed other than to 261 possibly exclude in a exception template (but those should still be per 262 certificate --- i.o.w. exceptions (or a database backed multiple role/user 263 trust store of some sort) and policies are 2 different things and this 264 text is about policies. 265 266 All static checks are only allowed to consider the certificate in isolation, 267 just given the position in the chain or the cert (leaf, intermidate, root). 268 dynamic checks can make determinations about the chain as a whole. 269 270 Static Subscriber Certificate Checks will be done up front before the 271 chainbuilder is even instantiated. If they fail and details aren't required 272 by the client (if no exceptions were present for this certificate) we could 273 short circuit fail the evaluation. 274 IDEA: These checks can dynamically add new checks...[needs work] 275 ALTERNATIVE: A policy can have one or more sub-policies. Each sub-policy will be evaluated only after the parent policy succeeds. Subpolicies can be either required (making the parent policy fail) or optional making the parent policy succeed, but allowing the chainbuilder to continue building chains after an optional subpolicy failure in search of a chain for which the subpolicy also succeeded. Subpolicies can be dynamically added to the policy evaluation context tree (a tree with a node for every node in the certificate path. This tree however is from the leaf up stored in the SecCertificatePathRef objects themselves possibly - requiring a separate shared subtree of nodes for the underlying certificate state tree.) by a parent policy at any stage, since the subpolicy evaluation only starts after 276 will have a key in the info (or even details and make info client side generated from info to indicate the success or failure of optional subpolicies) tree the value of which is an 277 equivalent subtree from that level down. So SSL has EV as a subpolicy, but 278 EV dynamically enables the ocsp or crl or dcrl or any combination thereof subpolicies. 279 280 Static Subsidiary CA Checks will be used by the chain-builder to choose the 281 best parents to evaluate first. This feature is currently already implemented 282 but with a hardcoded is_valid(verifyTime) check. Instead we will evaluate all 283 Static Subsidiary CA Checks. The results of these checks for purposes of 284 generating details could be cached in the SecCertificatePathRefs themselves, or we can short circuit fail and recalc details on demand later. 285 286 Static Anchor Checks can do things like populate the chainbuilder level context value of the initial_valid_policy_tree with a particular anchors list of ev policies it represents or modify inputs to the policy itself. 287 288 Dynamic Subscriber Certificate Checks These can do things like check for EV policy conformance based on the valid_policy_tree at the end of the certificate evaluation, or based on things like the pathlen, etc. in the chain validation context. 289 290 Dynamic Subsidiary CA Checks might not be needed to have custom 291 implementations, since they are all done as part of the rfc5280 checks now. 292 This assumes that checks like issuer common name includes 'foo' are 293 implmented as Static Subscriber Certificate Checks instead. 294 295 Dynamic Anchor Checks might include EV type checks or chain validation context seeding as well, allthough we might be able to do them as static checks to seed the chain validation context instead. 296 297 298 Questions/Notes: Do we need to dynamically add new policies? If policy static checks fail and policy is optional we don't even run policy dynamic checks nor do we compute subpolicy values. So if the static check of the leaf for EV fails we skip the rest of the EV style checks and instead don't run the revocation subpolicy of the ev policy. 299 300 If an optional subpolicy s_p has a required subpolicy r_s_p. Then success of s_p will cause the entire chain evaluation to fail if r_s_p fails. 301 302 All policies static revocation checks are run at the appropriate phase in the evaluation. static leaf checks are done before chainbuilding even starts. static intermediate checks are done in the chainbuilder for each cadidate parent certificate. If all policies pass we check the signatures. We reject the whole chain if that step fails. Otherwise we add the path to builder->candidatePaths. If the top level policy or a required subpolicy or a required subpolicy of a successful subpolicy fails we stick the chain at the end of the expiredPaths, if one of the optional subpolicies fail, we stick the chain at the start of expiredPaths so it's considered first after all real candidatePaths have been processed. 303 304 Static revocation policy checks could check the passed in ocspresponses or even the local cache, though the latter is probably best left for the dynamic phase. 305 306 The same rules that apply above to the adding paths to candidatePaths v/s expiredPaths apply to dynamicpolicy checks, except that we don't remember failures anymore, we reject them. 307 308 We need to remember the best successful chain we find, where best is defined by: satisfies as many optional policies as possible. 309 310 Chain building ends when either we find a chain that matches all optional and required policies, or we run out of chains to build. Another case is if we run out of candiate paths but we already have a chain that matches at least the top level and required subpolicies. In that case we don't even consider any expiredPaths. Example: we find a valid SSL chain (top level policy), but no partial chain we constructed satisfied the static checks of the ev subpolicy, or the required revocation sub-subpolicy of the ev policy. 311 312 In order for this to work well with exceptions on subpolicies, we'd need to move the validation of exceptions to the server, something we'd do anyway if we had full on truststore. In this case exceptions would be live in the failure callback for a trust check. 313 314Example sectrust operation in psuedocode: 315 */ 316#if 0 317{ 318 new builder(verifyTime, certificates, anchors, anchorsOnly, policies); 319 chain = builder.subscriber_only_chain; 320 foreach (policy in policies{kSecPolicySLCheck}) { 321 foreach(check in policy) 322 SecPolicyRunCheck(builder, chain, check, details); 323 foreach (subpolicy in policy) { 324 check_policy(builder, chain, subpolicy, details{subpolicy.name}) 325 } 326 propagate_subpolicy_results(builder, chain, details); 327 } 328 while (chain = builder.next) { 329 for (depth = 0; p_d = policies.at_depth(depth), 330 d_p_d = dynamic_policies.at_depth(depth), p_d || d_p_d; ++depth) 331 { 332 /* Modify SecPathBuilderIsPartial() to 333 run builder_check(buildier, policies, kSecPolicySICheck) instead 334 of SecCertificateIsValid. Also rename considerExpired to 335 considerSIFailures. 336 */ 337 foreach (policy in p_d) { 338 check_policy(builder, chain, policy, kSecPolicySICheck, depth); 339 } 340 /* Recalculate since the static checks might have added new dynamic 341 policies. */ 342 d_p_d = dynamic_policies.at_depth(depth); 343 foreach (policy in d_p_d) { 344 check_policy(builder, chain, policy, kSecPolicySICheck, depth); 345 } 346 if (chain.is_anchored) { 347 foreach (policy in p_d) { 348 check_policy(builder, chain, policy, kSecPolicySACheck, depth); 349 } 350 foreach (policy in d_p_d) { 351 check_policy(builder, chain, policy, kSecPolicySACheck, depth); 352 } 353 foreach (policy in p_d) { 354 check_policy(builder, chain, policy, kSecPolicyDACheck, depth); 355 } 356 foreach (policy in d_p_d) { 357 check_policy(builder, chain, policy, kSecPolicyDACheck, depth); 358 } 359 } 360 foreach (policy in policies) { 361 check_policy(builder, chain, policy, kSecPolicySACheck, depth); 362 check_policy(builder, chain, policy, kSecPolicyDACheck, depth); 363 } 364 foreach (policy in policies{kSecPolicySDCheck}) { 365 } 366 } 367} 368 369check_policy(builder, chain, policy, check_class, details, depth) { 370 if (depth == 0) { 371 foreach(check in policy{check_class}) { 372 SecPolicyRunCheck(builder, chain, check, details); 373 } 374 } else { 375 depth--; 376 foreach (subpolicy in policy) { 377 if (!check_policy(builder, chain, subpolicy, check_class, 378 details{subpolicy.name}) && subpolicy.is_required, depth) 379 secpvcsetresult() 380 } 381 } 382 propagate_subpolicy_results(builder, chain, details); 383} 384 385#endif 386 387 388 389#define kSecPolicySHA1Size 20 390const UInt8 kAppleCASHA1[kSecPolicySHA1Size] = { 391 0x61, 0x1E, 0x5B, 0x66, 0x2C, 0x59, 0x3A, 0x08, 0xFF, 0x58, 392 0xD1, 0x4A, 0xE2, 0x24, 0x52, 0xD1, 0x98, 0xDF, 0x6C, 0x60 393}; 394 395__unused static const UInt8 kAppleTESTCASHA1[kSecPolicySHA1Size] = { 396 0xbc, 0x30, 0x55, 0xc8, 0xc8, 0xd3, 0x48, 0x3f, 0xf4, 0x8d, 397 0xfe, 0x3d, 0x51, 0x75, 0x31, 0xc9, 0xf4, 0xd7, 0x4a, 0xf7 398}; 399 400static const UInt8 kITMSCASHA1[kSecPolicySHA1Size] = { 401 0x1D, 0x33, 0x42, 0x46, 0x8B, 0x10, 0xBD, 0xE6, 0x45, 0xCE, 402 0x44, 0x6E, 0xBB, 0xE8, 0xF5, 0x03, 0x5D, 0xF8, 0x32, 0x22 403}; 404 405static const UInt8 kFactoryDeviceCASHA1[kSecPolicySHA1Size] = { 406 0xef, 0x68, 0x73, 0x17, 0xa4, 0xf8, 0xf9, 0x4b, 0x7b, 0x21, 407 0xe2, 0x2f, 0x09, 0x8f, 0xfd, 0x6a, 0xae, 0xc0, 0x0d, 0x63 408}; 409 410#if TARGET_OS_IPHONE 411static const UInt8 kApplePKISettingsAuthority[kSecPolicySHA1Size] = { 412 0x1D, 0x0C, 0xBA, 0xAD, 0x17, 0xFD, 0x7E, 0x9E, 0x9F, 0xF1, 413 0xC9, 0xA2, 0x66, 0x79, 0x60, 0x00, 0x8B, 0xAE, 0x70, 0xB8 414}; 415 416static const UInt8 kAppleTestPKISettingsAuthority[kSecPolicySHA1Size] = { 417 0xDB, 0xBA, 0x25, 0x0B, 0xD8, 0x62, 0x71, 0x87, 0x54, 0x7E, 418 0xD7, 0xEF, 0x11, 0x94, 0x7E, 0x82, 0xE6, 0xD8, 0x1C, 0x9A 419}; 420 421static const UInt8 kTestAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = { 422 0x62, 0x0A, 0xED, 0x83, 0xD2, 0x97, 0x4A, 0x77, 0x56, 0x33, 423 0x83, 0xBE, 0xDB, 0xF9, 0xA1, 0xBD, 0x5F, 0xFE, 0x55, 0x7B 424}; 425 426static const UInt8 kAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = { 427 0xB5, 0x2C, 0xB0, 0x2F, 0xD5, 0x67, 0xE0, 0x35, 0x9F, 0xE8, 428 0xFA, 0x4D, 0x4C, 0x41, 0x03, 0x79, 0x70, 0xFE, 0x01, 0xB0 429}; 430#endif 431 432// MARK: - 433// MARK: SecPolicy 434/******************************************************** 435 ****************** SecPolicy object ******************** 436 ********************************************************/ 437 438static void SecPolicyDestroy(CFTypeRef cf) { 439 SecPolicyRef policy = (SecPolicyRef) cf; 440 CFRelease(policy->_oid); 441 CFRelease(policy->_options); 442} 443 444static Boolean SecPolicyCompare(CFTypeRef cf1, CFTypeRef cf2) { 445 SecPolicyRef policy1 = (SecPolicyRef) cf1; 446 SecPolicyRef policy2 = (SecPolicyRef) cf2; 447 return CFEqual(policy1->_oid, policy2->_oid) && 448 CFEqual(policy1->_options, policy2->_options); 449} 450 451static CFHashCode SecPolicyHash(CFTypeRef cf) { 452 SecPolicyRef policy = (SecPolicyRef) cf; 453 454 return CFHash(policy->_oid) + CFHash(policy->_options); 455} 456 457static CFStringRef SecPolicyCopyDescription(CFTypeRef cf) { 458 SecPolicyRef policy = (SecPolicyRef) cf; 459 CFMutableStringRef desc = CFStringCreateMutable(kCFAllocatorDefault, 0); 460 CFStringRef typeStr = CFCopyTypeIDDescription(CFGetTypeID(cf)); 461 CFStringAppendFormat(desc, NULL, 462 CFSTR("<%@: oid: %@ options %@"), typeStr, 463 policy->_oid, policy->_options); 464 CFRelease(typeStr); 465 CFStringAppend(desc, CFSTR(" >")); 466 467 return desc; 468} 469 470/* SecPolicy API functions. */ 471CFGiblisWithHashFor(SecPolicy) 472 473/* AUDIT[securityd](done): 474 oid (ok) is a caller provided string, only its cf type has been checked. 475 options is a caller provided dictionary, only its cf type has been checked. 476 */ 477SecPolicyRef SecPolicyCreate(CFStringRef oid, CFDictionaryRef options) { 478 SecPolicyRef result = NULL; 479 480 require(oid, errOut); 481 require(options, errOut); 482 require(result = 483 (SecPolicyRef)_CFRuntimeCreateInstance(kCFAllocatorDefault, 484 SecPolicyGetTypeID(), 485 sizeof(struct __SecPolicy) - sizeof(CFRuntimeBase), 0), errOut); 486 487 CFRetain(oid); 488 result->_oid = oid; 489 CFRetain(options); 490 result->_options = options; 491 492errOut: 493 return result; 494} 495 496SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, 497 CFDictionaryRef properties) { 498 // Creates a policy reference for a given policy object identifier. 499 // If policy-specific parameters can be supplied (e.g. hostname), 500 // attempt to obtain from input properties dictionary. 501 // Returns NULL if the given identifier is unsupported. 502 503 SecPolicyRef policy = NULL; 504 CFStringRef name = NULL; 505 CFStringRef teamID = NULL; 506 Boolean client = false; 507 require(policyIdentifier && (CFStringGetTypeID() == CFGetTypeID(policyIdentifier)), errOut); 508 509 if (properties) { 510 name = CFDictionaryGetValue(properties, kSecPolicyName); 511 teamID = CFDictionaryGetValue(properties, kSecPolicyTeamIdentifier); 512 513 CFBooleanRef dictionaryClientValue; 514 client = (CFDictionaryGetValueIfPresent(properties, kSecPolicyClient, (const void **)&dictionaryClientValue) && 515 (dictionaryClientValue != NULL) && CFEqual(kCFBooleanTrue, dictionaryClientValue)); 516 } 517 518 if (CFEqual(policyIdentifier, kSecPolicyAppleX509Basic)) { 519 policy = SecPolicyCreateBasicX509(); 520 } 521 else if (CFEqual(policyIdentifier, kSecPolicyAppleSSL)) { 522 policy = SecPolicyCreateSSL(!client, name); 523 } 524 else if (CFEqual(policyIdentifier, kSecPolicyAppleEAP)) { 525 CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, (const void **)&name, 1, 526 &kCFTypeArrayCallBacks); 527 policy = SecPolicyCreateEAP(!client, array); 528 CFReleaseSafe(array); 529 } 530 else if (CFEqual(policyIdentifier, kSecPolicyAppleIPsec)) { 531 policy = SecPolicyCreateIPSec(!client, name); 532 } 533 else if (CFEqual(policyIdentifier, kSecPolicyAppleRevocation)) { 534 policy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); 535 } 536 else if (CFEqual(policyIdentifier, kSecPolicyAppleSMIME)) { 537 policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, name); 538 } 539 else if (CFEqual(policyIdentifier, kSecPolicyAppleCodeSigning)) { 540 policy = SecPolicyCreateCodeSigning(); 541 } 542 else if (CFEqual(policyIdentifier, kSecPolicyAppleIDValidation)) { 543 policy = SecPolicyCreateAppleIDAuthorityPolicy(); 544 } 545 else if (CFEqual(policyIdentifier, kSecPolicyApplePassbookSigning)) { 546 policy = SecPolicyCreatePassbookCardSigner(name, teamID); 547 } 548 else if (CFEqual(policyIdentifier, kSecPolicyAppleMobileStore)) { 549 policy = SecPolicyCreateMobileStoreSigner(); 550 } 551 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestMobileStore)) { 552 policy = SecPolicyCreateTestMobileStoreSigner(); 553 } 554 else if (CFEqual(policyIdentifier, kSecPolicyAppleEscrowService)) { 555 policy = SecPolicyCreateEscrowServiceSigner(); 556 } 557 else if (CFEqual(policyIdentifier, kSecPolicyApplePCSEscrowService)) { 558 policy = SecPolicyCreatePCSEscrowServiceSigner(); 559 } 560 else if (CFEqual(policyIdentifier, kSecPolicyAppleProfileSigner)) { 561 policy = SecPolicyCreateConfigurationProfileSigner(); 562 } 563 else if (CFEqual(policyIdentifier, kSecPolicyAppleQAProfileSigner)) { 564 policy = SecPolicyCreateQAConfigurationProfileSigner(); 565 } 566 else if (CFEqual(policyIdentifier, kSecPolicyAppleServerAuthentication)) { 567 policy = SecPolicyCreateAppleSSLService(name); 568 } 569#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR 570 else if (CFEqual(policyIdentifier, kSecPolicyAppleOTAPKISigner)) { 571 policy = SecPolicyCreateOTAPKISigner(); 572 } 573 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestOTAPKISigner)) { 574 policy = SecPolicyCreateTestOTAPKISigner(); 575 } 576 else if (CFEqual(policyIdentifier, kSecPolicyAppleIDValidationRecordSigningPolicy)) { 577 policy = SecPolicyCreateAppleIDValidationRecordSigningPolicy(); 578 } 579 else if (CFEqual(policyIdentifier, kSecPolicyAppleSMPEncryption)) { 580 policy = SecPolicyCreateAppleSMPEncryption(); 581 } 582 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestSMPEncryption)) { 583 policy = SecPolicyCreateTestAppleSMPEncryption(); 584 } 585#endif 586 587errOut: 588 return policy; 589} 590 591CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) { 592 // Builds and returns a dictionary which the caller must release. 593 594 if (!policyRef) return NULL; 595 CFMutableDictionaryRef properties = CFDictionaryCreateMutable(NULL, 0, 596 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 597 if (!properties) return NULL; 598 CFStringRef oid = (CFStringRef) CFRetain(policyRef->_oid); 599 CFTypeRef nameKey = NULL; 600 601 // Convert private to public OID if we have one 602 CFStringRef outOid = oid; 603 if (CFEqual(oid, kSecPolicyOIDBasicX509)) { 604 outOid = kSecPolicyAppleX509Basic; 605 } 606 else if (CFEqual(oid, kSecPolicyOIDSSLServer) || 607 CFEqual(oid, kSecPolicyOIDSSLClient)) { 608 outOid = kSecPolicyAppleSSL; 609 nameKey = kSecPolicyCheckSSLHostname; 610 } 611 else if (CFEqual(oid, kSecPolicyEAPServer) || 612 CFEqual(oid, kSecPolicyEAPClient)) { 613 outOid = kSecPolicyAppleEAP; 614 nameKey = kSecPolicyCheckEAPTrustedServerNames; 615 } 616 else if (CFEqual(oid, kSecPolicyOIDIPSecServer) || 617 CFEqual(oid, kSecPolicyOIDIPSecClient)) { 618 outOid = kSecPolicyAppleIPsec; 619 nameKey = kSecPolicyCheckSSLHostname; 620 } 621 else if (CFEqual(oid, kSecPolicyOIDRevocation)) { 622 outOid = kSecPolicyAppleRevocation; 623 } 624 else if (CFEqual(oid, kSecPolicyOIDSMIME)) { 625 outOid = kSecPolicyAppleSMIME; 626 nameKey = kSecPolicyCheckEmail; 627 } 628 else if (CFEqual(oid, kSecPolicyOIDCodeSigning)) { 629 outOid = kSecPolicyAppleCodeSigning; 630 } 631 else if (CFEqual(oid, kSecPolicyOIDAppleIDAuthority)) { 632 outOid = kSecPolicyAppleIDValidation; 633 } 634 else if (CFEqual(oid, kSecPolicyOIDApplePassbook)) { 635 outOid = kSecPolicyApplePassbookSigning; 636 } 637 else if (CFEqual(oid, kSecPolicyOIDAppleMobileStore)) { 638 outOid = kSecPolicyAppleMobileStore; 639 } 640 else if (CFEqual(oid, kSecPolicyOIDAppleTestMobileStore)) { 641 outOid = kSecPolicyAppleTestMobileStore; 642 } 643 else if (CFEqual(oid, kSecPolicyOIDAppleEscrowService)) { 644 outOid = kSecPolicyAppleEscrowService; 645 } 646 else if (CFEqual(oid, kSecPolicyOIDApplePCSEscrowService)) { 647 outOid = kSecPolicyApplePCSEscrowService; 648 } 649 else if (CFEqual(oid, kSecPolicyOIDAppleProfileSigner)) { 650 outOid = kSecPolicyAppleProfileSigner; 651 } 652 else if (CFEqual(oid, kSecPolicyOIDAppleQAProfileSigner)) { 653 outOid = kSecPolicyAppleQAProfileSigner; 654 } 655#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR 656 else if (CFEqual(oid, kSecPolicyOIDAppleOTAPKIAssetSigner)) { 657 outOid = kSecPolicyAppleOTAPKISigner; 658 } 659 else if (CFEqual(oid, kSecPolicyOIDAppleTestOTAPKIAssetSigner)) { 660 outOid = kSecPolicyAppleTestOTAPKISigner; 661 } 662 else if (CFEqual(oid, kSecPolicyOIDAppleIDValidationRecordSigningPolicy)) { 663 outOid = kSecPolicyAppleIDValidationRecordSigningPolicy; 664 } 665#endif 666 667 // Set kSecPolicyOid 668 CFDictionarySetValue(properties, (const void *)kSecPolicyOid, 669 (const void *)outOid); 670 671 // Set kSecPolicyName if we have one 672 if (nameKey && policyRef->_options) { 673 CFTypeRef name = (CFTypeRef) CFDictionaryGetValue(policyRef->_options, 674 nameKey); 675 if (name) { 676 CFDictionarySetValue(properties, (const void *)kSecPolicyName, 677 (const void *)name); 678 } 679 } 680 681 // Set kSecPolicyClient 682 if (CFEqual(oid, kSecPolicyOIDSSLClient) || 683 CFEqual(oid, kSecPolicyOIDIPSecClient) || 684 CFEqual(oid, kSecPolicyEAPClient)) { 685 CFDictionarySetValue(properties, (const void *)kSecPolicyClient, 686 (const void *)kCFBooleanTrue); 687 } 688 689 CFRelease(oid); 690 return properties; 691} 692 693#if TARGET_OS_MAC && !TARGET_OS_IPHONE 694static void SecPolicySetOid(SecPolicyRef policy, CFStringRef oid) { 695 if (!policy || !oid) return; 696 CFStringRef temp = policy->_oid; 697 CFRetain(oid); 698 policy->_oid = oid; 699 CFReleaseSafe(temp); 700} 701 702static void SecPolicySetOptionsValue(SecPolicyRef policy, CFStringRef key, CFTypeRef value) { 703 if (!policy || !key) return; 704 CFMutableDictionaryRef options = (CFMutableDictionaryRef) policy->_options; 705 if (!options) { 706 options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 707 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 708 if (!options) return; 709 policy->_options = options; 710 } 711 CFDictionarySetValue(options, key, value); 712} 713 714OSStatus SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properties) { 715 // Set policy options based on the provided dictionary keys. 716 717 if (!(policyRef && properties && (CFDictionaryGetTypeID() == CFGetTypeID(properties)))) { 718 return errSecParam; 719 } 720 CFStringRef oid = (CFStringRef) CFRetain(policyRef->_oid); 721 OSStatus result = errSecSuccess; 722 723 // kSecPolicyName 724 CFTypeRef name = NULL; 725 if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyName, 726 (const void **)&name) && name) { 727 CFTypeID typeID = CFGetTypeID(name); 728 if (CFEqual(oid, kSecPolicyOIDSSLServer) || 729 CFEqual(oid, kSecPolicyOIDSSLClient) || 730 CFEqual(oid, kSecPolicyOIDIPSecServer) || 731 CFEqual(oid, kSecPolicyOIDIPSecClient)) { 732 if (CFStringGetTypeID() == typeID) { 733 SecPolicySetOptionsValue(policyRef, kSecPolicyCheckSSLHostname, name); 734 } 735 else result = errSecParam; 736 } 737 else if (CFEqual(oid, kSecPolicyEAPServer) || 738 CFEqual(oid, kSecPolicyEAPClient)) { 739 if ((CFStringGetTypeID() == typeID) || 740 (CFArrayGetTypeID() == typeID)) { 741 SecPolicySetOptionsValue(policyRef, kSecPolicyCheckEAPTrustedServerNames, name); 742 } 743 else result = errSecParam; 744 } 745 else if (CFEqual(oid, kSecPolicyOIDSMIME)) { 746 if (CFStringGetTypeID() == typeID) { 747 SecPolicySetOptionsValue(policyRef, kSecPolicyCheckEmail, name); 748 } 749 else result = errSecParam; 750 } 751 } 752 753 // kSecPolicyClient 754 CFTypeRef client = NULL; 755 if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyClient, 756 (const void **)&client) && client) { 757 if (!(CFBooleanGetTypeID() == CFGetTypeID(client))) { 758 result = errSecParam; 759 } 760 else if (CFEqual(client, kCFBooleanTrue)) { 761 if (CFEqual(oid, kSecPolicyOIDSSLServer)) { 762 SecPolicySetOid(policyRef, kSecPolicyOIDSSLClient); 763 } 764 else if (CFEqual(oid, kSecPolicyOIDIPSecServer)) { 765 SecPolicySetOid(policyRef, kSecPolicyOIDIPSecClient); 766 } 767 else if (CFEqual(oid, kSecPolicyEAPServer)) { 768 SecPolicySetOid(policyRef, kSecPolicyEAPClient); 769 } 770 } 771 else { 772 if (CFEqual(oid, kSecPolicyOIDSSLClient)) { 773 SecPolicySetOid(policyRef, kSecPolicyOIDSSLServer); 774 } 775 else if (CFEqual(oid, kSecPolicyOIDIPSecClient)) { 776 SecPolicySetOid(policyRef, kSecPolicyOIDIPSecServer); 777 } 778 else if (CFEqual(oid, kSecPolicyEAPClient)) { 779 SecPolicySetOid(policyRef, kSecPolicyEAPServer); 780 } 781 } 782 } 783 784 CFRelease(oid); 785 return result; 786} 787#endif 788 789static xpc_object_t SecPolicyCopyXPCObject(SecPolicyRef policy, CFErrorRef *error) { 790 xpc_object_t xpc_policy = NULL; 791 xpc_object_t data[2] = {}; 792 require_action_quiet(data[0] = _CFXPCCreateXPCObjectFromCFObject(policy->_oid), exit, 793 SecError(errSecParam, error, CFSTR("failed to create xpc_object from policy oid"))); 794 require_action_quiet(data[1] = _CFXPCCreateXPCObjectFromCFObject(policy->_options), exit, 795 SecError(errSecParam, error, CFSTR("failed to create xpc_object from policy options"))); 796 require_action_quiet(xpc_policy = xpc_array_create(data, array_size(data)), exit, 797 SecError(errSecAllocate, error, CFSTR("failed to create xpc_array for policy"))); 798 799exit: 800 if (data[0]) xpc_release(data[0]); 801 if (data[1]) xpc_release(data[1]); 802 return xpc_policy; 803} 804 805static bool SecPolicyAppendToXPCArray(SecPolicyRef policy, xpc_object_t policies, CFErrorRef *error) { 806 if (!policy) 807 return true; // NOOP 808 809 xpc_object_t xpc_policy = SecPolicyCopyXPCObject(policy, error); 810 if (!xpc_policy) 811 return false; 812 813 xpc_array_append_value(policies, xpc_policy); 814 xpc_release(xpc_policy); 815 return true; 816} 817 818xpc_object_t SecPolicyArrayCopyXPCArray(CFArrayRef policies, CFErrorRef *error) { 819 xpc_object_t xpc_policies; 820 require_action_quiet(xpc_policies = xpc_array_create(NULL, 0), exit, 821 SecError(errSecAllocate, error, CFSTR("failed to create xpc_array"))); 822 CFIndex ix, count = CFArrayGetCount(policies); 823 for (ix = 0; ix < count; ++ix) { 824 if (!SecPolicyAppendToXPCArray((SecPolicyRef)CFArrayGetValueAtIndex(policies, ix), xpc_policies, error)) { 825 xpc_release(xpc_policies); 826 return NULL; 827 } 828 } 829exit: 830 return xpc_policies; 831} 832 833static SecPolicyRef SecPolicyCreateWithXPCObject(xpc_object_t xpc_policy, CFErrorRef *error) { 834 SecPolicyRef policy = NULL; 835 CFTypeRef oid = NULL; 836 CFTypeRef options = NULL; 837 838 require_action_quiet(xpc_policy, exit, SecError(errSecParam, error, CFSTR("policy xpc value is NULL"))); 839 require_action_quiet(xpc_get_type(xpc_policy) == XPC_TYPE_ARRAY, exit, SecError(errSecDecode, error, CFSTR("policy xpc value is not an array"))); 840 require_action_quiet(xpc_array_get_count(xpc_policy) == 2, exit, SecError(errSecDecode, error, CFSTR("policy xpc array count != 2"))); 841 oid = _CFXPCCreateCFObjectFromXPCObject(xpc_array_get_value(xpc_policy, 0)); 842 require_action_quiet(isString(oid), exit, 843 SecError(errSecParam, error, CFSTR("failed to convert xpc policy[0]=%@ to CFString"), oid)); 844 options = _CFXPCCreateCFObjectFromXPCObject(xpc_array_get_value(xpc_policy, 1)); 845 require_action_quiet(isDictionary(options), exit, 846 SecError(errSecParam, error, CFSTR("failed to convert xpc policy[1]=%@ to CFDictionary"), options)); 847 require_action_quiet(policy = SecPolicyCreate(oid, options), exit, SecError(errSecDecode, error, CFSTR("Failed to create policy"))); 848 849exit: 850 CFReleaseSafe(oid); 851 CFReleaseSafe(options); 852 return policy; 853} 854 855CFArrayRef SecPolicyXPCArrayCopyArray(xpc_object_t xpc_policies, CFErrorRef *error) { 856 CFMutableArrayRef policies = NULL; 857 require_action_quiet(xpc_get_type(xpc_policies) == XPC_TYPE_ARRAY, exit, 858 SecError(errSecParam, error, CFSTR("policies xpc value is not an array"))); 859 size_t count = xpc_array_get_count(xpc_policies); 860 require_action_quiet(policies = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks), exit, 861 SecError(errSecAllocate, error, CFSTR("failed to create CFArray of capacity %zu"), count)); 862 863 size_t ix; 864 for (ix = 0; ix < count; ++ix) { 865 SecPolicyRef policy = SecPolicyCreateWithXPCObject(xpc_array_get_value(xpc_policies, ix), error); 866 if (!policy) { 867 CFRelease(policies); 868 return NULL; 869 } 870 CFArraySetValueAtIndex(policies, ix, policy); 871 CFRelease(policy); 872 } 873 874exit: 875 return policies; 876 877} 878 879static void add_element(CFMutableDictionaryRef options, CFStringRef key, 880 CFTypeRef value) { 881 CFTypeRef old_value = CFDictionaryGetValue(options, key); 882 if (old_value) { 883 CFMutableArrayRef array; 884 if (CFGetTypeID(old_value) == CFArrayGetTypeID()) { 885 array = (CFMutableArrayRef)old_value; 886 } else { 887 array = CFArrayCreateMutable(kCFAllocatorDefault, 0, 888 &kCFTypeArrayCallBacks); 889 CFArrayAppendValue(array, old_value); 890 CFDictionarySetValue(options, key, array); 891 CFRelease(array); 892 } 893 CFArrayAppendValue(array, value); 894 } else { 895 CFDictionaryAddValue(options, key, value); 896 } 897} 898 899static void add_eku(CFMutableDictionaryRef options, const DERItem *ekuOid) { 900 CFDataRef eku = CFDataCreate(kCFAllocatorDefault, 901 ekuOid ? ekuOid->data : NULL, 902 ekuOid ? ekuOid->length : 0); 903 if (eku) { 904 add_element(options, kSecPolicyCheckExtendedKeyUsage, eku); 905 CFRelease(eku); 906 } 907} 908 909static void add_ku(CFMutableDictionaryRef options, SecKeyUsage keyUsage) { 910 SInt32 dku = keyUsage; 911 CFNumberRef ku = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, 912 &dku); 913 if (ku) { 914 add_element(options, kSecPolicyCheckKeyUsage, ku); 915 CFRelease(ku); 916 } 917} 918 919static void add_oid(CFMutableDictionaryRef options, CFStringRef policy_key, const DERItem *oid) { 920 CFDataRef oid_data = CFDataCreate(kCFAllocatorDefault, 921 oid ? oid->data : NULL, 922 oid ? oid->length : 0); 923 if (oid_data) { 924 add_element(options, policy_key, oid_data); 925 CFRelease(oid_data); 926 } 927} 928 929static void add_leaf_marker_value(CFMutableDictionaryRef options, const DERItem *markerOid, CFStringRef string_value) { 930 931 CFTypeRef policyData = NULL; 932 933 if (NULL == string_value) { 934 policyData = CFDataCreate(kCFAllocatorDefault, 935 markerOid ? markerOid->data : NULL, 936 markerOid ? markerOid->length : 0); 937 } else { 938 CFStringRef oid_as_string = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, markerOid); 939 940 const void *key[1] = { oid_as_string }; 941 const void *value[1] = { string_value }; 942 policyData = CFDictionaryCreate(kCFAllocatorDefault, 943 key, value, 1, 944 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 945 CFReleaseNull(oid_as_string); 946 } 947 948 add_element(options, kSecPolicyCheckLeafMarkerOid, policyData); 949 950 CFReleaseNull(policyData); 951 952} 953 954static void add_leaf_marker(CFMutableDictionaryRef options, const DERItem *markerOid) { 955 add_leaf_marker_value(options, markerOid, NULL); 956} 957 958 959static void add_certificate_policy_oid(CFMutableDictionaryRef options, const DERItem *certificatePolicyOid, CFStringRef string_value) { 960 CFTypeRef certificatePolicyData = NULL; 961 962 if (NULL == string_value) { 963 certificatePolicyData = CFDataCreate(kCFAllocatorDefault, 964 certificatePolicyOid ? certificatePolicyOid->data : NULL, 965 certificatePolicyOid ? certificatePolicyOid->length : 0); 966 } else { 967 CFStringRef oid_as_string = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, certificatePolicyOid); 968 969 const void *key[1] = { oid_as_string }; 970 const void *value[1] = { string_value }; 971 certificatePolicyData = CFDictionaryCreate(kCFAllocatorDefault, 972 key, value, 1, 973 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 974 CFReleaseNull(oid_as_string); 975 } 976 977 add_element(options, kSecPolicyCheckCertificatePolicy, certificatePolicyData); 978 979 CFReleaseNull(certificatePolicyData); 980} 981// 982// Routines for adding dictionary entries for policies. 983// 984 985// X.509, but missing validity requirements. 986static void SecPolicyAddBasicCertOptions(CFMutableDictionaryRef options) 987{ 988 //CFDictionaryAddValue(options, kSecPolicyCheckBasicCertificateProcessing, kCFBooleanTrue); 989 CFDictionaryAddValue(options, kSecPolicyCheckCriticalExtensions, kCFBooleanTrue); 990 CFDictionaryAddValue(options, kSecPolicyCheckIdLinkage, kCFBooleanTrue); 991 CFDictionaryAddValue(options, kSecPolicyCheckBasicContraints, kCFBooleanTrue); 992 CFDictionaryAddValue(options, kSecPolicyCheckNonEmptySubject, kCFBooleanTrue); 993 CFDictionaryAddValue(options, kSecPolicyCheckQualifiedCertStatements, kCFBooleanTrue); 994} 995 996static void SecPolicyAddBasicX509Options(CFMutableDictionaryRef options) 997{ 998 SecPolicyAddBasicCertOptions(options); 999 CFDictionaryAddValue(options, kSecPolicyCheckValidIntermediates, kCFBooleanTrue); 1000 CFDictionaryAddValue(options, kSecPolicyCheckValidLeaf, kCFBooleanTrue); 1001 CFDictionaryAddValue(options, kSecPolicyCheckValidRoot, kCFBooleanTrue); 1002 1003 // Make sure that black and gray leaf checks are performed for basic X509 chain building 1004 CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf, kCFBooleanTrue); 1005 CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, kCFBooleanTrue); 1006} 1007 1008static bool SecPolicyAddChainLengthOptions(CFMutableDictionaryRef options, CFIndex length) 1009{ 1010 bool result = false; 1011 CFNumberRef lengthAsCF = NULL; 1012 1013 require(lengthAsCF = CFNumberCreate(kCFAllocatorDefault, 1014 kCFNumberCFIndexType, &length), errOut); 1015 CFDictionaryAddValue(options, kSecPolicyCheckChainLength, lengthAsCF); 1016 1017 result = true; 1018 1019errOut: 1020 CFReleaseSafe(lengthAsCF); 1021 return result; 1022} 1023 1024static bool SecPolicyAddAnchorSHA1Options(CFMutableDictionaryRef options, 1025 const UInt8 anchorSha1[kSecPolicySHA1Size]) 1026{ 1027 bool success = false; 1028 CFDataRef anchorData = NULL; 1029 1030 require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha1, kSecPolicySHA1Size), errOut); 1031 add_element(options, kSecPolicyCheckAnchorSHA1, anchorData); 1032 1033 success = true; 1034 1035errOut: 1036 CFReleaseSafe(anchorData); 1037 return success; 1038} 1039 1040static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef options) 1041{ 1042 return SecPolicyAddAnchorSHA1Options(options, kAppleCASHA1); 1043} 1044 1045#if 0 1046static bool SecPolicyAddAppleTESTAnchorOptions(CFMutableDictionaryRef options) 1047{ 1048 return SecPolicyAddAnchorSHA1Options(options, kAppleTESTCASHA1); 1049} 1050#endif 1051 1052// 1053// Policy Creation Functions 1054// 1055SecPolicyRef SecPolicyCreateBasicX509(void) { 1056 CFMutableDictionaryRef options = NULL; 1057 SecPolicyRef result = NULL; 1058 1059 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1060 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1061 1062 SecPolicyAddBasicX509Options(options); 1063 CFDictionaryAddValue(options, kSecPolicyCheckNoNetworkAccess, 1064 kCFBooleanTrue); 1065 1066 require(result = SecPolicyCreate(kSecPolicyOIDBasicX509, options), errOut); 1067 1068errOut: 1069 CFReleaseSafe(options); 1070 return result; 1071} 1072 1073SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) { 1074 CFMutableDictionaryRef options = NULL; 1075 SecPolicyRef result = NULL; 1076 1077 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1078 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1079 1080 SecPolicyAddBasicX509Options(options); 1081 1082#if 0 1083 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage, 1084 kCFBooleanTrue); 1085#endif 1086 1087 if (hostname) { 1088 CFDictionaryAddValue(options, kSecPolicyCheckSSLHostname, hostname); 1089 } 1090 1091 CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf, kCFBooleanTrue); 1092 CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, kCFBooleanTrue); 1093 1094 /* If server and EKU ext present then EKU ext should contain one of 1095 CSSMOID_ServerAuth or CSSMOID_ExtendedKeyUsageAny or 1096 CSSMOID_NetscapeSGC or CSSMOID_MicrosoftSGC. 1097 else if !server and EKU ext present then EKU ext should contain one of 1098 CSSMOID_ClientAuth or CSSMOID_ExtendedKeyUsageAny. */ 1099 1100 /* We always allow certification that specify oidAnyExtendedKeyUsage. */ 1101 add_eku(options, NULL); /* eku extension is optional */ 1102 add_eku(options, &oidAnyExtendedKeyUsage); 1103 if (server) { 1104 add_eku(options, &oidExtendedKeyUsageServerAuth); 1105 add_eku(options, &oidExtendedKeyUsageMicrosoftSGC); 1106 add_eku(options, &oidExtendedKeyUsageNetscapeSGC); 1107 } else { 1108 add_eku(options, &oidExtendedKeyUsageClientAuth); 1109 } 1110 1111 require(result = SecPolicyCreate( 1112 server ? kSecPolicyOIDSSLServer : kSecPolicyOIDSSLClient, 1113 options), errOut); 1114 1115errOut: 1116 CFReleaseSafe(options); 1117 return result; 1118} 1119 1120SecPolicyRef SecPolicyCreateiPhoneActivation(void) { 1121 CFMutableDictionaryRef options = NULL; 1122 SecPolicyRef result = NULL; 1123 1124 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1125 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1126 1127 SecPolicyAddBasicCertOptions(options); 1128 1129#if 0 1130 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage, 1131 kCFBooleanTrue); 1132 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage, 1133 kCFBooleanTrue); 1134#endif 1135 1136 /* Basic X.509 policy with the additional requirements that the chain 1137 length is 3, it's anchored at the AppleCA and the leaf certificate 1138 has issuer "Apple iPhone Certification Authority" and 1139 subject "Apple iPhone Activation" for the common name. */ 1140 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, 1141 CFSTR("Apple iPhone Certification Authority")); 1142 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName, 1143 CFSTR("Apple iPhone Activation")); 1144 1145 require(SecPolicyAddChainLengthOptions(options, 3), errOut); 1146 require(SecPolicyAddAppleAnchorOptions(options), errOut); 1147 1148 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneActivation, options), 1149 errOut); 1150 1151errOut: 1152 CFReleaseSafe(options); 1153 return result; 1154} 1155 1156SecPolicyRef SecPolicyCreateiPhoneDeviceCertificate(void) { 1157 CFMutableDictionaryRef options = NULL; 1158 SecPolicyRef result = NULL; 1159 1160 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1161 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1162 1163 SecPolicyAddBasicCertOptions(options); 1164 1165#if 0 1166 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage, 1167 kCFBooleanTrue); 1168 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage, 1169 kCFBooleanTrue); 1170#endif 1171 1172 /* Basic X.509 policy with the additional requirements that the chain 1173 length is 4, it's anchored at the AppleCA and the first intermediate 1174 has the subject "Apple iPhone Device CA". */ 1175 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, 1176 CFSTR("Apple iPhone Device CA")); 1177 1178 require(SecPolicyAddChainLengthOptions(options, 4), errOut); 1179 require(SecPolicyAddAppleAnchorOptions(options), errOut); 1180 1181 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneDeviceCertificate, options), 1182 errOut); 1183 1184errOut: 1185 CFReleaseSafe(options); 1186 return result; 1187} 1188 1189SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void) { 1190 CFMutableDictionaryRef options = NULL; 1191 SecPolicyRef result = NULL; 1192 1193 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1194 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1195 1196 SecPolicyAddBasicCertOptions(options); 1197 1198#if 0 1199 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage, 1200 kCFBooleanTrue); 1201 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage, 1202 kCFBooleanTrue); 1203#endif 1204 1205 /* Basic X.509 policy with the additional requirements that the chain 1206 is anchored at the factory device certificate issuer. */ 1207 require(SecPolicyAddAnchorSHA1Options(options, kFactoryDeviceCASHA1), errOut); 1208 1209 require(result = SecPolicyCreate(kSecPolicyOIDFactoryDeviceCertificate, options), 1210 errOut); 1211 1212errOut: 1213 CFReleaseSafe(options); 1214 return result; 1215} 1216 1217SecPolicyRef SecPolicyCreateiAP(void) { 1218 CFMutableDictionaryRef options = NULL; 1219 SecPolicyRef result = NULL; 1220 CFTimeZoneRef tz = NULL; 1221 CFDateRef date = NULL; 1222 1223 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1224 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1225 1226 SecPolicyAddBasicCertOptions(options); 1227 1228 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNamePrefix, 1229 CFSTR("IPA_")); 1230 1231 date = CFDateCreateForGregorianZuluDay(NULL, 2006, 5, 31); 1232 CFDictionaryAddValue(options, kSecPolicyCheckNotValidBefore, date); 1233 1234 require(result = SecPolicyCreate(kSecPolicyOIDiAP, options), 1235 errOut); 1236 1237errOut: 1238 CFReleaseSafe(date); 1239 CFReleaseSafe(tz); 1240 CFReleaseSafe(options); 1241 return result; 1242} 1243 1244SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void) { 1245 CFMutableDictionaryRef options = NULL; 1246 SecPolicyRef result = NULL; 1247 1248 1249 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1250 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1251 1252 SecPolicyAddBasicCertOptions(options); 1253 1254 CFDictionaryAddValue(options, kSecPolicyCheckSubjectOrganization, 1255 CFSTR("Apple Inc.")); 1256 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName, 1257 CFSTR("iTunes Store URL Bag")); 1258 1259 require(SecPolicyAddChainLengthOptions(options, 2), errOut); 1260 require(SecPolicyAddAnchorSHA1Options(options, kITMSCASHA1), errOut); 1261 1262 require(result = SecPolicyCreate(kSecPolicyOIDiTunesStoreURLBag, options), errOut); 1263 1264errOut: 1265 CFReleaseSafe(options); 1266 return result; 1267} 1268 1269SecPolicyRef SecPolicyCreateEAP(Boolean server, CFArrayRef trustedServerNames) { 1270 CFMutableDictionaryRef options = NULL; 1271 SecPolicyRef result = NULL; 1272 1273 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1274 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1275 1276 SecPolicyAddBasicX509Options(options); 1277 1278#if 0 1279 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage, 1280 kCFBooleanTrue); 1281 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage, 1282 kCFBooleanTrue); 1283#endif 1284 1285 /* Since EAP is used to setup the network we don't want evaluation 1286 using this policy to access the network. */ 1287 CFDictionaryAddValue(options, kSecPolicyCheckNoNetworkAccess, 1288 kCFBooleanTrue); 1289 if (trustedServerNames) { 1290 CFDictionaryAddValue(options, kSecPolicyCheckEAPTrustedServerNames, trustedServerNames); 1291 } 1292 1293 require(result = SecPolicyCreate( 1294 server ? kSecPolicyEAPServer : kSecPolicyEAPClient, 1295 options), errOut); 1296 1297errOut: 1298 CFReleaseSafe(options); 1299 return result; 1300} 1301 1302SecPolicyRef SecPolicyCreateIPSec(Boolean server, CFStringRef hostname) { 1303 CFMutableDictionaryRef options = NULL; 1304 SecPolicyRef result = NULL; 1305 1306 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1307 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1308 1309 SecPolicyAddBasicX509Options(options); 1310 1311 if (hostname) { 1312 CFDictionaryAddValue(options, kSecPolicyCheckSSLHostname, hostname); 1313 } 1314 1315 /* Require oidExtendedKeyUsageIPSec if Extended Keyusage Extention is 1316 present. */ 1317 /* Per <rdar://problem/6843827> Cisco VPN Certificate compatibility issue. 1318 We don't check the EKU for IPSec certs for now. If we do add eku 1319 checking back in the future, we should probably also accept the 1320 following EKUs: 1321 ipsecEndSystem 1.3.6.1.5.5.7.3.5 1322 and possibly even 1323 ipsecTunnel 1.3.6.1.5.5.7.3.6 1324 ipsecUser 1.3.6.1.5.5.7.3.7 1325 */ 1326 //add_eku(options, NULL); /* eku extension is optional */ 1327 //add_eku(options, &oidAnyExtendedKeyUsage); 1328 //add_eku(options, &oidExtendedKeyUsageIPSec); 1329 1330 require(result = SecPolicyCreate( 1331 server ? kSecPolicyOIDIPSecServer : kSecPolicyOIDIPSecClient, 1332 options), errOut); 1333 1334errOut: 1335 CFReleaseSafe(options); 1336 return result; 1337} 1338 1339SecPolicyRef SecPolicyCreateiPhoneApplicationSigning(void) { 1340 CFMutableDictionaryRef options = NULL; 1341 SecPolicyRef result = NULL; 1342 1343 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1344 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1345 1346 SecPolicyAddBasicCertOptions(options); 1347 1348 /* Basic X.509 policy with the additional requirements that the chain 1349 length is 3, it's anchored at the AppleCA and the leaf certificate 1350 has issuer "Apple iPhone Certification Authority" and 1351 subject "Apple iPhone OS Application Signing" for the common name. */ 1352 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, 1353 CFSTR("Apple iPhone Certification Authority")); 1354 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNameTEST, 1355 CFSTR("Apple iPhone OS Application Signing")); 1356 1357 require(SecPolicyAddChainLengthOptions(options, 3), errOut); 1358 require(SecPolicyAddAppleAnchorOptions(options), errOut); 1359 1360 add_eku(options, NULL); /* eku extension is optional */ 1361 add_eku(options, &oidAnyExtendedKeyUsage); 1362 add_eku(options, &oidExtendedKeyUsageCodeSigning); 1363 1364 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneApplicationSigning, options), 1365 errOut); 1366 1367 /* 1.2.840.113635.100.6.1.3, non-critical: DER:05:00 - application signing */ 1368 1369errOut: 1370 CFReleaseSafe(options); 1371 return result; 1372} 1373 1374SecPolicyRef SecPolicyCreateiPhoneProfileApplicationSigning(void) { 1375 CFMutableDictionaryRef options = NULL; 1376 SecPolicyRef result = NULL; 1377 1378 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1379 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1380 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); 1381 CFDictionaryAddValue(options, kSecPolicyCheckValidLeaf, kCFBooleanFalse); 1382 1383 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneProfileApplicationSigning, 1384 options), errOut); 1385 1386errOut: 1387 CFReleaseSafe(options); 1388 return result; 1389} 1390 1391SecPolicyRef SecPolicyCreateiPhoneProvisioningProfileSigning(void) { 1392 CFMutableDictionaryRef options = NULL; 1393 SecPolicyRef result = NULL; 1394 1395 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1396 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1397 1398 SecPolicyAddBasicCertOptions(options); 1399 1400 /* Basic X.509 policy with the additional requirements that the chain 1401 length is 3, it's anchored at the AppleCA and the leaf certificate 1402 has issuer "Apple iPhone Certification Authority" and 1403 subject "Apple iPhone OS Provisioning Profile Signing" for the common name. */ 1404 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, 1405 CFSTR("Apple iPhone Certification Authority")); 1406 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNameTEST, 1407 CFSTR("Apple iPhone OS Provisioning Profile Signing")); 1408 1409 require(SecPolicyAddChainLengthOptions(options, 3), errOut); 1410 require(SecPolicyAddAppleAnchorOptions(options), errOut); 1411 1412 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneProvisioningProfileSigning, options), 1413 errOut); 1414 1415 /* 1.2.840.113635.100.6.2.2.1, non-critical: DER:05:00 - provisioning profile */ 1416 1417errOut: 1418 CFReleaseSafe(options); 1419 return result; 1420} 1421 1422SecPolicyRef SecPolicyCreateOCSPSigner(void) { 1423 CFMutableDictionaryRef options = NULL; 1424 SecPolicyRef result = NULL; 1425 1426 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1427 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1428 1429 SecPolicyAddBasicX509Options(options); 1430 1431 /* Require id-kp-OCSPSigning extendedKeyUsage to be present, not optional. */ 1432 add_eku(options, &oidExtendedKeyUsageOCSPSigning); 1433 1434 require(result = SecPolicyCreate(kSecPolicyOIDOCSPSigner, options), errOut); 1435 1436errOut: 1437 CFReleaseSafe(options); 1438 return result; 1439} 1440 1441SecPolicyRef SecPolicyCreateRevocation(CFOptionFlags revocationFlags) { 1442 CFMutableDictionaryRef options = NULL; 1443 SecPolicyRef result = NULL; 1444 1445 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1446 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1447 1448 /* false = ocsp, true = crl, string/url value = crl distribution point, 1449 array = list of multiple values for example false, true, url1, url2 1450 check ocsp, crl, and url1 and url2 for certs which have no extensions. 1451 */ 1452 if (revocationFlags & kSecRevocationOCSPMethod) { 1453 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); 1454 } 1455 else if (revocationFlags & kSecRevocationCRLMethod) { 1456 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanTrue); 1457 } 1458 // 1459 //FIXME: check additional revocation flags 1460 // 1461 1462 /* Only flag bits 0-4 are currently defined */ 1463 require(((revocationFlags >> 5) == 0), errOut); 1464 1465 require(result = SecPolicyCreate(kSecPolicyOIDRevocation, options), errOut); 1466 1467errOut: 1468 CFReleaseSafe(options); 1469 return result; 1470} 1471 1472SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email) { 1473 CFMutableDictionaryRef options = NULL; 1474 SecPolicyRef result = NULL; 1475 1476 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1477 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1478 1479 SecPolicyAddBasicX509Options(options); 1480 1481 /* We call add_ku for each combination of bits we are willing to allow. */ 1482 if (smimeUsage & kSecSignSMIMEUsage) { 1483 add_ku(options, kSecKeyUsageUnspecified); 1484 add_ku(options, kSecKeyUsageDigitalSignature); 1485 add_ku(options, kSecKeyUsageNonRepudiation); 1486 } 1487 if (smimeUsage & kSecKeyEncryptSMIMEUsage) { 1488 add_ku(options, kSecKeyUsageKeyEncipherment); 1489 } 1490 if (smimeUsage & kSecDataEncryptSMIMEUsage) { 1491 add_ku(options, kSecKeyUsageDataEncipherment); 1492 } 1493 if (smimeUsage & kSecKeyExchangeDecryptSMIMEUsage) { 1494 add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageDecipherOnly); 1495 } 1496 if (smimeUsage & kSecKeyExchangeEncryptSMIMEUsage) { 1497 add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly); 1498 } 1499 if (smimeUsage & kSecKeyExchangeBothSMIMEUsage) { 1500 add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly | kSecKeyUsageDecipherOnly); 1501 } 1502 1503 if (email) { 1504 CFDictionaryAddValue(options, kSecPolicyCheckEmail, email); 1505 } 1506 1507 /* RFC 3850 paragraph 4.4.4 1508 1509 If the extended key usage extension is present in the certificate 1510 then interpersonal message S/MIME receiving agents MUST check that it 1511 contains either the emailProtection or the anyExtendedKeyUsage OID as 1512 defined in [KEYM]. S/MIME uses other than interpersonal messaging 1513 MAY require the explicit presence of the extended key usage extension 1514 or other OIDs to be present in the extension or both. 1515 */ 1516 add_eku(options, NULL); /* eku extension is optional */ 1517 add_eku(options, &oidAnyExtendedKeyUsage); 1518 add_eku(options, &oidExtendedKeyUsageEmailProtection); 1519 1520 require(result = SecPolicyCreate(kSecPolicyOIDSMIME, options), errOut); 1521 1522errOut: 1523 CFReleaseSafe(options); 1524 return result; 1525} 1526 1527SecPolicyRef SecPolicyCreateCodeSigning(void) { 1528 CFMutableDictionaryRef options = NULL; 1529 SecPolicyRef result = NULL; 1530 1531 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1532 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1533 1534 SecPolicyAddBasicX509Options(options); 1535 1536 /* If the key usage extension is present we accept it having either of 1537 these values. */ 1538 add_ku(options, kSecKeyUsageDigitalSignature); 1539 add_ku(options, kSecKeyUsageNonRepudiation); 1540 1541 /* We require a extended key usage extension and we accept any or 1542 codesigning ekus. */ 1543 /* TODO: Do we want to accept the apple codesigning oid as well or is 1544 that a separate policy? */ 1545 add_eku(options, &oidAnyExtendedKeyUsage); 1546 add_eku(options, &oidExtendedKeyUsageCodeSigning); 1547 1548 require(result = SecPolicyCreate(kSecPolicyOIDCodeSigning, options), 1549 errOut); 1550 1551errOut: 1552 CFReleaseSafe(options); 1553 return result; 1554} 1555 1556/* Explicitly leave out empty subject/subjectaltname check */ 1557SecPolicyRef SecPolicyCreateLockdownPairing(void) { 1558 CFMutableDictionaryRef options = NULL; 1559 SecPolicyRef result = NULL; 1560 1561 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1562 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1563 //CFDictionaryAddValue(options, kSecPolicyCheckBasicCertificateProcessing, 1564 // kCFBooleanTrue); 1565 CFDictionaryAddValue(options, kSecPolicyCheckCriticalExtensions, 1566 kCFBooleanTrue); 1567 CFDictionaryAddValue(options, kSecPolicyCheckIdLinkage, 1568 kCFBooleanTrue); 1569 CFDictionaryAddValue(options, kSecPolicyCheckBasicContraints, 1570 kCFBooleanTrue); 1571 CFDictionaryAddValue(options, kSecPolicyCheckQualifiedCertStatements, 1572 kCFBooleanTrue); 1573 1574 require(result = SecPolicyCreate(kSecPolicyOIDLockdownPairing, options), errOut); 1575 1576errOut: 1577 CFReleaseSafe(options); 1578 return result; 1579} 1580 1581SecPolicyRef SecPolicyCreateURLBag(void) { 1582 CFMutableDictionaryRef options = NULL; 1583 SecPolicyRef result = NULL; 1584 1585 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1586 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1587 1588 SecPolicyAddBasicCertOptions(options); 1589 1590 add_eku(options, &oidExtendedKeyUsageCodeSigning); 1591 1592 require(result = SecPolicyCreate(kSecPolicyOIDURLBag, options), errOut); 1593 1594errOut: 1595 CFReleaseSafe(options); 1596 return result; 1597} 1598 1599static bool SecPolicyAddAppleCertificationAuthorityOptions(CFMutableDictionaryRef options, bool honorValidity) 1600{ 1601 bool success = false; 1602 1603 if (honorValidity) 1604 SecPolicyAddBasicX509Options(options); 1605 else 1606 SecPolicyAddBasicCertOptions(options); 1607 1608#if 0 1609 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage, 1610 kCFBooleanTrue); 1611 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage, 1612 kCFBooleanTrue); 1613#endif 1614 1615 /* Basic X.509 policy with the additional requirements that the chain 1616 length is 3, it's anchored at the AppleCA and the leaf certificate 1617 has issuer "Apple iPhone Certification Authority". */ 1618 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, 1619 CFSTR("Apple iPhone Certification Authority")); 1620 1621 require(SecPolicyAddChainLengthOptions(options, 3), errOut); 1622 require(SecPolicyAddAppleAnchorOptions(options), errOut); 1623 1624 success = true; 1625 1626errOut: 1627 return success; 1628} 1629 1630static SecPolicyRef SecPolicyCreateAppleCertificationAuthorityPolicy(CFStringRef policyOID, CFStringRef leafName, bool honorValidity) 1631{ 1632 CFMutableDictionaryRef options = NULL; 1633 SecPolicyRef result = NULL; 1634 1635 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1636 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); 1637 1638 require(SecPolicyAddAppleCertificationAuthorityOptions(options, honorValidity), errOut); 1639 1640 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName, leafName); 1641 1642 require(result = SecPolicyCreate(policyOID, options), 1643 errOut); 1644 1645errOut: 1646 CFReleaseSafe(options); 1647 return result; 1648} 1649 1650 1651SecPolicyRef SecPolicyCreateOTATasking(void) 1652{ 1653 return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDOTATasking, CFSTR("OTA Task Signing"), true); 1654} 1655 1656SecPolicyRef SecPolicyCreateMobileAsset(void) 1657{ 1658 return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDMobileAsset, CFSTR("Asset Manifest Signing"), false); 1659} 1660 1661SecPolicyRef SecPolicyCreateAppleIDAuthorityPolicy(void) 1662{ 1663 SecPolicyRef result = NULL; 1664 CFMutableDictionaryRef options = NULL; 1665 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1666 &kCFTypeDictionaryKeyCallBacks, 1667 &kCFTypeDictionaryValueCallBacks), out); 1668 1669 //Leaf appears to be a SSL only cert, so policy should expand on that policy 1670 SecPolicyAddBasicX509Options(options); 1671 1672 // Apple CA anchored 1673 require(SecPolicyAddAppleAnchorOptions(options), out); 1674 1675 // with the addition of the existence check of an extension with "Apple ID Sharing Certificate" oid (1.2.840.113635.100.4.7) 1676 // NOTE: this obviously intended to have gone into Extended Key Usage, but evidence of existing certs proves the contrary. 1677 add_leaf_marker(options, &oidAppleExtendedKeyUsageAppleID); 1678 1679 // and validate that intermediate has extension with CSSMOID_APPLE_EXTENSION_AAI_INTERMEDIATE oid (1.2.840.113635.100.6.2.3) and goes back to the Apple Root CA. 1680 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID); 1681 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID2); 1682 1683 require(result = SecPolicyCreate(kSecPolicyOIDAppleIDAuthority, options), out); 1684 1685out: 1686 CFReleaseSafe(options); 1687 return result; 1688} 1689 1690static SecPolicyRef _SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, CFStringRef teamIdentifier, bool requireTeamID) 1691{ 1692 SecPolicyRef result = NULL; 1693 CFMutableDictionaryRef options = NULL; 1694 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1695 &kCFTypeDictionaryKeyCallBacks, 1696 &kCFTypeDictionaryValueCallBacks), out); 1697 1698 SecPolicyAddBasicX509Options(options); 1699 SecPolicyAddAppleAnchorOptions(options); 1700 1701 if (teamIdentifier) { 1702 // If supplied, teamIdentifier must match subject OU field 1703 CFDictionaryAddValue(options, kSecPolicyCheckSubjectOrganizationalUnit, teamIdentifier); 1704 } 1705 else { 1706 // If not supplied, and it was required, fail 1707 require(!requireTeamID, out); 1708 } 1709 1710 // Must be both push and 3rd party package signing 1711 add_leaf_marker_value(options, &oidAppleInstallerPackagingSigningExternal, cardIssuer); 1712 1713 // We should check that it also has push marker, but we don't support requiring both, only either. 1714 // add_independent_oid(options, kSecPolicyCheckLeafMarkerOid, &oidApplePushServiceClient); 1715 1716 // And Shoebox signing eku 1717 add_eku(options, &oidAppleExtendedKeyUsageShoebox); 1718 1719 require(result = SecPolicyCreate(kSecPolicyOIDApplePassbook, options), out); 1720 1721out: 1722 CFReleaseSafe(options); 1723 return result; 1724} 1725 1726SecPolicyRef SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, CFStringRef teamIdentifier) 1727{ 1728 return _SecPolicyCreatePassbookCardSigner(cardIssuer, teamIdentifier, true); 1729} 1730 1731 1732SecPolicyRef SecPolicyCreateShoeboxCardSigner(CFStringRef cardIssuer) 1733{ 1734 return _SecPolicyCreatePassbookCardSigner(cardIssuer, nil, false); 1735} 1736 1737static SecPolicyRef CreateMobileStoreSigner(Boolean forTest) 1738{ 1739 1740 SecPolicyRef result = NULL; 1741 CFMutableDictionaryRef options = NULL; 1742 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1743 &kCFTypeDictionaryKeyCallBacks, 1744 &kCFTypeDictionaryValueCallBacks), errOut); 1745 SecPolicyAddBasicX509Options(options); 1746 SecPolicyAddAppleAnchorOptions(options); 1747 1748 require(SecPolicyAddChainLengthOptions(options, 3), errOut); 1749 1750 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, 1751 CFSTR("Apple System Integration 2 Certification Authority")); 1752 1753 add_ku(options, kSecKeyUsageDigitalSignature); 1754 1755 const DERItem* pOID = (forTest) ? &oidApplePolicyTestMobileStore : &oidApplePolicyMobileStore; 1756 1757 add_certificate_policy_oid(options, pOID, NULL); 1758 1759 require(result = SecPolicyCreate(kSecPolicyOIDAppleMobileStore, options), errOut); 1760 1761errOut: 1762 CFReleaseSafe(options); 1763 return result; 1764} 1765 1766SecPolicyRef SecPolicyCreateMobileStoreSigner(void) 1767{ 1768 1769 return CreateMobileStoreSigner(false); 1770} 1771 1772SecPolicyRef SecPolicyCreateTestMobileStoreSigner(void) 1773{ 1774 1775 return CreateMobileStoreSigner(true); 1776} 1777 1778 1779CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateEscrowServiceSigner(void) 1780{ 1781 SecPolicyRef result = NULL; 1782 CFMutableDictionaryRef options = NULL; 1783 CFArrayRef anArray = NULL; 1784 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1785 &kCFTypeDictionaryKeyCallBacks, 1786 &kCFTypeDictionaryValueCallBacks), errOut); 1787 1788 SecPolicyAddBasicX509Options(options); 1789 1790 1791 add_ku(options, kSecKeyUsageKeyEncipherment); 1792 1793 //add_leaf_marker(options, &oidApplePolicyEscrowService); 1794 require(SecPolicyAddChainLengthOptions(options, 2), errOut); 1795 1796 1797 Boolean anchorAdded = false; 1798 // Get the roots by calling the SecCertificateCopyEscrowRoots 1799 anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot); 1800 CFIndex numRoots = 0; 1801 if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray))) 1802 { 1803 goto errOut; 1804 } 1805 1806 for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++) 1807 { 1808 SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt); 1809 1810 if (NULL != aCert) 1811 { 1812 CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert); 1813 if (NULL != sha_data) 1814 { 1815 const UInt8* pSHAData = CFDataGetBytePtr(sha_data); 1816 if (NULL != pSHAData) 1817 { 1818 SecPolicyAddAnchorSHA1Options(options, pSHAData); 1819 anchorAdded = true; 1820 } 1821 } 1822 } 1823 } 1824 CFReleaseNull(anArray); 1825 1826 if (!anchorAdded) 1827 { 1828 goto errOut; 1829 } 1830 1831 1832 require(result = SecPolicyCreate(kSecPolicyOIDAppleEscrowService, options), errOut); 1833 1834errOut: 1835 CFReleaseSafe(anArray); 1836 CFReleaseSafe(options); 1837 return result; 1838} 1839 1840CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreatePCSEscrowServiceSigner(void) 1841{ 1842 SecPolicyRef result = NULL; 1843 CFMutableDictionaryRef options = NULL; 1844 CFArrayRef anArray = NULL; 1845 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1846 &kCFTypeDictionaryKeyCallBacks, 1847 &kCFTypeDictionaryValueCallBacks), errOut); 1848 1849 SecPolicyAddBasicX509Options(options); 1850 1851 1852 add_ku(options, kSecKeyUsageKeyEncipherment); 1853 1854 //add_leaf_marker(options, &oidApplePolicyEscrowService); 1855 require(SecPolicyAddChainLengthOptions(options, 2), errOut); 1856 1857 1858 Boolean anchorAdded = false; 1859 anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot); 1860 CFIndex numRoots = 0; 1861 if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray))) 1862 { 1863 goto errOut; 1864 } 1865 1866 for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++) 1867 { 1868 SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt); 1869 1870 if (NULL != aCert) 1871 { 1872 CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert); 1873 if (NULL != sha_data) 1874 { 1875 const UInt8* pSHAData = CFDataGetBytePtr(sha_data); 1876 if (NULL != pSHAData) 1877 { 1878 SecPolicyAddAnchorSHA1Options(options, pSHAData); 1879 anchorAdded = true; 1880 } 1881 } 1882 } 1883 } 1884 CFReleaseNull(anArray); 1885 1886 if (!anchorAdded) 1887 { 1888 goto errOut; 1889 } 1890 1891 1892 require(result = SecPolicyCreate(kSecPolicyOIDApplePCSEscrowService, options), errOut); 1893 1894errOut: 1895 CFReleaseSafe(anArray); 1896 CFReleaseSafe(options); 1897 return result; 1898} 1899SecCertificateRef SecPolicyCopyEscrowRootCertificate(void) 1900{ 1901 SecCertificateRef result = NULL; 1902 1903 return result; 1904} 1905 1906SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void) 1907{ 1908 SecPolicyRef result = NULL; 1909 CFMutableDictionaryRef options = NULL; 1910 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1911 &kCFTypeDictionaryKeyCallBacks, 1912 &kCFTypeDictionaryValueCallBacks), errOut); 1913 1914 SecPolicyAddBasicX509Options(options); 1915 SecPolicyAddAppleAnchorOptions(options); 1916 1917 // Require the profile signing EKU 1918 add_eku(options, &oidAppleExtendedKeyUsageProfileSigning); 1919 1920 require(result = SecPolicyCreate(kSecPolicyOIDAppleProfileSigner, options), errOut); 1921 1922errOut: 1923 CFReleaseSafe(options); 1924 return result; 1925} 1926 1927 1928SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void) 1929{ 1930 SecPolicyRef result = NULL; 1931 CFMutableDictionaryRef options = NULL; 1932 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1933 &kCFTypeDictionaryKeyCallBacks, 1934 &kCFTypeDictionaryValueCallBacks), errOut); 1935 1936 SecPolicyAddBasicX509Options(options); 1937 SecPolicyAddAppleAnchorOptions(options); 1938 1939 // Require the QA profile signing EKU 1940 add_eku(options, &oidAppleExtendedKeyUsageQAProfileSigning); 1941 1942 require(result = SecPolicyCreate(kSecPolicyOIDAppleQAProfileSigner, options), errOut); 1943 1944errOut: 1945 CFReleaseSafe(options); 1946 return result; 1947} 1948 1949#if TARGET_OS_IPHONE 1950SecPolicyRef SecPolicyCreateOTAPKISigner(void) 1951{ 1952 SecPolicyRef result = NULL; 1953 CFMutableDictionaryRef options = NULL; 1954 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1955 &kCFTypeDictionaryKeyCallBacks, 1956 &kCFTypeDictionaryValueCallBacks), errOut); 1957 SecPolicyAddBasicX509Options(options); 1958 1959 SecPolicyAddAnchorSHA1Options(options, kApplePKISettingsAuthority); 1960 require(SecPolicyAddChainLengthOptions(options, 2), errOut); 1961 1962 require(result = SecPolicyCreate(kSecPolicyOIDAppleOTAPKIAssetSigner, options), errOut); 1963 1964errOut: 1965 CFReleaseSafe(options); 1966 return result; 1967 1968} 1969 1970 1971SecPolicyRef SecPolicyCreateTestOTAPKISigner(void) 1972{ 1973 SecPolicyRef result = NULL; 1974 CFMutableDictionaryRef options = NULL; 1975 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1976 &kCFTypeDictionaryKeyCallBacks, 1977 &kCFTypeDictionaryValueCallBacks), errOut); 1978 SecPolicyAddBasicX509Options(options); 1979 1980 SecPolicyAddAnchorSHA1Options(options, kAppleTestPKISettingsAuthority); 1981 require(SecPolicyAddChainLengthOptions(options, 2), errOut); 1982 1983 require(result = SecPolicyCreate(kSecPolicyOIDAppleTestOTAPKIAssetSigner, options), errOut); 1984 1985errOut: 1986 CFReleaseSafe(options); 1987 return result; 1988} 1989 1990/*! 1991 @function SecPolicyCreateAppleSMPEncryption 1992 @abstract Check for intermediate certificate 'Apple System Integration CA - G3' by name, 1993 and root certificate 'Apple Root CA - G3' by hash. 1994 Leaf cert must have Key Encipherment usage. 1995 Leaf cert must have Apple SMP Encryption marker OID (1.2.840.113635.100.6.30). 1996 Intermediate must have marker OID (1.2.840.113635.100.6.2.13). 1997 */ 1998SecPolicyRef SecPolicyCreateAppleSMPEncryption(void) 1999{ 2000 SecPolicyRef result = NULL; 2001 CFMutableDictionaryRef options = NULL; 2002 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 2003 &kCFTypeDictionaryKeyCallBacks, 2004 &kCFTypeDictionaryValueCallBacks), errOut); 2005 SecPolicyAddBasicCertOptions(options); 2006 2007 SecPolicyAddAnchorSHA1Options(options, kAppleRootCA_ECC_SHA1); 2008 require(SecPolicyAddChainLengthOptions(options, 3), errOut); 2009 2010 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, 2011 CFSTR("Apple System Integration CA - G3")); 2012 2013 // Check that leaf has extension with "Apple SMP Encryption" oid (1.2.840.113635.100.6.30) 2014 add_leaf_marker(options, &oidAppleCertExtAppleSMPEncryption); 2015 2016 // Check that intermediate has extension (1.2.840.113635.100.6.2.13) 2017 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntgG3); 2018 2019 add_ku(options, kSecKeyUsageKeyEncipherment); 2020 2021 // Ensure that revocation is checked (OCSP) 2022 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); 2023 2024 require(result = SecPolicyCreate(kSecPolicyAppleSMPEncryption, options), errOut); 2025 2026errOut: 2027 CFReleaseSafe(options); 2028 return result; 2029} 2030 2031/*! 2032 @function SecPolicyCreateTestAppleSMPEncryption 2033 @abstract Check for intermediate certificate 'Test Apple System Integration CA - ECC' by name, 2034 and root certificate 'Test Apple Root CA - ECC' by hash. 2035 Leaf cert must have Key Encipherment usage. Other checks TBD. 2036 */ 2037SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void) 2038{ 2039 SecPolicyRef result = NULL; 2040 CFMutableDictionaryRef options = NULL; 2041 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 2042 &kCFTypeDictionaryKeyCallBacks, 2043 &kCFTypeDictionaryValueCallBacks), errOut); 2044 SecPolicyAddBasicCertOptions(options); 2045 2046 SecPolicyAddAnchorSHA1Options(options, kTestAppleRootCA_ECC_SHA1); 2047 require(SecPolicyAddChainLengthOptions(options, 3), errOut); 2048 2049 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, 2050 CFSTR("Test Apple System Integration CA - ECC")); 2051 2052 add_ku(options, kSecKeyUsageKeyEncipherment); 2053 2054 // Ensure that revocation is checked (OCSP) 2055 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); 2056 2057 require(result = SecPolicyCreate(kSecPolicyAppleTestSMPEncryption, options), errOut); 2058 2059errOut: 2060 CFReleaseSafe(options); 2061 return result; 2062} 2063 2064 2065SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void) 2066{ 2067 SecPolicyRef result = NULL; 2068 CFMutableDictionaryRef options = NULL; 2069 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 2070 &kCFTypeDictionaryKeyCallBacks, 2071 &kCFTypeDictionaryValueCallBacks), errOut); 2072 2073 //Leaf appears to be a SSL only cert, so policy should expand on that policy 2074 SecPolicyAddBasicX509Options(options); 2075 2076 // Apple CA anchored 2077 require(SecPolicyAddAppleAnchorOptions(options), errOut); 2078 2079 // Check for an extension with " Apple ID Validation Record Signing" oid (1.2.840.113635.100.6.25) 2080 add_leaf_marker(options, &oidAppleCertExtensionAppleIDRecordValidationSigning); 2081 2082 // and validate that intermediate has extension 2083 // Application Integration Intermediate Certificate (1.2.840.113635.100.6.2.3) 2084 // and also validate that intermediate has extension 2085 // System Integration 2 Intermediate Certificate (1.2.840.113635.100.6.2.10) 2086 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID); 2087 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntg2); 2088 2089 // Ensure that revocation is checked (OCSP) 2090 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); 2091 2092 require(result = SecPolicyCreate(kSecPolicyOIDAppleIDValidationRecordSigningPolicy, options), errOut); 2093 2094errOut: 2095 CFReleaseSafe(options); 2096 return result; 2097} 2098 2099/*! 2100 @function SecPolicyCreateAppleIDSService 2101 @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) 2102 */ 2103SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname) 2104{ 2105 return SecPolicyCreateSSL(true, hostname); 2106} 2107 2108/*! 2109 @function SecPolicyCreateApplePushService 2110 @abstract Ensure we're appropriately pinned to the Push service (SSL + Apple restrictions) 2111 */ 2112SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname) 2113{ 2114 return SecPolicyCreateSSL(true, hostname); 2115} 2116 2117/*! 2118 @function SecPolicyCreateAppleMMCSService 2119 @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) 2120 */ 2121SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname) 2122{ 2123 return SecPolicyCreateSSL(true, hostname); 2124} 2125 2126/*! 2127 @function SecPolicyCreateAppleSSLService 2128 @abstract Ensure we're appropriately pinned to an Apple server (SSL + Apple restrictions) 2129 */ 2130SecPolicyRef SecPolicyCreateAppleSSLService(CFStringRef hostname) 2131{ 2132 // SSL server, pinned to an Apple intermediate 2133 SecPolicyRef policy = SecPolicyCreateSSL(true, hostname); 2134 CFMutableDictionaryRef options = NULL; 2135 require(policy, errOut); 2136 2137 // change options for SSL policy evaluation 2138 require((options=(CFMutableDictionaryRef)policy->_options) != NULL, errOut); 2139 2140 // Apple CA anchored 2141 require(SecPolicyAddAppleAnchorOptions(options), errOut); 2142 2143 // Check leaf for Apple Server Authentication marker oid (1.2.840.113635.100.6.27.1) 2144 add_leaf_marker(options, &oidAppleCertExtAppleServerAuthentication); 2145 2146 // Check intermediate for Apple Server Authentication intermediate marker (1.2.840.113635.100.6.2.12) 2147 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleServerAuthentication); 2148 2149 // Ensure that revocation is checked (OCSP only) 2150 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); 2151 2152 return policy; 2153 2154errOut: 2155 CFReleaseSafe(options); 2156 CFReleaseSafe(policy); 2157 return NULL; 2158} 2159 2160#endif // TARGET_OS_IPHONE 2161