]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecPolicy.c
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / sec / Security / SecPolicy.c
1 /*
2 * Copyright (c) 2007-2015 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/oidsPriv.h>
42 #include <utilities/SecCFError.h>
43 #include <utilities/SecCFWrappers.h>
44 #include <utilities/array_size.h>
45 #include <ipc/securityd_client.h>
46 #if TARGET_OS_EMBEDDED
47 #include <MobileGestalt.h>
48 #else
49 #include <sys/utsname.h>
50 #endif
51
52 #include <utilities/SecInternalReleasePriv.h>
53
54 /********************************************************
55 **************** SecPolicy Constants *******************
56 ********************************************************/
57 // MARK: -
58 // MARK: SecPolicy Constants
59
60 #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v);
61
62 /********************************************************
63 ************** Unverified Leaf Checks ******************
64 ********************************************************/
65 SEC_CONST_DECL (kSecPolicyCheckSSLHostname, "SSLHostname");
66 SEC_CONST_DECL (kSecPolicyCheckEmail, "email");
67
68 /* Checks that the issuer of the leaf has exactly one Common Name and that it
69 matches the specified string. */
70 SEC_CONST_DECL (kSecPolicyCheckIssuerCommonName, "IssuerCommonName");
71
72 /* Checks that the leaf has exactly one Common Name and that it
73 matches the specified string. */
74 SEC_CONST_DECL (kSecPolicyCheckSubjectCommonName, "SubjectCommonName");
75
76 /* Checks that the leaf has exactly one Common Name and that it has the
77 specified string as a prefix. */
78 SEC_CONST_DECL (kSecPolicyCheckSubjectCommonNamePrefix, "SubjectCommonNamePrefix");
79
80 /* Checks that the leaf has exactly one Common Name and that it
81 matches the specified "<string>" or "TEST <string> TEST". */
82 SEC_CONST_DECL (kSecPolicyCheckSubjectCommonNameTEST, "SubjectCommonNameTEST");
83
84 /* Checks that the leaf has exactly one Organization and that it
85 matches the specified string. */
86 SEC_CONST_DECL (kSecPolicyCheckSubjectOrganization, "SubjectOrganization");
87
88 /* Checks that the leaf has exactly one Organizational Unit and that it
89 matches the specified string. */
90 SEC_CONST_DECL (kSecPolicyCheckSubjectOrganizationalUnit, "SubjectOrganizationalUnit");
91
92 /* Check that the leaf is not valid before the specified date (or verifyDate
93 if none is provided?). */
94 SEC_CONST_DECL (kSecPolicyCheckNotValidBefore, "NotValidBefore");
95
96 SEC_CONST_DECL (kSecPolicyCheckEAPTrustedServerNames, "EAPTrustedServerNames");
97
98 SEC_CONST_DECL (kSecPolicyCheckCertificatePolicy, "CertificatePolicy");
99
100 #if 0
101 /* Check for basic constraints on leaf to be valid. (rfc5280 check) */
102 SEC_CONST_DECL (kSecPolicyCheckLeafBasicConstraints, "LeafBasicContraints");
103 #endif
104
105 /********************************************************
106 *********** Unverified Intermediate Checks *************
107 ********************************************************/
108 SEC_CONST_DECL (kSecPolicyCheckKeyUsage, "KeyUsage"); /* (rfc5280 check) */
109 SEC_CONST_DECL (kSecPolicyCheckExtendedKeyUsage, "ExtendedKeyUsage"); /* (rfc5280 check) */
110 SEC_CONST_DECL (kSecPolicyCheckBasicContraints, "BasicContraints"); /* (rfc5280 check) */
111 SEC_CONST_DECL (kSecPolicyCheckQualifiedCertStatements, "QualifiedCertStatements"); /* (rfc5280 check) */
112 SEC_CONST_DECL (kSecPolicyCheckIntermediateSPKISHA256, "IntermediateSPKISHA256")
113
114 /********************************************************
115 ************** Unverified Anchor Checks ****************
116 ********************************************************/
117 SEC_CONST_DECL (kSecPolicyCheckAnchorSHA1, "AnchorSHA1");
118
119 /* Fake key for isAnchored check. */
120 SEC_CONST_DECL (kSecPolicyCheckAnchorTrusted, "AnchorTrusted");
121
122 /* Anchor is one of the apple trust anchors */
123 SEC_CONST_DECL (kSecPolicyCheckAnchorApple, "AnchorApple");
124
125 /* options for kSecPolicyCheckAnchorApple */
126 SEC_CONST_DECL (kSecPolicyAppleAnchorIncludeTestRoots, "AnchorAppleTestRoots");
127
128 /********************************************************
129 *********** Unverified Certificate Checks **************
130 ********************************************************/
131 /* Unverified Certificate Checks (any of the above) */
132 SEC_CONST_DECL (kSecPolicyCheckNonEmptySubject, "NonEmptySubject");
133 SEC_CONST_DECL (kSecPolicyCheckIdLinkage, "IdLinkage") /* (rfc5280 check) */
134 #if 0
135 SEC_CONST_DECL (kSecPolicyCheckValidityStarted, "ValidStarted");
136 SEC_CONST_DECL (kSecPolicyCheckValidityExpired, "ValidExpired");
137 #else
138 SEC_CONST_DECL (kSecPolicyCheckValidIntermediates, "ValidIntermediates");
139 SEC_CONST_DECL (kSecPolicyCheckValidLeaf, "ValidLeaf");
140 SEC_CONST_DECL (kSecPolicyCheckValidRoot, "ValidRoot");
141 #endif
142
143
144 /********************************************************
145 **************** Verified Path Checks ******************
146 ********************************************************/
147 /* (rfc5280 check) Ideally we should dynamically track all the extensions
148 we processed for each certificate and fail this test if any critical
149 extensions remain. */
150 SEC_CONST_DECL (kSecPolicyCheckCriticalExtensions, "CriticalExtensions");
151
152 /* Check that the certificate chain length matches the specificed CFNumberRef
153 length. */
154 SEC_CONST_DECL (kSecPolicyCheckChainLength, "ChainLength");
155
156 /* (rfc5280 check) */
157 SEC_CONST_DECL (kSecPolicyCheckBasicCertificateProcessing, "BasicCertificateProcessing");
158
159 /********************************************************
160 ******************* Feature toggles ********************
161 ********************************************************/
162
163 /* Check revocation if specified. */
164 SEC_CONST_DECL (kSecPolicyCheckExtendedValidation, "ExtendedValidation");
165 SEC_CONST_DECL (kSecPolicyCheckRevocation, "Revocation");
166 SEC_CONST_DECL (kSecPolicyCheckRevocationResponseRequired, "RevocationResponseRequired");
167
168 /* Check Certificate Transparency if specified. */
169 SEC_CONST_DECL (kSecPolicyCheckCertificateTransparency, "CertificateTransparency");
170
171 /* If present and true, we never go out to the network for anything
172 (OCSP, CRL or CA Issuer checking) but just used cached data instead. */
173 SEC_CONST_DECL (kSecPolicyCheckNoNetworkAccess, "NoNetworkAccess");
174
175 /* Hack to quickly blacklist certain certs. */
176 SEC_CONST_DECL (kSecPolicyCheckBlackListedLeaf, "BlackListedLeaf");
177 SEC_CONST_DECL (kSecPolicyCheckGrayListedLeaf, "GrayListedLeaf");
178 SEC_CONST_DECL (kSecPolicyCheckGrayListedKey, "GrayListedKey");
179 SEC_CONST_DECL (kSecPolicyCheckBlackListedKey, "BlackListedKey");
180
181 SEC_CONST_DECL (kSecPolicyCheckLeafMarkerOid, "CheckLeafMarkerOid");
182 SEC_CONST_DECL (kSecPolicyCheckIntermediateMarkerOid, "CheckIntermediateMarkerOid");
183
184 /* Public policy names. */
185 SEC_CONST_DECL (kSecPolicyAppleX509Basic, "1.2.840.113635.100.1.2");
186 SEC_CONST_DECL (kSecPolicyAppleSSL, "1.2.840.113635.100.1.3");
187 SEC_CONST_DECL (kSecPolicyAppleSMIME, "1.2.840.113635.100.1.8");
188 SEC_CONST_DECL (kSecPolicyAppleEAP, "1.2.840.113635.100.1.9");
189 SEC_CONST_DECL (kSecPolicyAppleSWUpdateSigning, "1.2.840.113635.100.1.10");
190 SEC_CONST_DECL (kSecPolicyAppleIPsec, "1.2.840.113635.100.1.11");
191 SEC_CONST_DECL (kSecPolicyApplePKINITClient, "1.2.840.113635.100.1.14");
192 SEC_CONST_DECL (kSecPolicyApplePKINITServer, "1.2.840.113635.100.1.15");
193 SEC_CONST_DECL (kSecPolicyAppleCodeSigning, "1.2.840.113635.100.1.16");
194 SEC_CONST_DECL (kSecPolicyApplePackageSigning, "1.2.840.113635.100.1.17");
195 SEC_CONST_DECL (kSecPolicyAppleIDValidation, "1.2.840.113635.100.1.18");
196 SEC_CONST_DECL (kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19");
197 SEC_CONST_DECL (kSecPolicyAppleTimeStamping, "1.2.840.113635.100.1.20");
198 SEC_CONST_DECL (kSecPolicyAppleRevocation, "1.2.840.113635.100.1.21");
199 SEC_CONST_DECL (kSecPolicyApplePassbookSigning, "1.2.840.113635.100.1.22");
200 SEC_CONST_DECL (kSecPolicyAppleMobileStore, "1.2.840.113635.100.1.23");
201 SEC_CONST_DECL (kSecPolicyAppleEscrowService, "1.2.840.113635.100.1.24");
202 SEC_CONST_DECL (kSecPolicyAppleProfileSigner, "1.2.840.113635.100.1.25");
203 SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner, "1.2.840.113635.100.1.26");
204 SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27");
205 SEC_CONST_DECL (kSecPolicyAppleOTAPKISigner, "1.2.840.113635.100.1.28");
206 SEC_CONST_DECL (kSecPolicyAppleTestOTAPKISigner, "1.2.840.113635.100.1.29");
207 /* FIXME: this policy name should be deprecated and replaced with "kSecPolicyAppleIDValidationRecordSigning" */
208 SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113625.100.1.30");
209 SEC_CONST_DECL (kSecPolicyAppleSMPEncryption, "1.2.840.113625.100.1.31");
210 SEC_CONST_DECL (kSecPolicyAppleTestSMPEncryption, "1.2.840.113625.100.1.32");
211 SEC_CONST_DECL (kSecPolicyAppleServerAuthentication, "1.2.840.113635.100.1.33");
212 SEC_CONST_DECL (kSecPolicyApplePCSEscrowService, "1.2.840.113635.100.1.34");
213 SEC_CONST_DECL (kSecPolicyApplePPQSigning, "1.2.840.113625.100.1.35");
214 SEC_CONST_DECL (kSecPolicyAppleTestPPQSigning, "1.2.840.113625.100.1.36");
215 SEC_CONST_DECL (kSecPolicyAppleATVAppSigning, "1.2.840.113625.100.1.37");
216 SEC_CONST_DECL (kSecPolicyAppleTestATVAppSigning, "1.2.840.113625.100.1.38");
217 SEC_CONST_DECL (kSecPolicyApplePayIssuerEncryption, "1.2.840.113625.100.1.39");
218 SEC_CONST_DECL (kSecPolicyAppleOSXProvisioningProfileSigning, "1.2.840.113625.100.1.40");
219 SEC_CONST_DECL (kSecPolicyAppleATVVPNProfileSigning, "1.2.840.113625.100.1.41");
220 // TODO need confirmation that OID for kSecPolicyAppleATVVPNProfileSigning is reserved
221
222 SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid");
223 SEC_CONST_DECL (kSecPolicyName, "SecPolicyName");
224 SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient");
225 SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags");
226 SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier");
227
228 /* Private policy names */
229 static CFStringRef kSecPolicyOIDBasicX509 = CFSTR("basicX509");
230 static CFStringRef kSecPolicyOIDSSLServer = CFSTR("sslServer");
231 static CFStringRef kSecPolicyOIDSSLClient = CFSTR("sslClient");
232 static CFStringRef kSecPolicyOIDiPhoneActivation = CFSTR("iPhoneActivation");
233 static CFStringRef kSecPolicyOIDiPhoneDeviceCertificate =
234 CFSTR("iPhoneDeviceCertificate");
235 static CFStringRef kSecPolicyOIDFactoryDeviceCertificate =
236 CFSTR("FactoryDeviceCertificate");
237 static CFStringRef kSecPolicyOIDiAP = CFSTR("iAP");
238 static CFStringRef kSecPolicyOIDiTunesStoreURLBag = CFSTR("iTunesStoreURLBag");
239 static CFStringRef kSecPolicyOIDEAPServer = CFSTR("eapServer");
240 static CFStringRef kSecPolicyOIDEAPClient = CFSTR("eapClient");
241 static CFStringRef kSecPolicyOIDIPSecServer = CFSTR("ipsecServer");
242 static CFStringRef kSecPolicyOIDIPSecClient = CFSTR("ipsecClient");
243 static CFStringRef kSecPolicyOIDiPhoneApplicationSigning =
244 CFSTR("iPhoneApplicationSigning");
245 static CFStringRef kSecPolicyOIDiPhoneProfileApplicationSigning =
246 CFSTR("iPhoneProfileApplicationSigning");
247 static CFStringRef kSecPolicyOIDiPhoneProvisioningProfileSigning =
248 CFSTR("iPhoneProvisioningProfileSigning");
249 static CFStringRef kSecPolicyOIDAppleSWUpdateSigning = CFSTR("AppleSWUpdateSigning");
250 static CFStringRef kSecPolicyOIDAppleTVOSApplicationSigning =
251 CFSTR("AppleTVApplicationSigning");
252 static CFStringRef kSecPolicyOIDRevocation = CFSTR("revocation");
253 static CFStringRef kSecPolicyOIDOCSPSigner = CFSTR("OCSPSigner");
254 static CFStringRef kSecPolicyOIDSMIME = CFSTR("SMIME");
255 static CFStringRef kSecPolicyOIDCodeSigning = CFSTR("CodeSigning");
256 static CFStringRef kSecPolicyOIDPackageSigning = CFSTR("PackageSigning");
257 static CFStringRef kSecPolicyOIDLockdownPairing = CFSTR("LockdownPairing");
258 static CFStringRef kSecPolicyOIDURLBag = CFSTR("URLBag");
259 static CFStringRef kSecPolicyOIDOTATasking = CFSTR("OTATasking");
260 static CFStringRef kSecPolicyOIDMobileAsset = CFSTR("MobileAsset");
261 static CFStringRef kSecPolicyOIDAppleIDAuthority = CFSTR("AppleIDAuthority");
262 static CFStringRef kSecPolicyOIDMacAppStoreReceipt = CFSTR("MacAppStoreReceipt");
263 static CFStringRef kSecPolicyOIDAppleTimeStamping = CFSTR("AppleTimeStamping");
264 static CFStringRef kSecPolicyOIDApplePassbook = CFSTR("ApplePassbook");
265 static CFStringRef kSecPolicyOIDAppleMobileStore = CFSTR("AppleMobileStore");
266 static CFStringRef kSecPolicyOIDAppleTestMobileStore = CFSTR("AppleTestMobileStore");
267 static CFStringRef kSecPolicyOIDAppleEscrowService = CFSTR("AppleEscrowService");
268 static CFStringRef kSecPolicyOIDApplePCSEscrowService = CFSTR("ApplePCSEscrowService");
269 static CFStringRef kSecPolicyOIDAppleProfileSigner = CFSTR("AppleProfileSigner");
270 static CFStringRef kSecPolicyOIDAppleQAProfileSigner = CFSTR("AppleQAProfileSigner");
271 static CFStringRef kSecPolicyOIDAppleOTAPKIAssetSigner = CFSTR("AppleOTAPKIAssetSigner");
272 static CFStringRef kSecPolicyOIDAppleTestOTAPKIAssetSigner = CFSTR("AppleTestOTAPKIAssetSigner");
273 static CFStringRef kSecPolicyOIDAppleIDValidationRecordSigningPolicy = CFSTR("AppleIDValidationRecordSigningPolicy");
274 static CFStringRef kSecPolicyOIDAppleATVAppSigning = CFSTR("AppleATVAppSigning");
275 static CFStringRef kSecPolicyOIDAppleTestATVAppSigning = CFSTR("AppleTestATVAppSigning");
276 static CFStringRef kSecPolicyOIDApplePayIssuerEncryption = CFSTR("ApplePayIssuerEncryption");
277 static CFStringRef kSecPolicyOIDAppleOSXProvisioningProfileSigning = CFSTR("AppleOSXProvisioningProfileSigning");
278 static CFStringRef kSecPolicyOIDAppleATVVPNProfileSigning = CFSTR("AppleATVVPNProfileSigning");
279
280 /* Policies will now change to multiple categories of checks.
281
282 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.
283 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.
284
285 kSecPolicySLCheck Static Subscriber Certificate Checks
286 kSecPolicySICheck Static Subsidiary CA Checks
287 kSecPolicySACheck Static Anchor Checks
288
289 kSecPolicyDLCheck Dynamic Subscriber Certificate Checks
290 kSecPolicyDICheck Dynamic Subsidiary CA Checks
291 kSecPolicyDACheck Dynamic Anchor Checks ? not yet needed other than to
292 possibly exclude in a exception template (but those should still be per
293 certificate --- i.o.w. exceptions (or a database backed multiple role/user
294 trust store of some sort) and policies are 2 different things and this
295 text is about policies.
296
297 All static checks are only allowed to consider the certificate in isolation,
298 just given the position in the chain or the cert (leaf, intermidate, root).
299 dynamic checks can make determinations about the chain as a whole.
300
301 Static Subscriber Certificate Checks will be done up front before the
302 chainbuilder is even instantiated. If they fail and details aren't required
303 by the client (if no exceptions were present for this certificate) we could
304 short circuit fail the evaluation.
305 IDEA: These checks can dynamically add new checks...[needs work]
306 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
307 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
308 equivalent subtree from that level down. So SSL has EV as a subpolicy, but
309 EV dynamically enables the ocsp or crl or dcrl or any combination thereof subpolicies.
310
311 Static Subsidiary CA Checks will be used by the chain-builder to choose the
312 best parents to evaluate first. This feature is currently already implemented
313 but with a hardcoded is_valid(verifyTime) check. Instead we will evaluate all
314 Static Subsidiary CA Checks. The results of these checks for purposes of
315 generating details could be cached in the SecCertificatePathRefs themselves, or we can short circuit fail and recalc details on demand later.
316
317 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.
318
319 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.
320
321 Dynamic Subsidiary CA Checks might not be needed to have custom
322 implementations, since they are all done as part of the rfc5280 checks now.
323 This assumes that checks like issuer common name includes 'foo' are
324 implmented as Static Subscriber Certificate Checks instead.
325
326 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.
327
328
329 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.
330
331 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.
332
333 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.
334
335 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.
336
337 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.
338
339 We need to remember the best successful chain we find, where best is defined by: satisfies as many optional policies as possible.
340
341 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.
342
343 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.
344
345 Example sectrust operation in psuedocode:
346 */
347 /*
348 {
349 new builder(verifyTime, certificates, anchors, anchorsOnly, policies);
350 chain = builder.subscriber_only_chain;
351 foreach (policy in policies{kSecPolicySLCheck}) {
352 foreach(check in policy)
353 SecPolicyRunCheck(builder, chain, check, details);
354 foreach (subpolicy in policy) {
355 check_policy(builder, chain, subpolicy, details{subpolicy.name})
356 }
357 propagate_subpolicy_results(builder, chain, details);
358 }
359 while (chain = builder.next) {
360 for (depth = 0; p_d = policies.at_depth(depth),
361 d_p_d = dynamic_policies.at_depth(depth), p_d || d_p_d; ++depth)
362 {
363 // Modify SecPathBuilderIsPartial() to
364 // run builder_check(buildier, policies, kSecPolicySICheck) instead
365 // of SecCertificateIsValid. Also rename considerExpired to
366 // considerSIFailures.
367 foreach (policy in p_d) {
368 check_policy(builder, chain, policy, kSecPolicySICheck, depth);
369 }
370 /// Recalculate since the static checks might have added new dynamic
371 // policies.
372 d_p_d = dynamic_policies.at_depth(depth);
373 foreach (policy in d_p_d) {
374 check_policy(builder, chain, policy, kSecPolicySICheck, depth);
375 }
376 if (chain.is_anchored) {
377 foreach (policy in p_d) {
378 check_policy(builder, chain, policy, kSecPolicySACheck, depth);
379 }
380 foreach (policy in d_p_d) {
381 check_policy(builder, chain, policy, kSecPolicySACheck, depth);
382 }
383 foreach (policy in p_d) {
384 check_policy(builder, chain, policy, kSecPolicyDACheck, depth);
385 }
386 foreach (policy in d_p_d) {
387 check_policy(builder, chain, policy, kSecPolicyDACheck, depth);
388 }
389 }
390 foreach (policy in policies) {
391 check_policy(builder, chain, policy, kSecPolicySACheck, depth);
392 check_policy(builder, chain, policy, kSecPolicyDACheck, depth);
393 }
394 foreach (policy in policies{kSecPolicySDCheck}) {
395 }
396 }
397 }
398
399 check_policy(builder, chain, policy, check_class, details, depth) {
400 if (depth == 0) {
401 foreach(check in policy{check_class}) {
402 SecPolicyRunCheck(builder, chain, check, details);
403 }
404 } else {
405 depth--;
406 foreach (subpolicy in policy) {
407 if (!check_policy(builder, chain, subpolicy, check_class,
408 details{subpolicy.name}) && subpolicy.is_required, depth)
409 secpvcsetresult()
410 }
411 }
412 propagate_subpolicy_results(builder, chain, details);
413 }
414
415 */
416
417
418
419 #define kSecPolicySHA1Size 20
420 #define kSecPolicySHA256Size 32
421 const UInt8 kAppleCASHA1[kSecPolicySHA1Size] = {
422 0x61, 0x1E, 0x5B, 0x66, 0x2C, 0x59, 0x3A, 0x08, 0xFF, 0x58,
423 0xD1, 0x4A, 0xE2, 0x24, 0x52, 0xD1, 0x98, 0xDF, 0x6C, 0x60
424 };
425
426 __unused static const UInt8 kAppleTESTCASHA1[kSecPolicySHA1Size] = {
427 0xbc, 0x30, 0x55, 0xc8, 0xc8, 0xd3, 0x48, 0x3f, 0xf4, 0x8d,
428 0xfe, 0x3d, 0x51, 0x75, 0x31, 0xc9, 0xf4, 0xd7, 0x4a, 0xf7
429 };
430
431 static const UInt8 kITMSCASHA1[kSecPolicySHA1Size] = {
432 0x1D, 0x33, 0x42, 0x46, 0x8B, 0x10, 0xBD, 0xE6, 0x45, 0xCE,
433 0x44, 0x6E, 0xBB, 0xE8, 0xF5, 0x03, 0x5D, 0xF8, 0x32, 0x22
434 };
435
436 static const UInt8 kFactoryDeviceCASHA1[kSecPolicySHA1Size] = {
437 0xef, 0x68, 0x73, 0x17, 0xa4, 0xf8, 0xf9, 0x4b, 0x7b, 0x21,
438 0xe2, 0x2f, 0x09, 0x8f, 0xfd, 0x6a, 0xae, 0xc0, 0x0d, 0x63
439 };
440
441 static const UInt8 kApplePKISettingsAuthority[kSecPolicySHA1Size] = {
442 0x1D, 0x0C, 0xBA, 0xAD, 0x17, 0xFD, 0x7E, 0x9E, 0x9F, 0xF1,
443 0xC9, 0xA2, 0x66, 0x79, 0x60, 0x00, 0x8B, 0xAE, 0x70, 0xB8
444 };
445
446 static const UInt8 kAppleTestPKISettingsAuthority[kSecPolicySHA1Size] = {
447 0xDB, 0xBA, 0x25, 0x0B, 0xD8, 0x62, 0x71, 0x87, 0x54, 0x7E,
448 0xD7, 0xEF, 0x11, 0x94, 0x7E, 0x82, 0xE6, 0xD8, 0x1C, 0x9A
449 };
450
451 static const UInt8 kTestAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = {
452 0x62, 0x0A, 0xED, 0x83, 0xD2, 0x97, 0x4A, 0x77, 0x56, 0x33,
453 0x83, 0xBE, 0xDB, 0xF9, 0xA1, 0xBD, 0x5F, 0xFE, 0x55, 0x7B
454 };
455
456 static const UInt8 kAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = {
457 0xB5, 0x2C, 0xB0, 0x2F, 0xD5, 0x67, 0xE0, 0x35, 0x9F, 0xE8,
458 0xFA, 0x4D, 0x4C, 0x41, 0x03, 0x79, 0x70, 0xFE, 0x01, 0xB0
459 };
460
461 // MARK: -
462 // MARK: SecPolicy
463 /********************************************************
464 ****************** SecPolicy object ********************
465 ********************************************************/
466
467 static void SecPolicyDestroy(CFTypeRef cf) {
468 SecPolicyRef policy = (SecPolicyRef) cf;
469 CFRelease(policy->_oid);
470 CFRelease(policy->_options);
471 }
472
473 static Boolean SecPolicyCompare(CFTypeRef cf1, CFTypeRef cf2) {
474 SecPolicyRef policy1 = (SecPolicyRef) cf1;
475 SecPolicyRef policy2 = (SecPolicyRef) cf2;
476 return CFEqual(policy1->_oid, policy2->_oid) &&
477 CFEqual(policy1->_options, policy2->_options);
478 }
479
480 static CFHashCode SecPolicyHash(CFTypeRef cf) {
481 SecPolicyRef policy = (SecPolicyRef) cf;
482
483 return CFHash(policy->_oid) + CFHash(policy->_options);
484 }
485
486 static CFStringRef SecPolicyCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
487 SecPolicyRef policy = (SecPolicyRef) cf;
488 CFMutableStringRef desc = CFStringCreateMutable(kCFAllocatorDefault, 0);
489 CFStringRef typeStr = CFCopyTypeIDDescription(CFGetTypeID(cf));
490 CFStringAppendFormat(desc, NULL,
491 CFSTR("<%@: oid: %@ options %@"), typeStr,
492 policy->_oid, policy->_options);
493 CFRelease(typeStr);
494 CFStringAppend(desc, CFSTR(" >"));
495
496 return desc;
497 }
498
499 /* SecPolicy API functions. */
500 CFGiblisWithHashFor(SecPolicy);
501
502 /* AUDIT[securityd](done):
503 oid (ok) is a caller provided string, only its cf type has been checked.
504 options is a caller provided dictionary, only its cf type has been checked.
505 */
506 SecPolicyRef SecPolicyCreate(CFStringRef oid, CFDictionaryRef options) {
507 SecPolicyRef result = NULL;
508
509 require(oid, errOut);
510 require(options, errOut);
511 require(result =
512 (SecPolicyRef)_CFRuntimeCreateInstance(kCFAllocatorDefault,
513 SecPolicyGetTypeID(),
514 sizeof(struct __SecPolicy) - sizeof(CFRuntimeBase), 0), errOut);
515
516 CFRetain(oid);
517 result->_oid = oid;
518 CFRetain(options);
519 result->_options = options;
520
521 errOut:
522 return result;
523 }
524
525 SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier,
526 CFDictionaryRef properties) {
527 // Creates a policy reference for a given policy object identifier.
528 // If policy-specific parameters can be supplied (e.g. hostname),
529 // attempt to obtain from input properties dictionary.
530 // Returns NULL if the given identifier is unsupported.
531
532 SecPolicyRef policy = NULL;
533 CFStringRef name = NULL;
534 CFStringRef teamID = NULL;
535 Boolean client = false;
536 require(policyIdentifier && (CFStringGetTypeID() == CFGetTypeID(policyIdentifier)), errOut);
537
538 if (properties) {
539 name = CFDictionaryGetValue(properties, kSecPolicyName);
540 teamID = CFDictionaryGetValue(properties, kSecPolicyTeamIdentifier);
541
542 CFBooleanRef dictionaryClientValue;
543 client = (CFDictionaryGetValueIfPresent(properties, kSecPolicyClient, (const void **)&dictionaryClientValue) &&
544 (dictionaryClientValue != NULL) && CFEqual(kCFBooleanTrue, dictionaryClientValue));
545 }
546
547 if (CFEqual(policyIdentifier, kSecPolicyAppleX509Basic)) {
548 policy = SecPolicyCreateBasicX509();
549 }
550 else if (CFEqual(policyIdentifier, kSecPolicyAppleSSL)) {
551 policy = SecPolicyCreateSSL(!client, name);
552 }
553 else if (CFEqual(policyIdentifier, kSecPolicyAppleEAP)) {
554 CFArrayRef array = NULL;
555 if (name) {
556 array = CFArrayCreate(kCFAllocatorDefault, (const void **)&name, 1, &kCFTypeArrayCallBacks);
557 }
558 policy = SecPolicyCreateEAP(!client, array);
559 CFReleaseSafe(array);
560 }
561 else if (CFEqual(policyIdentifier, kSecPolicyApplePackageSigning)) {
562 policy = SecPolicyCreateApplePackageSigning();
563 }
564 else if (CFEqual(policyIdentifier, kSecPolicyAppleSWUpdateSigning)) {
565 policy = SecPolicyCreateAppleSWUpdateSigning();
566 }
567 else if (CFEqual(policyIdentifier, kSecPolicyAppleIPsec)) {
568 policy = SecPolicyCreateIPSec(!client, name);
569 }
570 else if (CFEqual(policyIdentifier, kSecPolicyAppleRevocation)) {
571 policy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod);
572 }
573 else if (CFEqual(policyIdentifier, kSecPolicyAppleSMIME)) {
574 policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, name);
575 }
576 else if (CFEqual(policyIdentifier, kSecPolicyAppleCodeSigning)) {
577 policy = SecPolicyCreateCodeSigning();
578 }
579 else if (CFEqual(policyIdentifier, kSecPolicyAppleTimeStamping)) {
580 policy = SecPolicyCreateAppleTimeStamping();
581 }
582 else if (CFEqual(policyIdentifier, kSecPolicyMacAppStoreReceipt)) {
583 policy = SecPolicyCreateMacAppStoreReceipt();
584 }
585 else if (CFEqual(policyIdentifier, kSecPolicyAppleIDValidation)) {
586 policy = SecPolicyCreateAppleIDAuthorityPolicy();
587 }
588 else if (CFEqual(policyIdentifier, kSecPolicyApplePassbookSigning)) {
589 policy = SecPolicyCreatePassbookCardSigner(name, teamID);
590 }
591 else if (CFEqual(policyIdentifier, kSecPolicyAppleMobileStore)) {
592 policy = SecPolicyCreateMobileStoreSigner();
593 }
594 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestMobileStore)) {
595 policy = SecPolicyCreateTestMobileStoreSigner();
596 }
597 else if (CFEqual(policyIdentifier, kSecPolicyAppleEscrowService)) {
598 policy = SecPolicyCreateEscrowServiceSigner();
599 }
600 else if (CFEqual(policyIdentifier, kSecPolicyApplePCSEscrowService)) {
601 policy = SecPolicyCreatePCSEscrowServiceSigner();
602 }
603 else if (CFEqual(policyIdentifier, kSecPolicyAppleProfileSigner)) {
604 policy = SecPolicyCreateConfigurationProfileSigner();
605 }
606 else if (CFEqual(policyIdentifier, kSecPolicyAppleQAProfileSigner)) {
607 policy = SecPolicyCreateQAConfigurationProfileSigner();
608 }
609 else if (CFEqual(policyIdentifier, kSecPolicyAppleServerAuthentication)) {
610 policy = SecPolicyCreateAppleSSLService(name);
611 }
612 #if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
613 else if (CFEqual(policyIdentifier, kSecPolicyAppleOTAPKISigner)) {
614 policy = SecPolicyCreateOTAPKISigner();
615 }
616 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestOTAPKISigner)) {
617 policy = SecPolicyCreateTestOTAPKISigner();
618 }
619 else if (CFEqual(policyIdentifier, kSecPolicyAppleIDValidationRecordSigningPolicy)) {
620 policy = SecPolicyCreateAppleIDValidationRecordSigningPolicy();
621 }
622 else if (CFEqual(policyIdentifier, kSecPolicyAppleSMPEncryption)) {
623 policy = SecPolicyCreateAppleSMPEncryption();
624 }
625 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestSMPEncryption)) {
626 policy = SecPolicyCreateTestAppleSMPEncryption();
627 }
628 else if (CFEqual(policyIdentifier, kSecPolicyAppleATVAppSigning)) {
629 policy = SecPolicyCreateAppleATVAppSigning();
630 }
631 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestATVAppSigning)) {
632 policy = SecPolicyCreateTestAppleATVAppSigning();
633 }
634 #endif
635 else if (CFEqual(policyIdentifier, kSecPolicyApplePPQSigning)) {
636 policy = SecPolicyCreateApplePPQSigning();
637 }
638 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestPPQSigning)) {
639 policy = SecPolicyCreateTestApplePPQSigning();
640 }
641 else if (CFEqual(policyIdentifier, kSecPolicyApplePayIssuerEncryption)) {
642 policy = SecPolicyCreateApplePayIssuerEncryption();
643 }
644 else if (CFEqual(policyIdentifier, kSecPolicyAppleATVVPNProfileSigning)) {
645 policy = SecPolicyCreateAppleATVVPNProfileSigning();
646 }
647 else {
648 secerror("ERROR: policy \"%@\" is unsupported", policyIdentifier);
649 }
650
651 errOut:
652 return policy;
653 }
654
655 CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) {
656 // Builds and returns a dictionary which the caller must release.
657
658 #pragma clang diagnostic push
659 #pragma clang diagnostic ignored "-Wnonnull"
660 // After introducing nullability annotations, policyRef is supposed to be nonnull, suppress the warning
661 if (!policyRef) return NULL;
662 #pragma clang diagnostic pop
663 CFMutableDictionaryRef properties = CFDictionaryCreateMutable(NULL, 0,
664 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
665 #pragma clang diagnostic push
666 #pragma clang diagnostic ignored "-Wnonnull"
667 // 'properties' is nonnull in reality suppress the warning
668 if (!properties) return NULL;
669 #pragma clang diagnostic pop
670 CFStringRef oid = (CFStringRef) CFRetain(policyRef->_oid);
671 CFTypeRef nameKey = NULL;
672
673 // Convert private to public OID if we have one
674 CFStringRef outOid = oid;
675 if (CFEqual(oid, kSecPolicyOIDBasicX509)) {
676 outOid = kSecPolicyAppleX509Basic;
677 }
678 else if (CFEqual(oid, kSecPolicyOIDSSLServer) ||
679 CFEqual(oid, kSecPolicyOIDSSLClient)) {
680 outOid = kSecPolicyAppleSSL;
681 nameKey = kSecPolicyCheckSSLHostname;
682 }
683 else if (CFEqual(oid, kSecPolicyOIDEAPServer) ||
684 CFEqual(oid, kSecPolicyOIDEAPClient)) {
685 outOid = kSecPolicyAppleEAP;
686 nameKey = kSecPolicyCheckEAPTrustedServerNames;
687 }
688 else if (CFEqual(oid, kSecPolicyOIDIPSecServer) ||
689 CFEqual(oid, kSecPolicyOIDIPSecClient)) {
690 outOid = kSecPolicyAppleIPsec;
691 nameKey = kSecPolicyCheckSSLHostname;
692 }
693 else if (CFEqual(oid, kSecPolicyOIDRevocation)) {
694 outOid = kSecPolicyAppleRevocation;
695 }
696 else if (CFEqual(oid, kSecPolicyOIDSMIME)) {
697 outOid = kSecPolicyAppleSMIME;
698 nameKey = kSecPolicyCheckEmail;
699 }
700 else if (CFEqual(oid, kSecPolicyOIDCodeSigning)) {
701 outOid = kSecPolicyAppleCodeSigning;
702 }
703 else if (CFEqual(oid, kSecPolicyOIDAppleIDAuthority)) {
704 outOid = kSecPolicyAppleIDValidation;
705 }
706 else if (CFEqual(oid, kSecPolicyOIDApplePassbook)) {
707 outOid = kSecPolicyApplePassbookSigning;
708 }
709 else if (CFEqual(oid, kSecPolicyOIDAppleMobileStore)) {
710 outOid = kSecPolicyAppleMobileStore;
711 }
712 else if (CFEqual(oid, kSecPolicyOIDAppleTestMobileStore)) {
713 outOid = kSecPolicyAppleTestMobileStore;
714 }
715 else if (CFEqual(oid, kSecPolicyOIDAppleEscrowService)) {
716 outOid = kSecPolicyAppleEscrowService;
717 }
718 else if (CFEqual(oid, kSecPolicyOIDApplePCSEscrowService)) {
719 outOid = kSecPolicyApplePCSEscrowService;
720 }
721 else if (CFEqual(oid, kSecPolicyOIDAppleProfileSigner)) {
722 outOid = kSecPolicyAppleProfileSigner;
723 }
724 else if (CFEqual(oid, kSecPolicyOIDAppleQAProfileSigner)) {
725 outOid = kSecPolicyAppleQAProfileSigner;
726 }
727 #if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
728 else if (CFEqual(oid, kSecPolicyOIDAppleOTAPKIAssetSigner)) {
729 outOid = kSecPolicyAppleOTAPKISigner;
730 }
731 else if (CFEqual(oid, kSecPolicyOIDAppleTestOTAPKIAssetSigner)) {
732 outOid = kSecPolicyAppleTestOTAPKISigner;
733 }
734 else if (CFEqual(oid, kSecPolicyOIDAppleIDValidationRecordSigningPolicy)) {
735 outOid = kSecPolicyAppleIDValidationRecordSigningPolicy;
736 }
737 else if (CFEqual(oid, kSecPolicyOIDAppleATVAppSigning)) {
738 outOid = kSecPolicyAppleATVAppSigning;
739 }
740 else if (CFEqual(oid, kSecPolicyOIDAppleTestATVAppSigning)) {
741 outOid = kSecPolicyAppleTestATVAppSigning;
742 }
743 #endif
744 else if (CFEqual(oid, kSecPolicyOIDApplePayIssuerEncryption)) {
745 outOid = kSecPolicyApplePayIssuerEncryption;
746 }
747 else if (CFEqual(oid, kSecPolicyOIDAppleOSXProvisioningProfileSigning)) {
748 outOid = kSecPolicyAppleOSXProvisioningProfileSigning;
749 }
750 else if (CFEqual(oid, kSecPolicyOIDAppleATVVPNProfileSigning)) {
751 outOid = kSecPolicyAppleATVVPNProfileSigning;
752 }
753
754 // Set kSecPolicyOid
755 CFDictionarySetValue(properties, (const void *)kSecPolicyOid,
756 (const void *)outOid);
757
758 // Set kSecPolicyName if we have one
759 if (nameKey && policyRef->_options) {
760 CFTypeRef name = (CFTypeRef) CFDictionaryGetValue(policyRef->_options,
761 nameKey);
762 if (name) {
763 CFDictionarySetValue(properties, (const void *)kSecPolicyName,
764 (const void *)name);
765 }
766 }
767
768 // Set kSecPolicyClient
769 if (CFEqual(oid, kSecPolicyOIDSSLClient) ||
770 CFEqual(oid, kSecPolicyOIDIPSecClient) ||
771 CFEqual(oid, kSecPolicyOIDEAPClient)) {
772 CFDictionarySetValue(properties, (const void *)kSecPolicyClient,
773 (const void *)kCFBooleanTrue);
774 }
775
776 CFRelease(oid);
777 return properties;
778 }
779
780 static void SecPolicySetOid(SecPolicyRef policy, CFStringRef oid) {
781 if (!policy || !oid) return;
782 CFStringRef temp = policy->_oid;
783 CFRetain(oid);
784 policy->_oid = oid;
785 CFReleaseSafe(temp);
786 }
787
788 CFStringRef SecPolicyGetOidString(SecPolicyRef policy) {
789 return policy->_oid;
790 }
791
792 CFDictionaryRef SecPolicyGetOptions(SecPolicyRef policy) {
793 return policy->_options;
794 }
795
796 void SecPolicySetOptionsValue(SecPolicyRef policy, CFStringRef key, CFTypeRef value) {
797 if (!policy || !key) return;
798 CFMutableDictionaryRef options = (CFMutableDictionaryRef) policy->_options;
799 if (!options) {
800 options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
801 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
802 if (!options) return;
803 policy->_options = options;
804 }
805 CFDictionarySetValue(options, key, value);
806 }
807
808 #if !SECTRUST_OSX
809 // this is declared as NA for iPhone in SecPolicy.h, so declare here
810 OSStatus SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properties);
811 #endif
812
813 OSStatus SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properties) {
814 // Set policy options based on the provided dictionary keys.
815
816 if (!(policyRef && properties && (CFDictionaryGetTypeID() == CFGetTypeID(properties)))) {
817 return errSecParam;
818 }
819 CFStringRef oid = (CFStringRef) CFRetain(policyRef->_oid);
820 OSStatus result = errSecSuccess;
821
822 // kSecPolicyName
823 CFTypeRef name = NULL;
824 if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyName,
825 (const void **)&name) && name) {
826 CFTypeID typeID = CFGetTypeID(name);
827 if (CFEqual(oid, kSecPolicyOIDSSLServer) ||
828 CFEqual(oid, kSecPolicyOIDSSLClient) ||
829 CFEqual(oid, kSecPolicyOIDIPSecServer) ||
830 CFEqual(oid, kSecPolicyOIDIPSecClient)) {
831 if (CFStringGetTypeID() == typeID) {
832 SecPolicySetOptionsValue(policyRef, kSecPolicyCheckSSLHostname, name);
833 }
834 else result = errSecParam;
835 }
836 else if (CFEqual(oid, kSecPolicyOIDEAPServer) ||
837 CFEqual(oid, kSecPolicyOIDEAPClient)) {
838 if ((CFStringGetTypeID() == typeID) ||
839 (CFArrayGetTypeID() == typeID)) {
840 SecPolicySetOptionsValue(policyRef, kSecPolicyCheckEAPTrustedServerNames, name);
841 }
842 else result = errSecParam;
843 }
844 else if (CFEqual(oid, kSecPolicyOIDSMIME)) {
845 if (CFStringGetTypeID() == typeID) {
846 SecPolicySetOptionsValue(policyRef, kSecPolicyCheckEmail, name);
847 }
848 else result = errSecParam;
849 }
850 }
851
852 // kSecPolicyClient
853 CFTypeRef client = NULL;
854 if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyClient,
855 (const void **)&client) && client) {
856 if (!(CFBooleanGetTypeID() == CFGetTypeID(client))) {
857 result = errSecParam;
858 }
859 else if (CFEqual(client, kCFBooleanTrue)) {
860 if (CFEqual(oid, kSecPolicyOIDSSLServer)) {
861 SecPolicySetOid(policyRef, kSecPolicyOIDSSLClient);
862 }
863 else if (CFEqual(oid, kSecPolicyOIDIPSecServer)) {
864 SecPolicySetOid(policyRef, kSecPolicyOIDIPSecClient);
865 }
866 else if (CFEqual(oid, kSecPolicyOIDEAPServer)) {
867 SecPolicySetOid(policyRef, kSecPolicyOIDEAPClient);
868 }
869 }
870 else {
871 if (CFEqual(oid, kSecPolicyOIDSSLClient)) {
872 SecPolicySetOid(policyRef, kSecPolicyOIDSSLServer);
873 }
874 else if (CFEqual(oid, kSecPolicyOIDIPSecClient)) {
875 SecPolicySetOid(policyRef, kSecPolicyOIDIPSecServer);
876 }
877 else if (CFEqual(oid, kSecPolicyOIDEAPClient)) {
878 SecPolicySetOid(policyRef, kSecPolicyOIDEAPServer);
879 }
880 }
881 }
882
883 CFRelease(oid);
884 return result;
885 }
886
887 static xpc_object_t copy_xpc_policy_object(SecPolicyRef policy);
888 static bool append_policy_to_xpc_array(SecPolicyRef policy, xpc_object_t xpc_policies);
889 extern xpc_object_t copy_xpc_policies_array(CFArrayRef policies);
890 extern OSStatus validate_array_of_items(CFArrayRef array, CFStringRef arrayItemType, CFTypeID itemTypeID, bool required);
891
892 static xpc_object_t copy_xpc_policy_object(SecPolicyRef policy) {
893 xpc_object_t xpc_policy = NULL;
894 xpc_object_t data[2] = { NULL, NULL };
895 if (policy->_oid && (CFGetTypeID(policy->_oid) == CFStringGetTypeID())) {
896 data[0] = _CFXPCCreateXPCObjectFromCFObject(policy->_oid);
897 } else {
898 secerror("policy 0x%lX has no _oid", (uintptr_t)policy);
899 }
900 if (policy->_options && (CFGetTypeID(policy->_options) == CFDictionaryGetTypeID())) {
901 data[1] = _CFXPCCreateXPCObjectFromCFObject(policy->_options);
902 } else {
903 secerror("policy 0x%lX has no _options", (uintptr_t)policy);
904 }
905 xpc_policy = xpc_array_create(data, array_size(data));
906 if (data[0]) xpc_release(data[0]);
907 if (data[1]) xpc_release(data[1]);
908 return xpc_policy;
909 }
910
911 static bool append_policy_to_xpc_array(SecPolicyRef policy, xpc_object_t xpc_policies) {
912 if (!policy) {
913 return true; // NOOP
914 }
915 xpc_object_t xpc_policy = copy_xpc_policy_object(policy);
916 if (!xpc_policy) {
917 return false;
918 }
919 xpc_array_append_value(xpc_policies, xpc_policy);
920 xpc_release(xpc_policy);
921 return true;
922 }
923
924 xpc_object_t copy_xpc_policies_array(CFArrayRef policies) {
925 xpc_object_t xpc_policies = xpc_array_create(NULL, 0);
926 if (!xpc_policies) {
927 return NULL;
928 }
929 validate_array_of_items(policies, CFSTR("policy"), SecPolicyGetTypeID(), true);
930 CFIndex ix, count = CFArrayGetCount(policies);
931 for (ix = 0; ix < count; ++ix) {
932 SecPolicyRef policy = (SecPolicyRef) CFArrayGetValueAtIndex(policies, ix);
933 #if SECTRUST_VERBOSE_DEBUG
934 CFDictionaryRef props = SecPolicyCopyProperties(policy);
935 secerror("idx=%d of %d; policy=0x%lX properties=%@", (int)ix, (int)count, (uintptr_t)policy, props);
936 CFReleaseSafe(props);
937 #endif
938 if (!append_policy_to_xpc_array(policy, xpc_policies)) {
939 xpc_release(xpc_policies);
940 xpc_policies = NULL;
941 break;
942 }
943 }
944 return xpc_policies;
945 }
946
947 static xpc_object_t SecPolicyCopyXPCObject(SecPolicyRef policy, CFErrorRef *error) {
948 xpc_object_t xpc_policy = NULL;
949 xpc_object_t data[2] = {};
950 require_action_quiet(data[0] = _CFXPCCreateXPCObjectFromCFObject(policy->_oid), exit,
951 SecError(errSecParam, error, CFSTR("failed to create xpc_object from policy oid")));
952 require_action_quiet(data[1] = _CFXPCCreateXPCObjectFromCFObject(policy->_options), exit,
953 SecError(errSecParam, error, CFSTR("failed to create xpc_object from policy options")));
954 require_action_quiet(xpc_policy = xpc_array_create(data, array_size(data)), exit,
955 SecError(errSecAllocate, error, CFSTR("failed to create xpc_array for policy")));
956
957 exit:
958 if (data[0]) xpc_release(data[0]);
959 if (data[1]) xpc_release(data[1]);
960 return xpc_policy;
961 }
962
963 static bool SecPolicyAppendToXPCArray(SecPolicyRef policy, xpc_object_t policies, CFErrorRef *error) {
964 if (!policy)
965 return true; // NOOP
966
967 xpc_object_t xpc_policy = SecPolicyCopyXPCObject(policy, error);
968 if (!xpc_policy)
969 return false;
970
971 xpc_array_append_value(policies, xpc_policy);
972 xpc_release(xpc_policy);
973 return true;
974 }
975
976 xpc_object_t SecPolicyArrayCopyXPCArray(CFArrayRef policies, CFErrorRef *error) {
977 xpc_object_t xpc_policies;
978 require_action_quiet(xpc_policies = xpc_array_create(NULL, 0), exit,
979 SecError(errSecAllocate, error, CFSTR("failed to create xpc_array")));
980 CFIndex ix, count = CFArrayGetCount(policies);
981 for (ix = 0; ix < count; ++ix) {
982 if (!SecPolicyAppendToXPCArray((SecPolicyRef)CFArrayGetValueAtIndex(policies, ix), xpc_policies, error)) {
983 xpc_release(xpc_policies);
984 return NULL;
985 }
986 }
987 exit:
988 return xpc_policies;
989 }
990
991 static SecPolicyRef SecPolicyCreateWithXPCObject(xpc_object_t xpc_policy, CFErrorRef *error) {
992 SecPolicyRef policy = NULL;
993 CFTypeRef oid = NULL;
994 CFTypeRef options = NULL;
995
996 require_action_quiet(xpc_policy, exit, SecError(errSecParam, error, CFSTR("policy xpc value is NULL")));
997 require_action_quiet(xpc_get_type(xpc_policy) == XPC_TYPE_ARRAY, exit, SecError(errSecDecode, error, CFSTR("policy xpc value is not an array")));
998 require_action_quiet(xpc_array_get_count(xpc_policy) == 2, exit, SecError(errSecDecode, error, CFSTR("policy xpc array count != 2")));
999 oid = _CFXPCCreateCFObjectFromXPCObject(xpc_array_get_value(xpc_policy, 0));
1000 require_action_quiet(isString(oid), exit,
1001 SecError(errSecParam, error, CFSTR("failed to convert xpc policy[0]=%@ to CFString"), oid));
1002 options = _CFXPCCreateCFObjectFromXPCObject(xpc_array_get_value(xpc_policy, 1));
1003 require_action_quiet(isDictionary(options), exit,
1004 SecError(errSecParam, error, CFSTR("failed to convert xpc policy[1]=%@ to CFDictionary"), options));
1005 require_action_quiet(policy = SecPolicyCreate(oid, options), exit, SecError(errSecDecode, error, CFSTR("Failed to create policy")));
1006
1007 exit:
1008 CFReleaseSafe(oid);
1009 CFReleaseSafe(options);
1010 return policy;
1011 }
1012
1013 CFArrayRef SecPolicyXPCArrayCopyArray(xpc_object_t xpc_policies, CFErrorRef *error) {
1014 CFMutableArrayRef policies = NULL;
1015 require_action_quiet(xpc_get_type(xpc_policies) == XPC_TYPE_ARRAY, exit,
1016 SecError(errSecParam, error, CFSTR("policies xpc value is not an array")));
1017 size_t count = xpc_array_get_count(xpc_policies);
1018 require_action_quiet(policies = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks), exit,
1019 SecError(errSecAllocate, error, CFSTR("failed to create CFArray of capacity %zu"), count));
1020
1021 size_t ix;
1022 for (ix = 0; ix < count; ++ix) {
1023 SecPolicyRef policy = SecPolicyCreateWithXPCObject(xpc_array_get_value(xpc_policies, ix), error);
1024 if (!policy) {
1025 CFRelease(policies);
1026 return NULL;
1027 }
1028 CFArraySetValueAtIndex(policies, ix, policy);
1029 CFRelease(policy);
1030 }
1031
1032 exit:
1033 return policies;
1034
1035 }
1036
1037 static void add_element(CFMutableDictionaryRef options, CFStringRef key,
1038 CFTypeRef value) {
1039 CFTypeRef old_value = CFDictionaryGetValue(options, key);
1040 if (old_value) {
1041 CFMutableArrayRef array;
1042 if (CFGetTypeID(old_value) == CFArrayGetTypeID()) {
1043 array = (CFMutableArrayRef)old_value;
1044 } else {
1045 array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
1046 &kCFTypeArrayCallBacks);
1047 CFArrayAppendValue(array, old_value);
1048 CFDictionarySetValue(options, key, array);
1049 CFRelease(array);
1050 }
1051 CFArrayAppendValue(array, value);
1052 } else {
1053 CFDictionaryAddValue(options, key, value);
1054 }
1055 }
1056
1057 static void add_eku(CFMutableDictionaryRef options, const DERItem *ekuOid) {
1058 CFDataRef eku = CFDataCreate(kCFAllocatorDefault,
1059 ekuOid ? ekuOid->data : NULL,
1060 ekuOid ? ekuOid->length : 0);
1061 if (eku) {
1062 add_element(options, kSecPolicyCheckExtendedKeyUsage, eku);
1063 CFRelease(eku);
1064 }
1065 }
1066
1067 static void add_ku(CFMutableDictionaryRef options, SecKeyUsage keyUsage) {
1068 SInt32 dku = keyUsage;
1069 CFNumberRef ku = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
1070 &dku);
1071 if (ku) {
1072 add_element(options, kSecPolicyCheckKeyUsage, ku);
1073 CFRelease(ku);
1074 }
1075 }
1076
1077 static void add_oid(CFMutableDictionaryRef options, CFStringRef policy_key, const DERItem *oid) {
1078 CFDataRef oid_data = CFDataCreate(kCFAllocatorDefault,
1079 oid ? oid->data : NULL,
1080 oid ? oid->length : 0);
1081 if (oid_data) {
1082 add_element(options, policy_key, oid_data);
1083 CFRelease(oid_data);
1084 }
1085 }
1086
1087 static void add_leaf_marker_value(CFMutableDictionaryRef options, const DERItem *markerOid, CFStringRef string_value) {
1088
1089 CFTypeRef policyData = NULL;
1090
1091 if (NULL == string_value) {
1092 policyData = CFDataCreate(kCFAllocatorDefault,
1093 markerOid ? markerOid->data : NULL,
1094 markerOid ? markerOid->length : 0);
1095 } else {
1096 CFStringRef oid_as_string = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, markerOid);
1097
1098 const void *key[1] = { oid_as_string };
1099 const void *value[1] = { string_value };
1100 policyData = CFDictionaryCreate(kCFAllocatorDefault,
1101 key, value, 1,
1102 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1103 CFReleaseNull(oid_as_string);
1104 }
1105
1106 add_element(options, kSecPolicyCheckLeafMarkerOid, policyData);
1107
1108 CFReleaseNull(policyData);
1109
1110 }
1111
1112 static void add_leaf_marker(CFMutableDictionaryRef options, const DERItem *markerOid) {
1113 add_leaf_marker_value(options, markerOid, NULL);
1114 }
1115
1116
1117 static void add_certificate_policy_oid(CFMutableDictionaryRef options, const DERItem *certificatePolicyOid, CFStringRef string_value) {
1118 CFTypeRef certificatePolicyData = NULL;
1119
1120 if (NULL == string_value) {
1121 certificatePolicyData = CFDataCreate(kCFAllocatorDefault,
1122 certificatePolicyOid ? certificatePolicyOid->data : NULL,
1123 certificatePolicyOid ? certificatePolicyOid->length : 0);
1124 } else {
1125 CFStringRef oid_as_string = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, certificatePolicyOid);
1126
1127 const void *key[1] = { oid_as_string };
1128 const void *value[1] = { string_value };
1129 certificatePolicyData = CFDictionaryCreate(kCFAllocatorDefault,
1130 key, value, 1,
1131 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1132 CFReleaseNull(oid_as_string);
1133 }
1134
1135 add_element(options, kSecPolicyCheckCertificatePolicy, certificatePolicyData);
1136
1137 CFReleaseNull(certificatePolicyData);
1138 }
1139 //
1140 // Routines for adding dictionary entries for policies.
1141 //
1142
1143 // X.509, but missing validity requirements.
1144 static void SecPolicyAddBasicCertOptions(CFMutableDictionaryRef options)
1145 {
1146 //CFDictionaryAddValue(options, kSecPolicyCheckBasicCertificateProcessing, kCFBooleanTrue);
1147 CFDictionaryAddValue(options, kSecPolicyCheckCriticalExtensions, kCFBooleanTrue);
1148 CFDictionaryAddValue(options, kSecPolicyCheckIdLinkage, kCFBooleanTrue);
1149 CFDictionaryAddValue(options, kSecPolicyCheckBasicContraints, kCFBooleanTrue);
1150 CFDictionaryAddValue(options, kSecPolicyCheckNonEmptySubject, kCFBooleanTrue);
1151 CFDictionaryAddValue(options, kSecPolicyCheckQualifiedCertStatements, kCFBooleanTrue);
1152 }
1153
1154 static void SecPolicyAddBasicX509Options(CFMutableDictionaryRef options)
1155 {
1156 SecPolicyAddBasicCertOptions(options);
1157 CFDictionaryAddValue(options, kSecPolicyCheckValidIntermediates, kCFBooleanTrue);
1158 CFDictionaryAddValue(options, kSecPolicyCheckValidLeaf, kCFBooleanTrue);
1159 CFDictionaryAddValue(options, kSecPolicyCheckValidRoot, kCFBooleanTrue);
1160
1161 // Make sure that black and gray leaf checks are performed for basic X509 chain building
1162 CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf, kCFBooleanTrue);
1163 CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, kCFBooleanTrue);
1164 }
1165
1166 static bool SecPolicyAddChainLengthOptions(CFMutableDictionaryRef options, CFIndex length)
1167 {
1168 bool result = false;
1169 CFNumberRef lengthAsCF = NULL;
1170
1171 require(lengthAsCF = CFNumberCreate(kCFAllocatorDefault,
1172 kCFNumberCFIndexType, &length), errOut);
1173 CFDictionaryAddValue(options, kSecPolicyCheckChainLength, lengthAsCF);
1174
1175 result = true;
1176
1177 errOut:
1178 CFReleaseSafe(lengthAsCF);
1179 return result;
1180 }
1181
1182 static bool SecPolicyAddAnchorSHA1Options(CFMutableDictionaryRef options,
1183 const UInt8 anchorSha1[kSecPolicySHA1Size])
1184 {
1185 bool success = false;
1186 CFDataRef anchorData = NULL;
1187
1188 require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha1, kSecPolicySHA1Size), errOut);
1189 add_element(options, kSecPolicyCheckAnchorSHA1, anchorData);
1190
1191 success = true;
1192
1193 errOut:
1194 CFReleaseSafe(anchorData);
1195 return success;
1196 }
1197
1198 static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef options)
1199 {
1200 return SecPolicyAddAnchorSHA1Options(options, kAppleCASHA1);
1201 }
1202
1203 //
1204 // Policy Creation Functions
1205 //
1206 SecPolicyRef SecPolicyCreateBasicX509(void) {
1207 CFMutableDictionaryRef options = NULL;
1208 SecPolicyRef result = NULL;
1209
1210 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1211 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1212
1213 SecPolicyAddBasicX509Options(options);
1214 CFDictionaryAddValue(options, kSecPolicyCheckNoNetworkAccess,
1215 kCFBooleanTrue);
1216
1217 require(result = SecPolicyCreate(kSecPolicyOIDBasicX509, options), errOut);
1218
1219 errOut:
1220 CFReleaseSafe(options);
1221 return result;
1222 }
1223
1224 SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) {
1225 CFMutableDictionaryRef options = NULL;
1226 SecPolicyRef result = NULL;
1227
1228 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1229 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1230
1231 SecPolicyAddBasicX509Options(options);
1232
1233 if (hostname) {
1234 CFDictionaryAddValue(options, kSecPolicyCheckSSLHostname, hostname);
1235 }
1236
1237 CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf, kCFBooleanTrue);
1238 CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, kCFBooleanTrue);
1239
1240 /* If server and EKU ext present then EKU ext should contain one of
1241 ServerAuth or ExtendedKeyUsageAny or NetscapeSGC or MicrosoftSGC.
1242 else if !server and EKU ext present then EKU ext should contain one of
1243 ClientAuth or ExtendedKeyUsageAny. */
1244
1245 /* We always allow certificates that specify oidAnyExtendedKeyUsage. */
1246 add_eku(options, NULL); /* eku extension is optional */
1247 add_eku(options, &oidAnyExtendedKeyUsage);
1248 if (server) {
1249 add_eku(options, &oidExtendedKeyUsageServerAuth);
1250 add_eku(options, &oidExtendedKeyUsageMicrosoftSGC);
1251 add_eku(options, &oidExtendedKeyUsageNetscapeSGC);
1252 } else {
1253 add_eku(options, &oidExtendedKeyUsageClientAuth);
1254 }
1255
1256 require(result = SecPolicyCreate(
1257 server ? kSecPolicyOIDSSLServer : kSecPolicyOIDSSLClient,
1258 options), errOut);
1259
1260 errOut:
1261 CFReleaseSafe(options);
1262 return result;
1263 }
1264
1265 SecPolicyRef SecPolicyCreateiPhoneActivation(void) {
1266 CFMutableDictionaryRef options = NULL;
1267 SecPolicyRef result = NULL;
1268
1269 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1270 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1271
1272 SecPolicyAddBasicCertOptions(options);
1273
1274 #if 0
1275 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
1276 kCFBooleanTrue);
1277 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
1278 kCFBooleanTrue);
1279 #endif
1280
1281 /* Basic X.509 policy with the additional requirements that the chain
1282 length is 3, it's anchored at the AppleCA and the leaf certificate
1283 has issuer "Apple iPhone Certification Authority" and
1284 subject "Apple iPhone Activation" for the common name. */
1285 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
1286 CFSTR("Apple iPhone Certification Authority"));
1287 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName,
1288 CFSTR("Apple iPhone Activation"));
1289
1290 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
1291 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1292
1293 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneActivation, options),
1294 errOut);
1295
1296 errOut:
1297 CFReleaseSafe(options);
1298 return result;
1299 }
1300
1301 SecPolicyRef SecPolicyCreateiPhoneDeviceCertificate(void) {
1302 CFMutableDictionaryRef options = NULL;
1303 SecPolicyRef result = NULL;
1304
1305 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1306 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1307
1308 SecPolicyAddBasicCertOptions(options);
1309
1310 #if 0
1311 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
1312 kCFBooleanTrue);
1313 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
1314 kCFBooleanTrue);
1315 #endif
1316
1317 /* Basic X.509 policy with the additional requirements that the chain
1318 length is 4, it's anchored at the AppleCA and the first intermediate
1319 has the subject "Apple iPhone Device CA". */
1320 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
1321 CFSTR("Apple iPhone Device CA"));
1322
1323 require(SecPolicyAddChainLengthOptions(options, 4), errOut);
1324 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1325
1326 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneDeviceCertificate, options),
1327 errOut);
1328
1329 errOut:
1330 CFReleaseSafe(options);
1331 return result;
1332 }
1333
1334 SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void) {
1335 CFMutableDictionaryRef options = NULL;
1336 SecPolicyRef result = NULL;
1337
1338 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1339 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1340
1341 SecPolicyAddBasicCertOptions(options);
1342
1343 #if 0
1344 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
1345 kCFBooleanTrue);
1346 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
1347 kCFBooleanTrue);
1348 #endif
1349
1350 /* Basic X.509 policy with the additional requirements that the chain
1351 is anchored at the factory device certificate issuer. */
1352 require(SecPolicyAddAnchorSHA1Options(options, kFactoryDeviceCASHA1), errOut);
1353
1354 require(result = SecPolicyCreate(kSecPolicyOIDFactoryDeviceCertificate, options),
1355 errOut);
1356
1357 errOut:
1358 CFReleaseSafe(options);
1359 return result;
1360 }
1361
1362 SecPolicyRef SecPolicyCreateiAP(void) {
1363 CFMutableDictionaryRef options = NULL;
1364 SecPolicyRef result = NULL;
1365 CFTimeZoneRef tz = NULL;
1366 CFDateRef date = NULL;
1367
1368 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1369 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1370
1371 SecPolicyAddBasicCertOptions(options);
1372
1373 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNamePrefix,
1374 CFSTR("IPA_"));
1375
1376 date = CFDateCreateForGregorianZuluDay(NULL, 2006, 5, 31);
1377 CFDictionaryAddValue(options, kSecPolicyCheckNotValidBefore, date);
1378
1379 require(result = SecPolicyCreate(kSecPolicyOIDiAP, options),
1380 errOut);
1381
1382 errOut:
1383 CFReleaseSafe(date);
1384 CFReleaseSafe(tz);
1385 CFReleaseSafe(options);
1386 return result;
1387 }
1388
1389 SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void) {
1390 CFMutableDictionaryRef options = NULL;
1391 SecPolicyRef result = NULL;
1392
1393
1394 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1395 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1396
1397 SecPolicyAddBasicCertOptions(options);
1398
1399 CFDictionaryAddValue(options, kSecPolicyCheckSubjectOrganization,
1400 CFSTR("Apple Inc."));
1401 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName,
1402 CFSTR("iTunes Store URL Bag"));
1403
1404 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
1405 require(SecPolicyAddAnchorSHA1Options(options, kITMSCASHA1), errOut);
1406
1407 require(result = SecPolicyCreate(kSecPolicyOIDiTunesStoreURLBag, options), errOut);
1408
1409 errOut:
1410 CFReleaseSafe(options);
1411 return result;
1412 }
1413
1414 SecPolicyRef SecPolicyCreateEAP(Boolean server, CFArrayRef trustedServerNames) {
1415 CFMutableDictionaryRef options = NULL;
1416 SecPolicyRef result = NULL;
1417
1418 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1419 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1420
1421 SecPolicyAddBasicX509Options(options);
1422
1423 /* Since EAP is used to setup the network we don't want evaluation
1424 using this policy to access the network. */
1425 CFDictionaryAddValue(options, kSecPolicyCheckNoNetworkAccess,
1426 kCFBooleanTrue);
1427
1428 if (trustedServerNames) {
1429 CFDictionaryAddValue(options, kSecPolicyCheckEAPTrustedServerNames, trustedServerNames);
1430
1431 /* Specifying trusted server names implies EAP-TLS,
1432 so we need to check for EKU per rdar://22206018 */
1433
1434 /* If server and EKU ext present then EKU ext should contain one of
1435 ServerAuth or ExtendedKeyUsageAny or NetscapeSGC or MicrosoftSGC.
1436 else if !server and EKU ext present then EKU ext should contain one of
1437 ClientAuth or ExtendedKeyUsageAny. */
1438
1439 /* We always allow certificates that specify oidAnyExtendedKeyUsage. */
1440 add_eku(options, NULL); /* eku extension is optional */
1441 add_eku(options, &oidAnyExtendedKeyUsage);
1442 if (server) {
1443 add_eku(options, &oidExtendedKeyUsageServerAuth);
1444 add_eku(options, &oidExtendedKeyUsageMicrosoftSGC);
1445 add_eku(options, &oidExtendedKeyUsageNetscapeSGC);
1446 } else {
1447 add_eku(options, &oidExtendedKeyUsageClientAuth);
1448 }
1449 }
1450
1451 require(result = SecPolicyCreate(
1452 server ? kSecPolicyOIDEAPServer : kSecPolicyOIDEAPClient,
1453 options), errOut);
1454
1455 errOut:
1456 CFReleaseSafe(options);
1457 return result;
1458 }
1459
1460 SecPolicyRef SecPolicyCreateIPSec(Boolean server, CFStringRef hostname) {
1461 CFMutableDictionaryRef options = NULL;
1462 SecPolicyRef result = NULL;
1463
1464 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1465 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1466
1467 SecPolicyAddBasicX509Options(options);
1468
1469 if (hostname) {
1470 CFDictionaryAddValue(options, kSecPolicyCheckSSLHostname, hostname);
1471 }
1472
1473 /* Require oidExtendedKeyUsageIPSec if Extended Keyusage Extention is
1474 present. */
1475 /* Per <rdar://problem/6843827> Cisco VPN Certificate compatibility issue.
1476 We don't check the EKU for IPSec certs for now. If we do add eku
1477 checking back in the future, we should probably also accept the
1478 following EKUs:
1479 ipsecEndSystem 1.3.6.1.5.5.7.3.5
1480 and possibly even
1481 ipsecTunnel 1.3.6.1.5.5.7.3.6
1482 ipsecUser 1.3.6.1.5.5.7.3.7
1483 */
1484 //add_eku(options, NULL); /* eku extension is optional */
1485 //add_eku(options, &oidAnyExtendedKeyUsage);
1486 //add_eku(options, &oidExtendedKeyUsageIPSec);
1487
1488 require(result = SecPolicyCreate(
1489 server ? kSecPolicyOIDIPSecServer : kSecPolicyOIDIPSecClient,
1490 options), errOut);
1491
1492 errOut:
1493 CFReleaseSafe(options);
1494 return result;
1495 }
1496
1497 SecPolicyRef SecPolicyCreateiPhoneApplicationSigning(void) {
1498 CFMutableDictionaryRef options = NULL;
1499 SecPolicyRef result = NULL;
1500
1501 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1502 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1503
1504 SecPolicyAddBasicCertOptions(options);
1505
1506 /* Basic X.509 policy with the additional requirements that the chain
1507 length is 3, it's anchored at the AppleCA and the leaf certificate
1508 has issuer "Apple iPhone Certification Authority" and
1509 subject "Apple iPhone OS Application Signing" for the common name. */
1510 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
1511 CFSTR("Apple iPhone Certification Authority"));
1512 if (SecIsInternalRelease() && !SecIsProductionFused()) {
1513 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNameTEST,
1514 CFSTR("Apple iPhone OS Application Signing"));
1515 }
1516 else {
1517 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName,
1518 CFSTR("Apple iPhone OS Application Signing"));
1519 }
1520
1521 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
1522 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1523
1524 add_eku(options, NULL); /* eku extension is optional */
1525 add_eku(options, &oidAnyExtendedKeyUsage);
1526 add_eku(options, &oidExtendedKeyUsageCodeSigning);
1527
1528 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneApplicationSigning, options),
1529 errOut);
1530
1531 /* 1.2.840.113635.100.6.1.3, non-critical: DER:05:00 - application signing */
1532
1533 errOut:
1534 CFReleaseSafe(options);
1535 return result;
1536 }
1537
1538 SecPolicyRef SecPolicyCreateiPhoneProfileApplicationSigning(void) {
1539 CFMutableDictionaryRef options = NULL;
1540 SecPolicyRef result = NULL;
1541
1542 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1543 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1544 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
1545 CFDictionaryAddValue(options, kSecPolicyCheckValidLeaf, kCFBooleanFalse);
1546
1547 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneProfileApplicationSigning,
1548 options), errOut);
1549
1550 errOut:
1551 CFReleaseSafe(options);
1552 return result;
1553 }
1554
1555 SecPolicyRef SecPolicyCreateiPhoneProvisioningProfileSigning(void) {
1556 CFMutableDictionaryRef options = NULL;
1557 SecPolicyRef result = NULL;
1558
1559 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1560 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1561
1562 SecPolicyAddBasicCertOptions(options);
1563
1564 /* Basic X.509 policy with the additional requirements that the chain
1565 length is 3, it's anchored at the AppleCA and the leaf certificate
1566 has issuer "Apple iPhone Certification Authority" and
1567 subject "Apple iPhone OS Provisioning Profile Signing" for the common name. */
1568 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
1569 CFSTR("Apple iPhone Certification Authority"));
1570 if (SecIsInternalRelease() && !SecIsProductionFused()) {
1571 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNameTEST,
1572 CFSTR("Apple iPhone OS Provisioning Profile Signing"));
1573 }
1574 else {
1575 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName,
1576 CFSTR("Apple iPhone OS Provisioning Profile Signing"));
1577 }
1578
1579 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
1580 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1581
1582 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneProvisioningProfileSigning, options),
1583 errOut);
1584
1585 /* 1.2.840.113635.100.6.2.2.1, non-critical: DER:05:00 - provisioning profile */
1586
1587 errOut:
1588 CFReleaseSafe(options);
1589 return result;
1590 }
1591
1592 SecPolicyRef SecPolicyCreateAppleTVOSApplicationSigning(void) {
1593 CFMutableDictionaryRef options = NULL;
1594 SecPolicyRef result = NULL;
1595 CFDataRef atvProdOid = NULL;
1596 CFDataRef atvTestOid = NULL;
1597 CFArrayRef oids = NULL;
1598
1599 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1600 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1601
1602 SecPolicyAddBasicCertOptions(options);
1603
1604 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
1605
1606 CFMutableDictionaryRef appleAnchorOptions = CFDictionaryCreateMutableForCFTypes(NULL);
1607 require(appleAnchorOptions, errOut);
1608 add_element(options, kSecPolicyCheckAnchorApple, appleAnchorOptions);
1609
1610 /* Check for intermediate: Apple Worldwide Developer Relations */
1611 /* 1.2.840.113635.100.6.2.1 */
1612 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleWWDR);
1613
1614 add_eku(options, NULL); /* eku extension is optional */
1615 add_eku(options, &oidAnyExtendedKeyUsage);
1616 add_eku(options, &oidExtendedKeyUsageCodeSigning);
1617
1618 /* Check for prod or test AppleTV Application Signing OIDs */
1619 /* Prod: 1.2.840.113635.100.6.1.24 */
1620 /* Test: 1.2.840.113635.100.6.1.24.1 */
1621 atvProdOid = CFDataCreate(kCFAllocatorDefault, oidAppleTVOSApplicationSigningProd.data, oidAppleTVOSApplicationSigningProd.length);
1622 require(atvProdOid, errOut);
1623 atvTestOid = CFDataCreate(kCFAllocatorDefault, oidAppleTVOSApplicationSigningTest.data, oidAppleTVOSApplicationSigningTest.length);
1624 require(atvTestOid, errOut);
1625
1626 oids = CFArrayCreateForCFTypes(kCFAllocatorDefault, atvProdOid, atvTestOid, NULL);
1627 require(oids, errOut);
1628
1629 add_element(options, kSecPolicyCheckLeafMarkerOid, oids);
1630
1631 require(result = SecPolicyCreate(kSecPolicyOIDAppleTVOSApplicationSigning, options),
1632 errOut);
1633
1634 errOut:
1635 CFReleaseSafe(options);
1636 CFReleaseSafe(oids);
1637 CFReleaseSafe(atvProdOid);
1638 CFReleaseSafe(atvTestOid);
1639 return result;
1640 }
1641
1642 SecPolicyRef SecPolicyCreateOCSPSigner(void) {
1643 CFMutableDictionaryRef options = NULL;
1644 SecPolicyRef result = NULL;
1645
1646 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1647 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1648
1649 SecPolicyAddBasicX509Options(options);
1650
1651 /* Require id-kp-OCSPSigning extendedKeyUsage to be present, not optional. */
1652 add_eku(options, &oidExtendedKeyUsageOCSPSigning);
1653
1654 require(result = SecPolicyCreate(kSecPolicyOIDOCSPSigner, options), errOut);
1655
1656 errOut:
1657 CFReleaseSafe(options);
1658 return result;
1659 }
1660
1661 SecPolicyRef SecPolicyCreateRevocation(CFOptionFlags revocationFlags) {
1662 CFMutableDictionaryRef options = NULL;
1663 SecPolicyRef result = NULL;
1664
1665 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1666 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1667
1668 /* false = ocsp, true = crl, string/url value = crl distribution point,
1669 array = list of multiple values for example false, true, url1, url2
1670 check ocsp, crl, and url1 and url2 for certs which have no extensions.
1671 */
1672 if (revocationFlags & kSecRevocationOCSPMethod) {
1673 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
1674 }
1675 else if (revocationFlags & kSecRevocationCRLMethod) {
1676 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanTrue);
1677 }
1678
1679 if (revocationFlags & kSecRevocationRequirePositiveResponse) {
1680 CFDictionaryAddValue(options, kSecPolicyCheckRevocationResponseRequired, kCFBooleanTrue);
1681 }
1682
1683 if (revocationFlags & kSecRevocationNetworkAccessDisabled) {
1684 CFDictionaryAddValue(options, kSecPolicyCheckNoNetworkAccess, kCFBooleanTrue);
1685 }
1686
1687 /* Only flag bits 0-4 are currently defined */
1688 require(((revocationFlags >> 5) == 0), errOut);
1689
1690 require(result = SecPolicyCreate(kSecPolicyOIDRevocation, options), errOut);
1691
1692 errOut:
1693 CFReleaseSafe(options);
1694 return result;
1695 }
1696
1697 SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email) {
1698 CFMutableDictionaryRef options = NULL;
1699 SecPolicyRef result = NULL;
1700
1701 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1702 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1703
1704 SecPolicyAddBasicX509Options(options);
1705
1706 /* We call add_ku for each combination of bits we are willing to allow. */
1707 if (smimeUsage & kSecSignSMIMEUsage) {
1708 add_ku(options, kSecKeyUsageUnspecified);
1709 add_ku(options, kSecKeyUsageDigitalSignature);
1710 add_ku(options, kSecKeyUsageNonRepudiation);
1711 }
1712 if (smimeUsage & kSecKeyEncryptSMIMEUsage) {
1713 add_ku(options, kSecKeyUsageKeyEncipherment);
1714 }
1715 if (smimeUsage & kSecDataEncryptSMIMEUsage) {
1716 add_ku(options, kSecKeyUsageDataEncipherment);
1717 }
1718 if (smimeUsage & kSecKeyExchangeDecryptSMIMEUsage) {
1719 add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageDecipherOnly);
1720 }
1721 if (smimeUsage & kSecKeyExchangeEncryptSMIMEUsage) {
1722 add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly);
1723 }
1724 if (smimeUsage & kSecKeyExchangeBothSMIMEUsage) {
1725 add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly | kSecKeyUsageDecipherOnly);
1726 }
1727
1728 if (email) {
1729 CFDictionaryAddValue(options, kSecPolicyCheckEmail, email);
1730 }
1731
1732 /* RFC 3850 paragraph 4.4.4
1733
1734 If the extended key usage extension is present in the certificate
1735 then interpersonal message S/MIME receiving agents MUST check that it
1736 contains either the emailProtection or the anyExtendedKeyUsage OID as
1737 defined in [KEYM]. S/MIME uses other than interpersonal messaging
1738 MAY require the explicit presence of the extended key usage extension
1739 or other OIDs to be present in the extension or both.
1740 */
1741 add_eku(options, NULL); /* eku extension is optional */
1742 add_eku(options, &oidAnyExtendedKeyUsage);
1743 add_eku(options, &oidExtendedKeyUsageEmailProtection);
1744
1745 require(result = SecPolicyCreate(kSecPolicyOIDSMIME, options), errOut);
1746
1747 errOut:
1748 CFReleaseSafe(options);
1749 return result;
1750 }
1751
1752 SecPolicyRef SecPolicyCreateApplePackageSigning(void) {
1753 CFMutableDictionaryRef options = NULL;
1754 SecPolicyRef result = NULL;
1755
1756 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1757 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1758
1759 // TBD: review OS X policy to see what options are needed for this policy
1760 SecPolicyAddBasicCertOptions(options);
1761
1762 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
1763 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1764
1765 require(result = SecPolicyCreate(kSecPolicyOIDPackageSigning, options),
1766 errOut);
1767
1768 errOut:
1769 CFReleaseSafe(options);
1770 return result;
1771
1772 }
1773
1774 SecPolicyRef SecPolicyCreateAppleSWUpdateSigning(void) {
1775 CFMutableDictionaryRef options = NULL;
1776 SecPolicyRef result = NULL;
1777 /*
1778 * OS X rules for this policy:
1779 * -- Must have one intermediate cert
1780 * -- intermediate must have basic constraints with path length 0
1781 * -- intermediate has CSSMOID_APPLE_EKU_CODE_SIGNING EKU
1782 * -- leaf cert has either CODE_SIGNING or CODE_SIGN_DEVELOPMENT EKU (the latter of
1783 * which triggers a CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT error)
1784 */
1785 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1786 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1787
1788 // TBD: review OS X policy to see what options are needed for this policy
1789 SecPolicyAddBasicCertOptions(options);
1790
1791 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
1792 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1793
1794 add_eku(options, &oidAppleExtendedKeyUsageCodeSigning);
1795 add_eku(options, &oidAppleExtendedKeyUsageCodeSigningDev);
1796
1797 require(result = SecPolicyCreate(kSecPolicyOIDAppleSWUpdateSigning, options),
1798 errOut);
1799
1800 errOut:
1801 CFReleaseSafe(options);
1802 return result;
1803
1804 }
1805
1806 SecPolicyRef SecPolicyCreateCodeSigning(void) {
1807 CFMutableDictionaryRef options = NULL;
1808 SecPolicyRef result = NULL;
1809
1810 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1811 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1812
1813 #if SECTRUST_OSX
1814 #warning STU: <rdar://21328880>
1815 //%%% figure out why this policy is not passing for OS X.
1816 // I suspect it has to do with iOS not supporting anchor and keychain options yet.
1817 SecPolicyAddBasicCertOptions(options);
1818 #else
1819 SecPolicyAddBasicX509Options(options);
1820
1821 /* If the key usage extension is present we accept it having either of
1822 these values. */
1823 add_ku(options, kSecKeyUsageDigitalSignature);
1824 add_ku(options, kSecKeyUsageNonRepudiation);
1825
1826 /* We require a extended key usage extension and we accept any or
1827 codesigning ekus. */
1828 /* TODO: Do we want to accept the apple codesigning oid as well or is
1829 that a separate policy? */
1830 /* ANSWER: it's a separate policy, SecPolicyCreateAppleSWUpdateSigning */
1831 add_eku(options, &oidAnyExtendedKeyUsage);
1832 add_eku(options, &oidExtendedKeyUsageCodeSigning);
1833 #endif
1834
1835 require(result = SecPolicyCreate(kSecPolicyOIDCodeSigning, options),
1836 errOut);
1837
1838 errOut:
1839 CFReleaseSafe(options);
1840 return result;
1841 }
1842
1843 /* Explicitly leave out empty subject/subjectaltname check */
1844 SecPolicyRef SecPolicyCreateLockdownPairing(void) {
1845 CFMutableDictionaryRef options = NULL;
1846 SecPolicyRef result = NULL;
1847
1848 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1849 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1850 //CFDictionaryAddValue(options, kSecPolicyCheckBasicCertificateProcessing,
1851 // kCFBooleanTrue);
1852 CFDictionaryAddValue(options, kSecPolicyCheckCriticalExtensions,
1853 kCFBooleanTrue);
1854 CFDictionaryAddValue(options, kSecPolicyCheckIdLinkage,
1855 kCFBooleanTrue);
1856 CFDictionaryAddValue(options, kSecPolicyCheckBasicContraints,
1857 kCFBooleanTrue);
1858 CFDictionaryAddValue(options, kSecPolicyCheckQualifiedCertStatements,
1859 kCFBooleanTrue);
1860
1861 require(result = SecPolicyCreate(kSecPolicyOIDLockdownPairing, options), errOut);
1862
1863 errOut:
1864 CFReleaseSafe(options);
1865 return result;
1866 }
1867
1868 SecPolicyRef SecPolicyCreateURLBag(void) {
1869 CFMutableDictionaryRef options = NULL;
1870 SecPolicyRef result = NULL;
1871
1872 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1873 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1874
1875 SecPolicyAddBasicCertOptions(options);
1876
1877 add_eku(options, &oidExtendedKeyUsageCodeSigning);
1878
1879 require(result = SecPolicyCreate(kSecPolicyOIDURLBag, options), errOut);
1880
1881 errOut:
1882 CFReleaseSafe(options);
1883 return result;
1884 }
1885
1886 static bool SecPolicyAddAppleCertificationAuthorityOptions(CFMutableDictionaryRef options, bool honorValidity)
1887 {
1888 bool success = false;
1889
1890 if (honorValidity)
1891 SecPolicyAddBasicX509Options(options);
1892 else
1893 SecPolicyAddBasicCertOptions(options);
1894
1895 #if 0
1896 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
1897 kCFBooleanTrue);
1898 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
1899 kCFBooleanTrue);
1900 #endif
1901
1902 /* Basic X.509 policy with the additional requirements that the chain
1903 length is 3, it's anchored at the AppleCA and the leaf certificate
1904 has issuer "Apple iPhone Certification Authority". */
1905 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
1906 CFSTR("Apple iPhone Certification Authority"));
1907
1908 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
1909 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1910
1911 success = true;
1912
1913 errOut:
1914 return success;
1915 }
1916
1917 static SecPolicyRef SecPolicyCreateAppleCertificationAuthorityPolicy(CFStringRef policyOID, CFStringRef leafName, bool honorValidity)
1918 {
1919 CFMutableDictionaryRef options = NULL;
1920 SecPolicyRef result = NULL;
1921
1922 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1923 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1924
1925 require(SecPolicyAddAppleCertificationAuthorityOptions(options, honorValidity), errOut);
1926
1927 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName, leafName);
1928
1929 require(result = SecPolicyCreate(policyOID, options),
1930 errOut);
1931
1932 errOut:
1933 CFReleaseSafe(options);
1934 return result;
1935 }
1936
1937
1938 SecPolicyRef SecPolicyCreateOTATasking(void)
1939 {
1940 return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDOTATasking, CFSTR("OTA Task Signing"), true);
1941 }
1942
1943 SecPolicyRef SecPolicyCreateMobileAsset(void)
1944 {
1945 return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDMobileAsset, CFSTR("Asset Manifest Signing"), false);
1946 }
1947
1948 SecPolicyRef SecPolicyCreateAppleIDAuthorityPolicy(void)
1949 {
1950 SecPolicyRef result = NULL;
1951 CFMutableDictionaryRef options = NULL;
1952 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1953 &kCFTypeDictionaryKeyCallBacks,
1954 &kCFTypeDictionaryValueCallBacks), out);
1955
1956 //Leaf appears to be a SSL only cert, so policy should expand on that policy
1957 SecPolicyAddBasicX509Options(options);
1958
1959 // Apple CA anchored
1960 require(SecPolicyAddAppleAnchorOptions(options), out);
1961
1962 // with the addition of the existence check of an extension with "Apple ID Sharing Certificate" oid (1.2.840.113635.100.4.7)
1963 // NOTE: this obviously intended to have gone into Extended Key Usage, but evidence of existing certs proves the contrary.
1964 add_leaf_marker(options, &oidAppleExtendedKeyUsageAppleID);
1965
1966 // 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.
1967 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID);
1968 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID2);
1969
1970 require(result = SecPolicyCreate(kSecPolicyOIDAppleIDAuthority, options), out);
1971
1972 out:
1973 CFReleaseSafe(options);
1974 return result;
1975 }
1976
1977 SecPolicyRef SecPolicyCreateMacAppStoreReceipt(void)
1978 {
1979 SecPolicyRef result = NULL;
1980 CFMutableDictionaryRef options = NULL;
1981 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1982 &kCFTypeDictionaryKeyCallBacks,
1983 &kCFTypeDictionaryValueCallBacks), out);
1984
1985 SecPolicyAddBasicX509Options(options);
1986
1987 // Apple CA anchored
1988 require(SecPolicyAddAppleAnchorOptions(options), out);
1989
1990 // - leaf needs certificatePolicies with CSSMOID_MACAPPSTORE_RECEIPT_CERT_POLICY
1991 // - chain length must be 3
1992
1993 require(result = SecPolicyCreate(kSecPolicyOIDMacAppStoreReceipt, options), out);
1994
1995 out:
1996 CFReleaseSafe(options);
1997 return result;
1998
1999 }
2000
2001 static SecPolicyRef _SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, CFStringRef teamIdentifier, bool requireTeamID)
2002 {
2003 SecPolicyRef result = NULL;
2004 CFMutableDictionaryRef options = NULL;
2005 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2006 &kCFTypeDictionaryKeyCallBacks,
2007 &kCFTypeDictionaryValueCallBacks), out);
2008
2009 SecPolicyAddBasicX509Options(options);
2010 SecPolicyAddAppleAnchorOptions(options);
2011
2012 if (teamIdentifier) {
2013 // If supplied, teamIdentifier must match subject OU field
2014 CFDictionaryAddValue(options, kSecPolicyCheckSubjectOrganizationalUnit, teamIdentifier);
2015 }
2016 else {
2017 // If not supplied, and it was required, fail
2018 require(!requireTeamID, out);
2019 }
2020
2021 // Must be both push and 3rd party package signing
2022 add_leaf_marker_value(options, &oidAppleInstallerPackagingSigningExternal, cardIssuer);
2023
2024 // We should check that it also has push marker, but we don't support requiring both, only either.
2025 // add_independent_oid(options, kSecPolicyCheckLeafMarkerOid, &oidApplePushServiceClient);
2026
2027 // And Passbook signing eku
2028 add_eku(options, &oidAppleExtendedKeyUsagePassbook);
2029
2030 require(result = SecPolicyCreate(kSecPolicyOIDApplePassbook, options), out);
2031
2032 out:
2033 CFReleaseSafe(options);
2034 return result;
2035 }
2036
2037 SecPolicyRef SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, CFStringRef teamIdentifier)
2038 {
2039 return _SecPolicyCreatePassbookCardSigner(cardIssuer, teamIdentifier, true);
2040 }
2041
2042
2043 static SecPolicyRef CreateMobileStoreSigner(Boolean forTest)
2044 {
2045
2046 SecPolicyRef result = NULL;
2047 CFMutableDictionaryRef options = NULL;
2048 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2049 &kCFTypeDictionaryKeyCallBacks,
2050 &kCFTypeDictionaryValueCallBacks), errOut);
2051 SecPolicyAddBasicX509Options(options);
2052 SecPolicyAddAppleAnchorOptions(options);
2053
2054 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2055
2056 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2057 CFSTR("Apple System Integration 2 Certification Authority"));
2058
2059 add_ku(options, kSecKeyUsageDigitalSignature);
2060
2061 const DERItem* pOID = (forTest) ? &oidApplePolicyTestMobileStore : &oidApplePolicyMobileStore;
2062
2063 add_certificate_policy_oid(options, pOID, NULL);
2064
2065 require(result = SecPolicyCreate(kSecPolicyOIDAppleMobileStore, options), errOut);
2066
2067 errOut:
2068 CFReleaseSafe(options);
2069 return result;
2070 }
2071
2072 SecPolicyRef SecPolicyCreateMobileStoreSigner(void)
2073 {
2074
2075 return CreateMobileStoreSigner(false);
2076 }
2077
2078 SecPolicyRef SecPolicyCreateTestMobileStoreSigner(void)
2079 {
2080
2081 return CreateMobileStoreSigner(true);
2082 }
2083
2084
2085 CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateEscrowServiceSigner(void)
2086 {
2087 SecPolicyRef result = NULL;
2088 CFMutableDictionaryRef options = NULL;
2089 CFArrayRef anArray = NULL;
2090 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2091 &kCFTypeDictionaryKeyCallBacks,
2092 &kCFTypeDictionaryValueCallBacks), errOut);
2093
2094 // X509, ignoring date validity
2095 SecPolicyAddBasicCertOptions(options);
2096
2097
2098 add_ku(options, kSecKeyUsageKeyEncipherment);
2099
2100 //add_leaf_marker(options, &oidApplePolicyEscrowService);
2101 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
2102
2103
2104 Boolean anchorAdded = false;
2105 // Get the roots by calling the SecCertificateCopyEscrowRoots
2106 anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot);
2107 CFIndex numRoots = 0;
2108 if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray)))
2109 {
2110 goto errOut;
2111 }
2112
2113 for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++)
2114 {
2115 SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt);
2116
2117 if (NULL != aCert)
2118 {
2119 CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert);
2120 if (NULL != sha_data)
2121 {
2122 const UInt8* pSHAData = CFDataGetBytePtr(sha_data);
2123 if (NULL != pSHAData)
2124 {
2125 SecPolicyAddAnchorSHA1Options(options, pSHAData);
2126 anchorAdded = true;
2127 }
2128 }
2129 }
2130 }
2131 CFReleaseNull(anArray);
2132
2133 if (!anchorAdded)
2134 {
2135 goto errOut;
2136 }
2137
2138
2139 require(result = SecPolicyCreate(kSecPolicyOIDAppleEscrowService, options), errOut);
2140
2141 errOut:
2142 CFReleaseSafe(anArray);
2143 CFReleaseSafe(options);
2144 return result;
2145 }
2146
2147 CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreatePCSEscrowServiceSigner(void)
2148 {
2149 SecPolicyRef result = NULL;
2150 CFMutableDictionaryRef options = NULL;
2151 CFArrayRef anArray = NULL;
2152 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2153 &kCFTypeDictionaryKeyCallBacks,
2154 &kCFTypeDictionaryValueCallBacks), errOut);
2155
2156 SecPolicyAddBasicX509Options(options);
2157
2158
2159 add_ku(options, kSecKeyUsageKeyEncipherment);
2160
2161 //add_leaf_marker(options, &oidApplePolicyEscrowService);
2162 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
2163
2164
2165 Boolean anchorAdded = false;
2166 anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot);
2167 CFIndex numRoots = 0;
2168 if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray)))
2169 {
2170 goto errOut;
2171 }
2172
2173 for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++)
2174 {
2175 SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt);
2176
2177 if (NULL != aCert)
2178 {
2179 CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert);
2180 if (NULL != sha_data)
2181 {
2182 const UInt8* pSHAData = CFDataGetBytePtr(sha_data);
2183 if (NULL != pSHAData)
2184 {
2185 SecPolicyAddAnchorSHA1Options(options, pSHAData);
2186 anchorAdded = true;
2187 }
2188 }
2189 }
2190 }
2191 CFReleaseNull(anArray);
2192
2193 if (!anchorAdded)
2194 {
2195 goto errOut;
2196 }
2197
2198
2199 require(result = SecPolicyCreate(kSecPolicyOIDApplePCSEscrowService, options), errOut);
2200
2201 errOut:
2202 CFReleaseSafe(anArray);
2203 CFReleaseSafe(options);
2204 return result;
2205 }
2206 SecCertificateRef SecPolicyCopyEscrowRootCertificate(void)
2207 {
2208 SecCertificateRef result = NULL;
2209
2210 return result;
2211 }
2212
2213 SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void)
2214 {
2215 SecPolicyRef result = NULL;
2216 CFMutableDictionaryRef options = NULL;
2217 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2218 &kCFTypeDictionaryKeyCallBacks,
2219 &kCFTypeDictionaryValueCallBacks), errOut);
2220
2221 SecPolicyAddBasicX509Options(options);
2222 SecPolicyAddAppleAnchorOptions(options);
2223
2224 // Require the profile signing EKU
2225 add_eku(options, &oidAppleExtendedKeyUsageProfileSigning);
2226
2227 require(result = SecPolicyCreate(kSecPolicyOIDAppleProfileSigner, options), errOut);
2228
2229 errOut:
2230 CFReleaseSafe(options);
2231 return result;
2232 }
2233
2234
2235 SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void)
2236 {
2237 SecPolicyRef result = NULL;
2238 CFMutableDictionaryRef options = NULL;
2239 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2240 &kCFTypeDictionaryKeyCallBacks,
2241 &kCFTypeDictionaryValueCallBacks), errOut);
2242
2243 SecPolicyAddBasicX509Options(options);
2244 SecPolicyAddAppleAnchorOptions(options);
2245
2246 // Require the QA profile signing EKU
2247 add_eku(options, &oidAppleExtendedKeyUsageQAProfileSigning);
2248
2249 require(result = SecPolicyCreate(kSecPolicyOIDAppleQAProfileSigner, options), errOut);
2250
2251 errOut:
2252 CFReleaseSafe(options);
2253 return result;
2254 }
2255
2256 SecPolicyRef SecPolicyCreateOSXProvisioningProfileSigning(void)
2257 {
2258 SecPolicyRef result = NULL;
2259 CFMutableDictionaryRef options = NULL;
2260 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2261 &kCFTypeDictionaryKeyCallBacks,
2262 &kCFTypeDictionaryValueCallBacks), errOut);
2263 // Require valid chain from the Apple root
2264 SecPolicyAddBasicX509Options(options);
2265 SecPolicyAddAppleAnchorOptions(options);
2266
2267 // Require provisioning profile leaf marker OID (1.2.840.113635.100.4.11)
2268 add_leaf_marker(options, &oidAppleCertExtOSXProvisioningProfileSigning);
2269
2270 // Require intermediate marker OID (1.2.840.113635.100.6.2.1)
2271 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleWWDR);
2272
2273 // Require key usage that allows signing
2274 add_ku(options, kSecKeyUsageDigitalSignature);
2275
2276 // Ensure that revocation is checked (OCSP)
2277 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2278
2279 require(result = SecPolicyCreate(kSecPolicyOIDAppleOSXProvisioningProfileSigning, options), errOut);
2280
2281 errOut:
2282 CFReleaseSafe(options);
2283 return result;
2284 }
2285
2286
2287 SecPolicyRef SecPolicyCreateOTAPKISigner(void)
2288 {
2289 SecPolicyRef result = NULL;
2290 CFMutableDictionaryRef options = NULL;
2291 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2292 &kCFTypeDictionaryKeyCallBacks,
2293 &kCFTypeDictionaryValueCallBacks), errOut);
2294 SecPolicyAddBasicX509Options(options);
2295
2296 SecPolicyAddAnchorSHA1Options(options, kApplePKISettingsAuthority);
2297 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
2298
2299 require(result = SecPolicyCreate(kSecPolicyOIDAppleOTAPKIAssetSigner, options), errOut);
2300
2301 errOut:
2302 CFReleaseSafe(options);
2303 return result;
2304
2305 }
2306
2307
2308 SecPolicyRef SecPolicyCreateTestOTAPKISigner(void)
2309 {
2310 SecPolicyRef result = NULL;
2311 CFMutableDictionaryRef options = NULL;
2312 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2313 &kCFTypeDictionaryKeyCallBacks,
2314 &kCFTypeDictionaryValueCallBacks), errOut);
2315 SecPolicyAddBasicX509Options(options);
2316
2317 SecPolicyAddAnchorSHA1Options(options, kAppleTestPKISettingsAuthority);
2318 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
2319
2320 require(result = SecPolicyCreate(kSecPolicyOIDAppleTestOTAPKIAssetSigner, options), errOut);
2321
2322 errOut:
2323 CFReleaseSafe(options);
2324 return result;
2325 }
2326
2327 /*!
2328 @function SecPolicyCreateAppleSMPEncryption
2329 @abstract Check for intermediate certificate 'Apple System Integration CA - G3' by name,
2330 and root certificate 'Apple Root CA - G3' by hash.
2331 Leaf cert must have Key Encipherment usage.
2332 Leaf cert must have Apple SMP Encryption marker OID (1.2.840.113635.100.6.30).
2333 Intermediate must have marker OID (1.2.840.113635.100.6.2.13).
2334 */
2335 SecPolicyRef SecPolicyCreateAppleSMPEncryption(void)
2336 {
2337 SecPolicyRef result = NULL;
2338 CFMutableDictionaryRef options = NULL;
2339 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2340 &kCFTypeDictionaryKeyCallBacks,
2341 &kCFTypeDictionaryValueCallBacks), errOut);
2342 SecPolicyAddBasicCertOptions(options);
2343
2344 SecPolicyAddAnchorSHA1Options(options, kAppleRootCA_ECC_SHA1);
2345 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2346
2347 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2348 CFSTR("Apple System Integration CA - G3"));
2349
2350 // Check that leaf has extension with "Apple SMP Encryption" oid (1.2.840.113635.100.6.30)
2351 add_leaf_marker(options, &oidAppleCertExtAppleSMPEncryption);
2352
2353 // Check that intermediate has extension (1.2.840.113635.100.6.2.13)
2354 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntgG3);
2355
2356 add_ku(options, kSecKeyUsageKeyEncipherment);
2357
2358 // Ensure that revocation is checked (OCSP)
2359 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2360
2361 require(result = SecPolicyCreate(kSecPolicyAppleSMPEncryption, options), errOut);
2362
2363 errOut:
2364 CFReleaseSafe(options);
2365 return result;
2366 }
2367
2368 /*!
2369 @function SecPolicyCreateTestAppleSMPEncryption
2370 @abstract Check for intermediate certificate 'Test Apple System Integration CA - ECC' by name,
2371 and root certificate 'Test Apple Root CA - ECC' by hash.
2372 Leaf cert must have Key Encipherment usage. Other checks TBD.
2373 */
2374 SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void)
2375 {
2376 SecPolicyRef result = NULL;
2377 CFMutableDictionaryRef options = NULL;
2378 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2379 &kCFTypeDictionaryKeyCallBacks,
2380 &kCFTypeDictionaryValueCallBacks), errOut);
2381 SecPolicyAddBasicCertOptions(options);
2382
2383 SecPolicyAddAnchorSHA1Options(options, kTestAppleRootCA_ECC_SHA1);
2384 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2385
2386 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2387 CFSTR("Test Apple System Integration CA - ECC"));
2388
2389 add_ku(options, kSecKeyUsageKeyEncipherment);
2390
2391 // Ensure that revocation is checked (OCSP)
2392 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2393
2394 require(result = SecPolicyCreate(kSecPolicyAppleTestSMPEncryption, options), errOut);
2395
2396 errOut:
2397 CFReleaseSafe(options);
2398 return result;
2399 }
2400
2401
2402 SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void)
2403 {
2404 SecPolicyRef result = NULL;
2405 CFMutableDictionaryRef options = NULL;
2406 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2407 &kCFTypeDictionaryKeyCallBacks,
2408 &kCFTypeDictionaryValueCallBacks), errOut);
2409
2410 //Leaf appears to be a SSL only cert, so policy should expand on that policy
2411 SecPolicyAddBasicX509Options(options);
2412
2413 // Apple CA anchored
2414 require(SecPolicyAddAppleAnchorOptions(options), errOut);
2415
2416 // Check for an extension with " Apple ID Validation Record Signing" oid (1.2.840.113635.100.6.25)
2417 add_leaf_marker(options, &oidAppleCertExtensionAppleIDRecordValidationSigning);
2418
2419 // and validate that intermediate has extension
2420 // Application Integration Intermediate Certificate (1.2.840.113635.100.6.2.3)
2421 // and also validate that intermediate has extension
2422 // System Integration 2 Intermediate Certificate (1.2.840.113635.100.6.2.10)
2423 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID);
2424 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntg2);
2425
2426 // Ensure that revocation is checked (OCSP)
2427 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2428
2429 require(result = SecPolicyCreate(kSecPolicyOIDAppleIDValidationRecordSigningPolicy, options), errOut);
2430
2431 errOut:
2432 CFReleaseSafe(options);
2433 return result;
2434 }
2435
2436 static bool
2437 allowUATRoot(CFStringRef service, CFDictionaryRef context)
2438 {
2439 bool UATAllowed = false;
2440 if (SecIsInternalRelease()) {
2441 CFStringRef setting = CFStringCreateWithFormat(NULL, NULL, CFSTR("AppleServerAuthenticationAllowUAT%@"), service);
2442 CFTypeRef value = NULL;
2443 require(setting, fail);
2444
2445 if (context &&
2446 CFDictionaryGetValueIfPresent(context, setting, &value) &&
2447 isBoolean(value) &&
2448 CFBooleanGetValue(value))
2449 {
2450 UATAllowed = true;
2451 }
2452
2453 if (CFPreferencesGetAppBooleanValue(setting, CFSTR("com.apple.Security"), NULL)) {
2454 UATAllowed = true;
2455 }
2456 CFRelease(setting);
2457 }
2458 fail:
2459 return UATAllowed;
2460 }
2461
2462 static bool
2463 requirePinning(CFStringRef service)
2464 {
2465 bool pinningRequired = true;
2466
2467 if (SecIsInternalRelease()) {
2468 CFStringRef setting = CFStringCreateWithFormat(NULL, NULL, CFSTR("AppleServerAuthenticationNoPinning%@"), service);
2469 require(setting, fail);
2470 if (CFPreferencesGetAppBooleanValue(setting, CFSTR("com.apple.Security"), NULL))
2471 pinningRequired = false;
2472 CFRelease(setting);
2473 }
2474 fail:
2475 return pinningRequired;
2476 }
2477
2478 /*!
2479 @function SecPolicyCreateAppleServerAuthCommon
2480 @abstract Generic policy for server authentication Sub CAs
2481
2482 Allows control for both if pinning is required at all and if UAT environments should be added
2483 to the trust policy.
2484
2485 No pinning is for developer/QA that needs to use proxy to debug the protocol, while UAT
2486 environment is for QA/internal developer that have no need allow fake servers.
2487
2488 Both the noPinning and allowUAT are gated on that you run on internal hardware.
2489
2490 */
2491
2492 static SecPolicyRef
2493 SecPolicyCreateAppleServerAuthCommon(CFStringRef hostname,
2494 CFDictionaryRef __unused context,
2495 CFStringRef service,
2496 const DERItem *leafMarkerOID,
2497 const DERItem *UATLeafMarkerOID)
2498 {
2499 CFMutableDictionaryRef appleAnchorOptions = NULL;
2500 CFMutableDictionaryRef options = NULL;
2501 SecPolicyRef result = NULL;
2502 CFDataRef oid = NULL, uatoid = NULL;
2503
2504 options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2505 require(options, errOut);
2506
2507 SecPolicyAddBasicX509Options(options);
2508
2509 CFDictionaryAddValue(options, kSecPolicyCheckSSLHostname, hostname);
2510
2511 CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf, kCFBooleanTrue);
2512 CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, kCFBooleanTrue);
2513
2514 add_eku(options, &oidExtendedKeyUsageServerAuth);
2515
2516 if (requirePinning(service)) {
2517 bool allowUAT = allowUATRoot(service, context);
2518
2519 /*
2520 * Require pinning to the Apple CA's (and if UAT environment,
2521 * include the Apple Test CA's as anchors).
2522 */
2523
2524 appleAnchorOptions = CFDictionaryCreateMutableForCFTypes(NULL);
2525 require(appleAnchorOptions, errOut);
2526
2527 if (allowUAT) {
2528 CFDictionarySetValue(appleAnchorOptions,
2529 kSecPolicyAppleAnchorIncludeTestRoots, kCFBooleanTrue);
2530 }
2531
2532 add_element(options, kSecPolicyCheckAnchorApple, appleAnchorOptions);
2533
2534 /*
2535 * Check if we also should allow the UAT variant of the leafs
2536 * as some variants of the UAT environment uses that instead
2537 * of the test Apple CA's.
2538 */
2539
2540 if (allowUAT) {
2541 oid = CFDataCreate(kCFAllocatorDefault, leafMarkerOID->data, leafMarkerOID->length);
2542 require(oid, errOut);
2543
2544 uatoid = CFDataCreate(kCFAllocatorDefault, UATLeafMarkerOID->data, UATLeafMarkerOID->length);
2545 require(oid, errOut);
2546
2547 CFArrayRef array = CFArrayCreateForCFTypes(NULL, oid, uatoid, NULL);
2548 require(array, errOut);
2549
2550 add_element(options, kSecPolicyCheckLeafMarkerOid, array);
2551 CFReleaseSafe(array);
2552 } else {
2553 add_leaf_marker(options, leafMarkerOID);
2554
2555 }
2556 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleServerAuthentication);
2557 }
2558
2559
2560 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2561
2562 result = SecPolicyCreate(kSecPolicyOIDSSLServer, options);
2563 require(result, errOut);
2564
2565 errOut:
2566 CFReleaseSafe(appleAnchorOptions);
2567 CFReleaseSafe(options);
2568 CFReleaseSafe(oid);
2569 CFReleaseSafe(uatoid);
2570 return result;
2571 }
2572
2573
2574
2575 /*!
2576 @function SecPolicyCreateAppleIDSService
2577 @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions)
2578 */
2579 SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname)
2580 {
2581 #if 1
2582 return SecPolicyCreateSSL(true, hostname);
2583 #else
2584 return SecPolicyCreateAppleServerAuthCommon(hostname, NULL, CFSTR("IDS"),
2585 &oidAppleCertExtAppleServerAuthenticationIDSProd,
2586 &oidAppleCertExtAppleServerAuthenticationIDSTest);
2587 #endif
2588 }
2589
2590 /*!
2591 @function SecPolicyCreateAppleIDSService
2592 @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions)
2593 */
2594 SecPolicyRef SecPolicyCreateAppleIDSServiceContext(CFStringRef hostname, CFDictionaryRef context)
2595 {
2596 return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("IDS"),
2597 &oidAppleCertExtAppleServerAuthenticationIDSProd,
2598 &oidAppleCertExtAppleServerAuthenticationIDSTest);
2599 }
2600
2601 /*!
2602 @function SecPolicyCreateAppleGSService
2603 @abstract Ensure we're appropriately pinned to the GS service
2604 */
2605 SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef context)
2606 {
2607 return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("GS"),
2608 &oidAppleCertExtAppleServerAuthenticationGS,
2609 NULL);
2610 }
2611
2612 /*!
2613 @function SecPolicyCreateApplePushService
2614 @abstract Ensure we're appropriately pinned to the Push service (SSL + Apple restrictions)
2615 */
2616 SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname, CFDictionaryRef context)
2617 {
2618 return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("APN"),
2619 &oidAppleCertExtAppleServerAuthenticationAPNProd,
2620 &oidAppleCertExtAppleServerAuthenticationAPNTest);
2621 }
2622
2623 /*!
2624 @function SecPolicyCreateApplePPQService
2625 @abstract Ensure we're appropriately pinned to the PPQ service (SSL + Apple restrictions)
2626 */
2627 SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRef context)
2628 {
2629 return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("PPQ"),
2630 &oidAppleCertExtAppleServerAuthenticationPPQProd ,
2631 &oidAppleCertExtAppleServerAuthenticationPPQTest);
2632 }
2633
2634 /* should use verbatim copy, but since this is the deprecated way, don't care right now */
2635 static const UInt8 entrustSPKIL1C[kSecPolicySHA256Size] = {
2636 0x54, 0x5b, 0xf9, 0x35, 0xe9, 0xad, 0xa1, 0xda,
2637 0x11, 0x7e, 0xdc, 0x3c, 0x2a, 0xcb, 0xc5, 0x6f,
2638 0xc0, 0x28, 0x09, 0x6c, 0x0e, 0x24, 0xbe, 0x9b,
2639 0x38, 0x94, 0xbe, 0x52, 0x2d, 0x1b, 0x43, 0xde
2640 };
2641
2642 /*!
2643 @function SecPolicyCreateApplePushServiceLegacy
2644 @abstract Ensure we're appropriately pinned to the Push service (via Entrust)
2645 */
2646 SecPolicyRef SecPolicyCreateApplePushServiceLegacy(CFStringRef hostname)
2647 {
2648 CFMutableDictionaryRef options = NULL;
2649 SecPolicyRef result = NULL;
2650 CFDataRef digest = NULL;
2651
2652 digest = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, entrustSPKIL1C, sizeof(entrustSPKIL1C), kCFAllocatorNull);
2653 require(digest, errOut);
2654
2655 options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2656 require(options, errOut);
2657
2658 SecPolicyAddBasicX509Options(options);
2659
2660 CFDictionaryAddValue(options, kSecPolicyCheckSSLHostname, hostname);
2661
2662 CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf, kCFBooleanTrue);
2663 CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, kCFBooleanTrue);
2664
2665 CFDictionaryAddValue(options, kSecPolicyCheckIntermediateSPKISHA256, digest);
2666
2667 add_eku(options, &oidExtendedKeyUsageServerAuth);
2668
2669 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2670
2671 result = SecPolicyCreate(kSecPolicyOIDSSLServer, options);
2672 require(result, errOut);
2673
2674 errOut:
2675 CFReleaseSafe(digest);
2676 CFReleaseSafe(options);
2677 return result;
2678 }
2679
2680 /*!
2681 @function SecPolicyCreateAppleMMCSService
2682 @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions)
2683 */
2684 SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname, CFDictionaryRef __unused context)
2685 {
2686 return SecPolicyCreateSSL(true, hostname);
2687 }
2688
2689 /*!
2690 @function SecPolicyCreateAppleSSLService
2691 @abstract Ensure we're appropriately pinned to an Apple server (SSL + Apple restrictions)
2692 */
2693 SecPolicyRef SecPolicyCreateAppleSSLService(CFStringRef hostname)
2694 {
2695 // SSL server, pinned to an Apple intermediate
2696 SecPolicyRef policy = SecPolicyCreateSSL(true, hostname);
2697 CFMutableDictionaryRef options = NULL;
2698 require(policy, errOut);
2699
2700 // change options for SSL policy evaluation
2701 require((options=(CFMutableDictionaryRef)policy->_options) != NULL, errOut);
2702
2703 // Apple CA anchored
2704 require(SecPolicyAddAppleAnchorOptions(options), errOut);
2705
2706 // Check leaf for Apple Server Authentication marker oid (1.2.840.113635.100.6.27.1)
2707 add_leaf_marker(options, &oidAppleCertExtAppleServerAuthentication);
2708
2709 // Check intermediate for Apple Server Authentication intermediate marker (1.2.840.113635.100.6.2.12)
2710 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleServerAuthentication);
2711
2712 // Ensure that revocation is checked (OCSP only)
2713 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2714
2715 return policy;
2716
2717 errOut:
2718 CFReleaseSafe(options);
2719 CFReleaseSafe(policy);
2720 return NULL;
2721 }
2722
2723 /*!
2724 @function SecPolicyCreateApplePPQSigning
2725 @abstract Check for intermediate certificate 'Apple System Integration 2 Certification Authority' by name,
2726 and apple anchor.
2727 Leaf cert must have Digital Signature usage.
2728 Leaf cert must have Apple PPQ Signing marker OID (1.2.840.113635.100.6.38.2).
2729 Intermediate must have marker OID (1.2.840.113635.100.6.2.10).
2730 */
2731 SecPolicyRef SecPolicyCreateApplePPQSigning(void)
2732 {
2733 SecPolicyRef result = NULL;
2734 CFMutableDictionaryRef options = NULL;
2735 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2736 &kCFTypeDictionaryKeyCallBacks,
2737 &kCFTypeDictionaryValueCallBacks), errOut);
2738 SecPolicyAddBasicCertOptions(options);
2739
2740 SecPolicyAddAppleAnchorOptions(options);
2741 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2742
2743 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2744 CFSTR("Apple System Integration 2 Certification Authority"));
2745
2746 // Check that leaf has extension with "Apple PPQ Signing" prod oid (1.2.840.113635.100.6.38.2)
2747 add_leaf_marker(options, &oidAppleCertExtApplePPQSigningProd);
2748
2749 // Check that intermediate has extension (1.2.840.113635.100.6.2.10)
2750 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntg2);
2751
2752 add_ku(options, kSecKeyUsageDigitalSignature);
2753
2754 require(result = SecPolicyCreate(kSecPolicyApplePPQSigning, options), errOut);
2755
2756 errOut:
2757 CFReleaseSafe(options);
2758 return result;
2759 }
2760
2761 /*!
2762 @function SecPolicyCreateTestApplePPQSigning
2763 @abstract Check for intermediate certificate 'Apple System Integration 2 Certification Authority' by name,
2764 and apple anchor.
2765 Leaf cert must have Digital Signature usage.
2766 Leaf cert must have Apple PPQ Signing Test marker OID (1.2.840.113635.100.6.38.1).
2767 Intermediate must have marker OID (1.2.840.113635.100.6.2.10).
2768 */
2769 SecPolicyRef SecPolicyCreateTestApplePPQSigning(void)
2770 {
2771 SecPolicyRef result = NULL;
2772 CFMutableDictionaryRef options = NULL;
2773 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2774 &kCFTypeDictionaryKeyCallBacks,
2775 &kCFTypeDictionaryValueCallBacks), errOut);
2776 SecPolicyAddBasicCertOptions(options);
2777
2778 SecPolicyAddAppleAnchorOptions(options);
2779 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2780
2781 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2782 CFSTR("Apple System Integration 2 Certification Authority"));
2783
2784 // Check that leaf has extension with "Apple PPQ Signing" test oid (1.2.840.113635.100.6.38.1)
2785 add_leaf_marker(options, &oidAppleCertExtApplePPQSigningTest);
2786
2787 // Check that intermediate has extension (1.2.840.113635.100.6.2.10)
2788 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntg2);
2789
2790 add_ku(options, kSecKeyUsageDigitalSignature);
2791
2792 require(result = SecPolicyCreate(kSecPolicyAppleTestPPQSigning, options), errOut);
2793
2794 errOut:
2795 CFReleaseSafe(options);
2796 return result;
2797 }
2798 /*!
2799 @function SecPolicyCreateAppleTimeStamping
2800 @abstract Check for RFC3161 timestamping EKU.
2801 */
2802 SecPolicyRef SecPolicyCreateAppleTimeStamping(void)
2803 {
2804 SecPolicyRef result = NULL;
2805 CFMutableDictionaryRef options = NULL;
2806 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2807 &kCFTypeDictionaryKeyCallBacks,
2808 &kCFTypeDictionaryValueCallBacks), errOut);
2809
2810 SecPolicyAddBasicX509Options(options);
2811
2812 /* Require id-kp-timeStamping extendedKeyUsage to be present. */
2813 add_eku(options, &oidExtendedKeyUsageTimeStamping);
2814
2815 require(result = SecPolicyCreate(kSecPolicyOIDAppleTimeStamping, options), errOut);
2816
2817 errOut:
2818 CFReleaseSafe(options);
2819 return result;
2820 }
2821
2822 /*!
2823 @function SecPolicyCreateAppleATVAppSigning
2824 @abstract Check for intermediate certificate 'Apple Worldwide Developer Relations Certification Authority' by name,
2825 and apple anchor.
2826 Leaf cert must have Digital Signature usage.
2827 Leaf cert must have Apple ATV App Signing marker OID (1.2.840.113635.100.6.1.24).
2828 Leaf cert must have 'Apple TVOS Application Signing' common name.
2829 */
2830 SecPolicyRef SecPolicyCreateAppleATVAppSigning(void)
2831 {
2832 SecPolicyRef result = NULL;
2833 CFMutableDictionaryRef options = NULL;
2834 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2835 &kCFTypeDictionaryKeyCallBacks,
2836 &kCFTypeDictionaryValueCallBacks), errOut);
2837 SecPolicyAddBasicCertOptions(options);
2838
2839 require(SecPolicyAddAppleAnchorOptions(options), errOut);
2840 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2841
2842 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2843 CFSTR("Apple Worldwide Developer Relations Certification Authority"));
2844 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName,
2845 CFSTR("Apple TVOS Application Signing"));
2846
2847 // Check that leaf has extension with "Apple ATV App Signing" prod oid (1.2.840.113635.100.6.1.24)
2848 add_leaf_marker(options, &oidAppleCertExtATVAppSigningProd);
2849
2850 add_ku(options, kSecKeyUsageDigitalSignature);
2851
2852 require(result = SecPolicyCreate(kSecPolicyAppleATVAppSigning, options), errOut);
2853
2854 errOut:
2855 CFReleaseSafe(options);
2856 return result;
2857 }
2858
2859 /*!
2860 @function SecPolicyCreateTestAppleATVAppSigning
2861 @abstract Check for intermediate certificate 'Apple Worldwide Developer Relations Certification Authority' by name,
2862 and apple anchor.
2863 Leaf cert must have Digital Signature usage.
2864 Leaf cert must have Apple ATV App Signing Test marker OID (1.2.840.113635.100.6.1.24.1).
2865 Leaf cert must have 'TEST Apple TVOS Application Signing TEST' common name.
2866 */
2867 SecPolicyRef SecPolicyCreateTestAppleATVAppSigning(void)
2868 {
2869 SecPolicyRef result = NULL;
2870 CFMutableDictionaryRef options = NULL;
2871 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2872 &kCFTypeDictionaryKeyCallBacks,
2873 &kCFTypeDictionaryValueCallBacks), errOut);
2874 SecPolicyAddBasicCertOptions(options);
2875
2876 require(SecPolicyAddAppleAnchorOptions(options), errOut);
2877 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2878
2879 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2880 CFSTR("Apple Worldwide Developer Relations Certification Authority"));
2881 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName,
2882 CFSTR("TEST Apple TVOS Application Signing TEST"));
2883
2884 // Check that leaf has extension with "Apple ATV App Signing" test oid (1.2.840.113635.100.6.1.24.1)
2885 add_leaf_marker(options, &oidAppleCertExtATVAppSigningTest);
2886
2887 add_ku(options, kSecKeyUsageDigitalSignature);
2888
2889 require(result = SecPolicyCreate(kSecPolicyAppleTestATVAppSigning, options), errOut);
2890
2891 errOut:
2892 CFReleaseSafe(options);
2893 return result;
2894 }
2895
2896 /*!
2897 @function SecPolicyCreateApplePayIssuerEncryption
2898 @abstract Check for intermediate certificate 'Apple Worldwide Developer Relations CA - G2' by name,
2899 and ECC apple anchor.
2900 Leaf cert must have Key Encipherment and Key Agreement usage.
2901 Leaf cert must have Apple Pay Issuer Encryption marker OID (1.2.840.113635.100.6.39).
2902 */
2903 SecPolicyRef SecPolicyCreateApplePayIssuerEncryption(void)
2904 {
2905 SecPolicyRef result = NULL;
2906 CFMutableDictionaryRef options = NULL;
2907 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2908 &kCFTypeDictionaryKeyCallBacks,
2909 &kCFTypeDictionaryValueCallBacks), errOut);
2910 SecPolicyAddBasicCertOptions(options);
2911
2912 require(SecPolicyAddAnchorSHA1Options(options, kAppleRootCA_ECC_SHA1), errOut);
2913 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2914
2915 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2916 CFSTR("Apple Worldwide Developer Relations CA - G2"));
2917
2918 // Check that leaf has extension with "Apple Pay Issuer Encryption" oid (1.2.840.113635.100.6.39)
2919 add_leaf_marker(options, &oidAppleCertExtCryptoServicesExtEncryption);
2920
2921 add_ku(options, kSecKeyUsageKeyEncipherment);
2922
2923 require(result = SecPolicyCreate(kSecPolicyApplePayIssuerEncryption, options), errOut);
2924
2925 errOut:
2926 CFReleaseSafe(options);
2927 return result;
2928 }
2929
2930 /*!
2931 @function SecPolicyCreateAppleATVVPNProfileSigning
2932 @abstract Check for leaf marker OID 1.2.840.113635.100.6.43,
2933 intermediate marker OID 1.2.840.113635.100.6.2.10,
2934 chains to Apple Root CA, path length 3
2935 */
2936 SecPolicyRef SecPolicyCreateAppleATVVPNProfileSigning(void)
2937 {
2938 SecPolicyRef result = NULL;
2939 CFMutableDictionaryRef options = NULL;
2940 CFMutableDictionaryRef appleAnchorOptions = NULL;
2941 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2942 &kCFTypeDictionaryKeyCallBacks,
2943 &kCFTypeDictionaryValueCallBacks), errOut);
2944
2945 SecPolicyAddBasicCertOptions(options);
2946
2947 // Require pinning to the Apple CAs (including test CA for internal releases)
2948 appleAnchorOptions = CFDictionaryCreateMutableForCFTypes(NULL);
2949 require(appleAnchorOptions, errOut);
2950
2951 if (SecIsInternalRelease()) {
2952 CFDictionarySetValue(appleAnchorOptions,
2953 kSecPolicyAppleAnchorIncludeTestRoots, kCFBooleanTrue);
2954 }
2955
2956 add_element(options, kSecPolicyCheckAnchorApple, appleAnchorOptions);
2957
2958 // Cert chain length 3
2959 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2960
2961 // Check leaf for Apple ATV VPN Profile Signing OID (1.2.840.113635.100.6.43)
2962 add_leaf_marker(options, &oidAppleCertExtATVVPNProfileSigning);
2963
2964 // Check intermediate for Apple System Integration 2 CA intermediate marker (1.2.840.113635.100.6.2.10)
2965 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntg2);
2966
2967 // Ensure that revocation is checked (OCSP only)
2968 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2969
2970 require(result = SecPolicyCreate(kSecPolicyAppleATVVPNProfileSigning, options), errOut);
2971
2972 errOut:
2973 CFReleaseSafe(options);
2974 CFReleaseSafe(appleAnchorOptions);
2975 return result;
2976 }