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