]> git.saurik.com Git - apple/security.git/blob - Security/sec/Security/SecPolicy.c
7cf760f5f298af7796004881e2602bc352476841
[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 SecPolicyAddBasicX509Options(options);
1789
1790
1791 add_ku(options, kSecKeyUsageKeyEncipherment);
1792
1793 //add_leaf_marker(options, &oidApplePolicyEscrowService);
1794 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
1795
1796
1797 Boolean anchorAdded = false;
1798 // Get the roots by calling the SecCertificateCopyEscrowRoots
1799 anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot);
1800 CFIndex numRoots = 0;
1801 if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray)))
1802 {
1803 goto errOut;
1804 }
1805
1806 for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++)
1807 {
1808 SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt);
1809
1810 if (NULL != aCert)
1811 {
1812 CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert);
1813 if (NULL != sha_data)
1814 {
1815 const UInt8* pSHAData = CFDataGetBytePtr(sha_data);
1816 if (NULL != pSHAData)
1817 {
1818 SecPolicyAddAnchorSHA1Options(options, pSHAData);
1819 anchorAdded = true;
1820 }
1821 }
1822 }
1823 }
1824 CFReleaseNull(anArray);
1825
1826 if (!anchorAdded)
1827 {
1828 goto errOut;
1829 }
1830
1831
1832 require(result = SecPolicyCreate(kSecPolicyOIDAppleEscrowService, options), errOut);
1833
1834 errOut:
1835 CFReleaseSafe(anArray);
1836 CFReleaseSafe(options);
1837 return result;
1838 }
1839
1840 CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreatePCSEscrowServiceSigner(void)
1841 {
1842 SecPolicyRef result = NULL;
1843 CFMutableDictionaryRef options = NULL;
1844 CFArrayRef anArray = NULL;
1845 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1846 &kCFTypeDictionaryKeyCallBacks,
1847 &kCFTypeDictionaryValueCallBacks), errOut);
1848
1849 SecPolicyAddBasicX509Options(options);
1850
1851
1852 add_ku(options, kSecKeyUsageKeyEncipherment);
1853
1854 //add_leaf_marker(options, &oidApplePolicyEscrowService);
1855 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
1856
1857
1858 Boolean anchorAdded = false;
1859 anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot);
1860 CFIndex numRoots = 0;
1861 if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray)))
1862 {
1863 goto errOut;
1864 }
1865
1866 for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++)
1867 {
1868 SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt);
1869
1870 if (NULL != aCert)
1871 {
1872 CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert);
1873 if (NULL != sha_data)
1874 {
1875 const UInt8* pSHAData = CFDataGetBytePtr(sha_data);
1876 if (NULL != pSHAData)
1877 {
1878 SecPolicyAddAnchorSHA1Options(options, pSHAData);
1879 anchorAdded = true;
1880 }
1881 }
1882 }
1883 }
1884 CFReleaseNull(anArray);
1885
1886 if (!anchorAdded)
1887 {
1888 goto errOut;
1889 }
1890
1891
1892 require(result = SecPolicyCreate(kSecPolicyOIDApplePCSEscrowService, options), errOut);
1893
1894 errOut:
1895 CFReleaseSafe(anArray);
1896 CFReleaseSafe(options);
1897 return result;
1898 }
1899 SecCertificateRef SecPolicyCopyEscrowRootCertificate(void)
1900 {
1901 SecCertificateRef result = NULL;
1902
1903 return result;
1904 }
1905
1906 SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void)
1907 {
1908 SecPolicyRef result = NULL;
1909 CFMutableDictionaryRef options = NULL;
1910 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1911 &kCFTypeDictionaryKeyCallBacks,
1912 &kCFTypeDictionaryValueCallBacks), errOut);
1913
1914 SecPolicyAddBasicX509Options(options);
1915 SecPolicyAddAppleAnchorOptions(options);
1916
1917 // Require the profile signing EKU
1918 add_eku(options, &oidAppleExtendedKeyUsageProfileSigning);
1919
1920 require(result = SecPolicyCreate(kSecPolicyOIDAppleProfileSigner, options), errOut);
1921
1922 errOut:
1923 CFReleaseSafe(options);
1924 return result;
1925 }
1926
1927
1928 SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void)
1929 {
1930 SecPolicyRef result = NULL;
1931 CFMutableDictionaryRef options = NULL;
1932 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1933 &kCFTypeDictionaryKeyCallBacks,
1934 &kCFTypeDictionaryValueCallBacks), errOut);
1935
1936 SecPolicyAddBasicX509Options(options);
1937 SecPolicyAddAppleAnchorOptions(options);
1938
1939 // Require the QA profile signing EKU
1940 add_eku(options, &oidAppleExtendedKeyUsageQAProfileSigning);
1941
1942 require(result = SecPolicyCreate(kSecPolicyOIDAppleQAProfileSigner, options), errOut);
1943
1944 errOut:
1945 CFReleaseSafe(options);
1946 return result;
1947 }
1948
1949 #if TARGET_OS_IPHONE
1950 SecPolicyRef SecPolicyCreateOTAPKISigner(void)
1951 {
1952 SecPolicyRef result = NULL;
1953 CFMutableDictionaryRef options = NULL;
1954 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1955 &kCFTypeDictionaryKeyCallBacks,
1956 &kCFTypeDictionaryValueCallBacks), errOut);
1957 SecPolicyAddBasicX509Options(options);
1958
1959 SecPolicyAddAnchorSHA1Options(options, kApplePKISettingsAuthority);
1960 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
1961
1962 require(result = SecPolicyCreate(kSecPolicyOIDAppleOTAPKIAssetSigner, options), errOut);
1963
1964 errOut:
1965 CFReleaseSafe(options);
1966 return result;
1967
1968 }
1969
1970
1971 SecPolicyRef SecPolicyCreateTestOTAPKISigner(void)
1972 {
1973 SecPolicyRef result = NULL;
1974 CFMutableDictionaryRef options = NULL;
1975 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1976 &kCFTypeDictionaryKeyCallBacks,
1977 &kCFTypeDictionaryValueCallBacks), errOut);
1978 SecPolicyAddBasicX509Options(options);
1979
1980 SecPolicyAddAnchorSHA1Options(options, kAppleTestPKISettingsAuthority);
1981 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
1982
1983 require(result = SecPolicyCreate(kSecPolicyOIDAppleTestOTAPKIAssetSigner, options), errOut);
1984
1985 errOut:
1986 CFReleaseSafe(options);
1987 return result;
1988 }
1989
1990 /*!
1991 @function SecPolicyCreateAppleSMPEncryption
1992 @abstract Check for intermediate certificate 'Apple System Integration CA - G3' by name,
1993 and root certificate 'Apple Root CA - G3' by hash.
1994 Leaf cert must have Key Encipherment usage.
1995 Leaf cert must have Apple SMP Encryption marker OID (1.2.840.113635.100.6.30).
1996 Intermediate must have marker OID (1.2.840.113635.100.6.2.13).
1997 */
1998 SecPolicyRef SecPolicyCreateAppleSMPEncryption(void)
1999 {
2000 SecPolicyRef result = NULL;
2001 CFMutableDictionaryRef options = NULL;
2002 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2003 &kCFTypeDictionaryKeyCallBacks,
2004 &kCFTypeDictionaryValueCallBacks), errOut);
2005 SecPolicyAddBasicCertOptions(options);
2006
2007 SecPolicyAddAnchorSHA1Options(options, kAppleRootCA_ECC_SHA1);
2008 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2009
2010 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2011 CFSTR("Apple System Integration CA - G3"));
2012
2013 // Check that leaf has extension with "Apple SMP Encryption" oid (1.2.840.113635.100.6.30)
2014 add_leaf_marker(options, &oidAppleCertExtAppleSMPEncryption);
2015
2016 // Check that intermediate has extension (1.2.840.113635.100.6.2.13)
2017 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntgG3);
2018
2019 add_ku(options, kSecKeyUsageKeyEncipherment);
2020
2021 // Ensure that revocation is checked (OCSP)
2022 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2023
2024 require(result = SecPolicyCreate(kSecPolicyAppleSMPEncryption, options), errOut);
2025
2026 errOut:
2027 CFReleaseSafe(options);
2028 return result;
2029 }
2030
2031 /*!
2032 @function SecPolicyCreateTestAppleSMPEncryption
2033 @abstract Check for intermediate certificate 'Test Apple System Integration CA - ECC' by name,
2034 and root certificate 'Test Apple Root CA - ECC' by hash.
2035 Leaf cert must have Key Encipherment usage. Other checks TBD.
2036 */
2037 SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void)
2038 {
2039 SecPolicyRef result = NULL;
2040 CFMutableDictionaryRef options = NULL;
2041 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2042 &kCFTypeDictionaryKeyCallBacks,
2043 &kCFTypeDictionaryValueCallBacks), errOut);
2044 SecPolicyAddBasicCertOptions(options);
2045
2046 SecPolicyAddAnchorSHA1Options(options, kTestAppleRootCA_ECC_SHA1);
2047 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
2048
2049 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
2050 CFSTR("Test Apple System Integration CA - ECC"));
2051
2052 add_ku(options, kSecKeyUsageKeyEncipherment);
2053
2054 // Ensure that revocation is checked (OCSP)
2055 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2056
2057 require(result = SecPolicyCreate(kSecPolicyAppleTestSMPEncryption, options), errOut);
2058
2059 errOut:
2060 CFReleaseSafe(options);
2061 return result;
2062 }
2063
2064
2065 SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void)
2066 {
2067 SecPolicyRef result = NULL;
2068 CFMutableDictionaryRef options = NULL;
2069 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2070 &kCFTypeDictionaryKeyCallBacks,
2071 &kCFTypeDictionaryValueCallBacks), errOut);
2072
2073 //Leaf appears to be a SSL only cert, so policy should expand on that policy
2074 SecPolicyAddBasicX509Options(options);
2075
2076 // Apple CA anchored
2077 require(SecPolicyAddAppleAnchorOptions(options), errOut);
2078
2079 // Check for an extension with " Apple ID Validation Record Signing" oid (1.2.840.113635.100.6.25)
2080 add_leaf_marker(options, &oidAppleCertExtensionAppleIDRecordValidationSigning);
2081
2082 // and validate that intermediate has extension
2083 // Application Integration Intermediate Certificate (1.2.840.113635.100.6.2.3)
2084 // and also validate that intermediate has extension
2085 // System Integration 2 Intermediate Certificate (1.2.840.113635.100.6.2.10)
2086 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID);
2087 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntg2);
2088
2089 // Ensure that revocation is checked (OCSP)
2090 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2091
2092 require(result = SecPolicyCreate(kSecPolicyOIDAppleIDValidationRecordSigningPolicy, options), errOut);
2093
2094 errOut:
2095 CFReleaseSafe(options);
2096 return result;
2097 }
2098
2099 /*!
2100 @function SecPolicyCreateAppleIDSService
2101 @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions)
2102 */
2103 SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname)
2104 {
2105 return SecPolicyCreateSSL(true, hostname);
2106 }
2107
2108 /*!
2109 @function SecPolicyCreateApplePushService
2110 @abstract Ensure we're appropriately pinned to the Push service (SSL + Apple restrictions)
2111 */
2112 SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname)
2113 {
2114 return SecPolicyCreateSSL(true, hostname);
2115 }
2116
2117 /*!
2118 @function SecPolicyCreateAppleMMCSService
2119 @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions)
2120 */
2121 SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname)
2122 {
2123 return SecPolicyCreateSSL(true, hostname);
2124 }
2125
2126 /*!
2127 @function SecPolicyCreateAppleSSLService
2128 @abstract Ensure we're appropriately pinned to an Apple server (SSL + Apple restrictions)
2129 */
2130 SecPolicyRef SecPolicyCreateAppleSSLService(CFStringRef hostname)
2131 {
2132 // SSL server, pinned to an Apple intermediate
2133 SecPolicyRef policy = SecPolicyCreateSSL(true, hostname);
2134 CFMutableDictionaryRef options = NULL;
2135 require(policy, errOut);
2136
2137 // change options for SSL policy evaluation
2138 require((options=(CFMutableDictionaryRef)policy->_options) != NULL, errOut);
2139
2140 // Apple CA anchored
2141 require(SecPolicyAddAppleAnchorOptions(options), errOut);
2142
2143 // Check leaf for Apple Server Authentication marker oid (1.2.840.113635.100.6.27.1)
2144 add_leaf_marker(options, &oidAppleCertExtAppleServerAuthentication);
2145
2146 // Check intermediate for Apple Server Authentication intermediate marker (1.2.840.113635.100.6.2.12)
2147 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleServerAuthentication);
2148
2149 // Ensure that revocation is checked (OCSP only)
2150 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
2151
2152 return policy;
2153
2154 errOut:
2155 CFReleaseSafe(options);
2156 CFReleaseSafe(policy);
2157 return NULL;
2158 }
2159
2160 #endif // TARGET_OS_IPHONE