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