]> git.saurik.com Git - apple/security.git/blob - sec/Security/SecPolicy.c
Security-55471.14.tar.gz
[apple/security.git] / sec / Security / SecPolicy.c
1 /*
2 * Copyright (c) 2007-2013 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 <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 SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113625.100.1.30");
193 #endif
194
195 SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid");
196 SEC_CONST_DECL (kSecPolicyName, "SecPolicyName");
197 SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient");
198 SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags");
199 SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier");
200
201 /* Private policy names */
202 static CFStringRef kSecPolicyOIDBasicX509 = CFSTR("basicX509");
203 static CFStringRef kSecPolicyOIDSSLServer = CFSTR("sslServer");
204 static CFStringRef kSecPolicyOIDSSLClient = CFSTR("sslClient");
205 static CFStringRef kSecPolicyOIDiPhoneActivation = CFSTR("iPhoneActivation");
206 static CFStringRef kSecPolicyOIDiPhoneDeviceCertificate =
207 CFSTR("iPhoneDeviceCertificate");
208 static CFStringRef kSecPolicyOIDFactoryDeviceCertificate =
209 CFSTR("FactoryDeviceCertificate");
210 static CFStringRef kSecPolicyOIDiAP = CFSTR("iAP");
211 static CFStringRef kSecPolicyOIDiTunesStoreURLBag = CFSTR("iTunesStoreURLBag");
212 static CFStringRef kSecPolicyEAPServer = CFSTR("eapServer");
213 static CFStringRef kSecPolicyEAPClient = CFSTR("eapClient");
214 static CFStringRef kSecPolicyOIDIPSecServer = CFSTR("ipsecServer");
215 static CFStringRef kSecPolicyOIDIPSecClient = CFSTR("ipsecClient");
216 static CFStringRef kSecPolicyOIDiPhoneApplicationSigning =
217 CFSTR("iPhoneApplicationSigning");
218 static CFStringRef kSecPolicyOIDiPhoneProfileApplicationSigning =
219 CFSTR("iPhoneProfileApplicationSigning");
220 static CFStringRef kSecPolicyOIDiPhoneProvisioningProfileSigning =
221 CFSTR("iPhoneProvisioningProfileSigning");
222 static CFStringRef kSecPolicyOIDRevocation = CFSTR("revocation");
223 static CFStringRef kSecPolicyOIDOCSPSigner = CFSTR("OCSPSigner");
224 static CFStringRef kSecPolicyOIDSMIME = CFSTR("SMIME");
225 static CFStringRef kSecPolicyOIDCodeSigning = CFSTR("CodeSigning");
226 static CFStringRef kSecPolicyOIDLockdownPairing = CFSTR("LockdownPairing");
227 static CFStringRef kSecPolicyOIDURLBag = CFSTR("URLBag");
228 static CFStringRef kSecPolicyOIDOTATasking = CFSTR("OTATasking");
229 static CFStringRef kSecPolicyOIDMobileAsset = CFSTR("MobileAsset");
230 static CFStringRef kSecPolicyOIDAppleIDAuthority = CFSTR("AppleIDAuthority");
231 static CFStringRef kSecPolicyOIDAppleShoebox = CFSTR("AppleShoebox");
232 static CFStringRef kSecPolicyOIDApplePassbook = CFSTR("ApplePassbook");
233 static CFStringRef kSecPolicyOIDAppleMobileStore = CFSTR("AppleMobileStore");
234 static CFStringRef kSecPolicyOIDAppleTestMobileStore = CFSTR("AppleTestMobileStore");
235 static CFStringRef kSecPolicyOIDAppleEscrowService = CFSTR("AppleEscrowService");
236 static CFStringRef kSecPolicyOIDAppleProfileSigner = CFSTR("AppleProfileSigner");
237 static CFStringRef kSecPolicyOIDAppleQAProfileSigner = CFSTR("AppleQAProfileSigner");
238 static CFStringRef kSecPolicyOIDAppleOTAPKIAssetSigner = CFSTR("AppleOTAPKIAssetSigner");
239 static CFStringRef kSecPolicyOIDAppleTestOTAPKIAssetSigner = CFSTR("AppleTestOTAPKIAssetSigner");
240 static CFStringRef kSecPolicyOIDAppleIDValidationRecordSigningPolicy = CFSTR("AppleIDValidationRecordSigningPolicy");
241
242
243 /* Policies will now change to multiple categories of checks.
244
245 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.
246 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.
247
248 kSecPolicySLCheck Static Subscriber Certificate Checks
249 kSecPolicySICheck Static Subsidiary CA Checks
250 kSecPolicySACheck Static Anchor Checks
251
252 kSecPolicyDLCheck Dynamic Subscriber Certificate Checks
253 kSecPolicyDICheck Dynamic Subsidiary CA Checks
254 kSecPolicyDACheck Dynamic Anchor Checks ? not yet needed other than to
255 possibly exclude in a exception template (but those should still be per
256 certificate --- i.o.w. exceptions (or a database backed multiple role/user
257 trust store of some sort) and policies are 2 different things and this
258 text is about policies.
259
260 All static checks are only allowed to consider the certificate in isolation,
261 just given the position in the chain or the cert (leaf, intermidate, root).
262 dynamic checks can make determinations about the chain as a whole.
263
264 Static Subscriber Certificate Checks will be done up front before the
265 chainbuilder is even instantiated. If they fail and details aren't required
266 by the client (if no exceptions were present for this certificate) we could
267 short circuit fail the evaluation.
268 IDEA: These checks can dynamically add new checks...[needs work]
269 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
270 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
271 equivalent subtree from that level down. So SSL has EV as a subpolicy, but
272 EV dynamically enables the ocsp or crl or dcrl or any combination thereof subpolicies.
273
274 Static Subsidiary CA Checks will be used by the chain-builder to choose the
275 best parents to evaluate first. This feature is currently already implemented
276 but with a hardcoded is_valid(verifyTime) check. Instead we will evaluate all
277 Static Subsidiary CA Checks. The results of these checks for purposes of
278 generating details could be cached in the SecCertificatePathRefs themselves, or we can short circuit fail and recalc details on demand later.
279
280 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.
281
282 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.
283
284 Dynamic Subsidiary CA Checks might not be needed to have custom
285 implementations, since they are all done as part of the rfc5280 checks now.
286 This assumes that checks like issuer common name includes 'foo' are
287 implmented as Static Subscriber Certificate Checks instead.
288
289 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.
290
291
292 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.
293
294 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.
295
296 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.
297
298 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.
299
300 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.
301
302 We need to remember the best successful chain we find, where best is defined by: satisfies as many optional policies as possible.
303
304 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.
305
306 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.
307
308 Example sectrust operation in psuedocode:
309 */
310 #if 0
311 {
312 new builder(verifyTime, certificates, anchors, anchorsOnly, policies);
313 chain = builder.subscriber_only_chain;
314 foreach (policy in policies{kSecPolicySLCheck}) {
315 foreach(check in policy)
316 SecPolicyRunCheck(builder, chain, check, details);
317 foreach (subpolicy in policy) {
318 check_policy(builder, chain, subpolicy, details{subpolicy.name})
319 }
320 propagate_subpolicy_results(builder, chain, details);
321 }
322 while (chain = builder.next) {
323 for (depth = 0; p_d = policies.at_depth(depth),
324 d_p_d = dynamic_policies.at_depth(depth), p_d || d_p_d; ++depth)
325 {
326 /* Modify SecPathBuilderIsPartial() to
327 run builder_check(buildier, policies, kSecPolicySICheck) instead
328 of SecCertificateIsValid. Also rename considerExpired to
329 considerSIFailures.
330 */
331 foreach (policy in p_d) {
332 check_policy(builder, chain, policy, kSecPolicySICheck, depth);
333 }
334 /* Recalculate since the static checks might have added new dynamic
335 policies. */
336 d_p_d = dynamic_policies.at_depth(depth);
337 foreach (policy in d_p_d) {
338 check_policy(builder, chain, policy, kSecPolicySICheck, depth);
339 }
340 if (chain.is_anchored) {
341 foreach (policy in p_d) {
342 check_policy(builder, chain, policy, kSecPolicySACheck, depth);
343 }
344 foreach (policy in d_p_d) {
345 check_policy(builder, chain, policy, kSecPolicySACheck, depth);
346 }
347 foreach (policy in p_d) {
348 check_policy(builder, chain, policy, kSecPolicyDACheck, depth);
349 }
350 foreach (policy in d_p_d) {
351 check_policy(builder, chain, policy, kSecPolicyDACheck, depth);
352 }
353 }
354 foreach (policy in policies) {
355 check_policy(builder, chain, policy, kSecPolicySACheck, depth);
356 check_policy(builder, chain, policy, kSecPolicyDACheck, depth);
357 }
358 foreach (policy in policies{kSecPolicySDCheck}) {
359 }
360 }
361 }
362
363 check_policy(builder, chain, policy, check_class, details, depth) {
364 if (depth == 0) {
365 foreach(check in policy{check_class}) {
366 SecPolicyRunCheck(builder, chain, check, details);
367 }
368 } else {
369 depth--;
370 foreach (subpolicy in policy) {
371 if (!check_policy(builder, chain, subpolicy, check_class,
372 details{subpolicy.name}) && subpolicy.is_required, depth)
373 secpvcsetresult()
374 }
375 }
376 propagate_subpolicy_results(builder, chain, details);
377 }
378
379 #endif
380
381
382
383 #define kSecPolicySHA1Size 20
384 const UInt8 kAppleCASHA1[kSecPolicySHA1Size] = {
385 0x61, 0x1E, 0x5B, 0x66, 0x2C, 0x59, 0x3A, 0x08, 0xFF, 0x58,
386 0xD1, 0x4A, 0xE2, 0x24, 0x52, 0xD1, 0x98, 0xDF, 0x6C, 0x60
387 };
388
389 static const UInt8 kAppleTESTCASHA1[kSecPolicySHA1Size] = {
390 0xbc, 0x30, 0x55, 0xc8, 0xc8, 0xd3, 0x48, 0x3f, 0xf4, 0x8d,
391 0xfe, 0x3d, 0x51, 0x75, 0x31, 0xc9, 0xf4, 0xd7, 0x4a, 0xf7
392 };
393
394 static const UInt8 kITMSCASHA1[kSecPolicySHA1Size] = {
395 0x1D, 0x33, 0x42, 0x46, 0x8B, 0x10, 0xBD, 0xE6, 0x45, 0xCE,
396 0x44, 0x6E, 0xBB, 0xE8, 0xF5, 0x03, 0x5D, 0xF8, 0x32, 0x22
397 };
398
399 static const UInt8 kFactoryDeviceCASHA1[kSecPolicySHA1Size] = {
400 0xef, 0x68, 0x73, 0x17, 0xa4, 0xf8, 0xf9, 0x4b, 0x7b, 0x21,
401 0xe2, 0x2f, 0x09, 0x8f, 0xfd, 0x6a, 0xae, 0xc0, 0x0d, 0x63
402 };
403
404 static const UInt8 kApplePKISettingsAuthority[kSecPolicySHA1Size] = {
405 0x1D, 0x0C, 0xBA, 0xAD, 0x17, 0xFD, 0x7E, 0x9E, 0x9F, 0xF1,
406 0xC9, 0xA2, 0x66, 0x79, 0x60, 0x00, 0x8B, 0xAE, 0x70, 0xB8
407 };
408
409 static const UInt8 kAppleTestPKISettingsAuthority[kSecPolicySHA1Size] = {
410 0xDB, 0xBA, 0x25, 0x0B, 0xD8, 0x62, 0x71, 0x87, 0x54, 0x7E,
411 0xD7, 0xEF, 0x11, 0x94, 0x7E, 0x82, 0xE6, 0xD8, 0x1C, 0x9A
412 };
413
414 // MARK: -
415 // MARK: SecPolicy
416 /********************************************************
417 ****************** SecPolicy object ********************
418 ********************************************************/
419
420 /* CFRuntime registration data. */
421 static pthread_once_t kSecPolicyRegisterClass = PTHREAD_ONCE_INIT;
422 static CFTypeID kSecPolicyTypeID = _kCFRuntimeNotATypeID;
423
424 static void SecPolicyDestroy(CFTypeRef cf) {
425 SecPolicyRef policy = (SecPolicyRef) cf;
426 CFRelease(policy->_oid);
427 CFRelease(policy->_options);
428 }
429
430 static Boolean SecPolicyEqual(CFTypeRef cf1, CFTypeRef cf2) {
431 SecPolicyRef policy1 = (SecPolicyRef) cf1;
432 SecPolicyRef policy2 = (SecPolicyRef) cf2;
433 return CFEqual(policy1->_oid, policy2->_oid) &&
434 CFEqual(policy1->_options, policy2->_options);
435 }
436
437 static CFHashCode SecPolicyHash(CFTypeRef cf) {
438 SecPolicyRef policy = (SecPolicyRef) cf;
439
440 return CFHash(policy->_oid) + CFHash(policy->_options);
441 }
442
443 static CF_RETURNS_RETAINED CFStringRef SecPolicyDescribe(CFTypeRef cf) {
444 SecPolicyRef policy = (SecPolicyRef) cf;
445 CFMutableStringRef desc = CFStringCreateMutable(kCFAllocatorDefault, 0);
446 CFStringRef typeStr = CFCopyTypeIDDescription(CFGetTypeID(cf));
447 CFStringAppendFormat(desc, NULL,
448 CFSTR("<%@: oid: %@ options %@"), typeStr,
449 policy->_oid, policy->_options);
450 CFRelease(typeStr);
451 CFStringAppend(desc, CFSTR(" >"));
452
453 return desc;
454 }
455
456 static void SecPolicyRegisterClass(void) {
457 static const CFRuntimeClass kSecPolicyClass = {
458 0, /* version */
459 "SecPolicy", /* class name */
460 NULL, /* init */
461 NULL, /* copy */
462 SecPolicyDestroy, /* dealloc */
463 SecPolicyEqual, /* equal */
464 SecPolicyHash, /* hash */
465 NULL, /* copyFormattingDesc */
466 SecPolicyDescribe /* copyDebugDesc */
467 };
468
469 kSecPolicyTypeID = _CFRuntimeRegisterClass(&kSecPolicyClass);
470 }
471
472 /* SecPolicy API functions. */
473 CFTypeID SecPolicyGetTypeID(void) {
474 pthread_once(&kSecPolicyRegisterClass, SecPolicyRegisterClass);
475 return kSecPolicyTypeID;
476 }
477
478 /* AUDIT[securityd](done):
479 oid (ok) is a caller provided string, only its cf type has been checked.
480 options is a caller provided dictionary, only its cf type has been checked.
481 */
482 SecPolicyRef SecPolicyCreate(CFStringRef oid, CFDictionaryRef options) {
483 SecPolicyRef result = NULL;
484
485 require(oid, errOut);
486 require(options, errOut);
487 require(result =
488 (SecPolicyRef)_CFRuntimeCreateInstance(kCFAllocatorDefault,
489 SecPolicyGetTypeID(),
490 sizeof(struct __SecPolicy) - sizeof(CFRuntimeBase), 0), errOut);
491
492 CFRetain(oid);
493 result->_oid = oid;
494 CFRetain(options);
495 result->_options = options;
496
497 errOut:
498 return result;
499 }
500
501 SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier,
502 CFDictionaryRef properties) {
503 // Creates a policy reference for a given policy object identifier.
504 // If policy-specific parameters can be supplied (e.g. hostname),
505 // attempt to obtain from input properties dictionary.
506 // Returns NULL if the given identifier is unsupported.
507
508 SecPolicyRef policy = NULL;
509 CFStringRef name = NULL;
510 CFStringRef teamID = NULL;
511 Boolean client = false;
512 require(policyIdentifier && (CFStringGetTypeID() == CFGetTypeID(policyIdentifier)), errOut);
513
514 if (properties) {
515 name = CFDictionaryGetValue(properties, kSecPolicyName);
516 teamID = CFDictionaryGetValue(properties, kSecPolicyTeamIdentifier);
517
518 CFBooleanRef dictionaryClientValue;
519 client = (CFDictionaryGetValueIfPresent(properties, kSecPolicyClient, (const void **)&dictionaryClientValue) &&
520 (dictionaryClientValue != NULL) && CFEqual(kCFBooleanTrue, dictionaryClientValue));
521 }
522
523 if (CFEqual(policyIdentifier, kSecPolicyAppleX509Basic)) {
524 policy = SecPolicyCreateBasicX509();
525 }
526 else if (CFEqual(policyIdentifier, kSecPolicyAppleSSL)) {
527 policy = SecPolicyCreateSSL(!client, name);
528 }
529 else if (CFEqual(policyIdentifier, kSecPolicyAppleEAP)) {
530 CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, (const void **)&name, 1,
531 &kCFTypeArrayCallBacks);
532 policy = SecPolicyCreateEAP(!client, array);
533 CFReleaseSafe(array);
534 }
535 else if (CFEqual(policyIdentifier, kSecPolicyAppleIPsec)) {
536 policy = SecPolicyCreateIPSec(!client, name);
537 }
538 else if (CFEqual(policyIdentifier, kSecPolicyAppleRevocation)) {
539 policy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod);
540 }
541 else if (CFEqual(policyIdentifier, kSecPolicyAppleSMIME)) {
542 policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, name);
543 }
544 else if (CFEqual(policyIdentifier, kSecPolicyAppleCodeSigning)) {
545 policy = SecPolicyCreateCodeSigning();
546 }
547 else if (CFEqual(policyIdentifier, kSecPolicyAppleIDValidation)) {
548 policy = SecPolicyCreateAppleIDAuthorityPolicy();
549 }
550 else if (CFEqual(policyIdentifier, kSecPolicyApplePassbookSigning)) {
551 policy = SecPolicyCreatePassbookCardSigner(name, teamID);
552 }
553 else if (CFEqual(policyIdentifier, kSecPolicyAppleMobileStore)) {
554 policy = SecPolicyCreateMobileStoreSigner();
555 }
556 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestMobileStore)) {
557 policy = SecPolicyCreateTestMobileStoreSigner();
558 }
559 else if (CFEqual(policyIdentifier, kSecPolicyAppleEscrowService)) {
560 policy = SecPolicyCreateEscrowServiceSigner();
561 }
562 else if (CFEqual(policyIdentifier, kSecPolicyAppleProfileSigner)) {
563 policy = SecPolicyCreateConfigurationProfileSigner();
564 }
565 else if (CFEqual(policyIdentifier, kSecPolicyAppleQAProfileSigner)) {
566 policy = SecPolicyCreateQAConfigurationProfileSigner();
567 }
568 #if TARGET_OS_IPHONE
569 else if (CFEqual(policyIdentifier, kSecPolicyAppleOTAPKISigner)) {
570 policy = SecPolicyCreateOTAPKISigner();
571 }
572 else if (CFEqual(policyIdentifier, kSecPolicyAppleTestOTAPKISigner)) {
573 policy = SecPolicyCreateTestOTAPKISigner();
574 }
575 else if (CFEqual(policyIdentifier, kSecPolicyAppleIDValidationRecordSigningPolicy)) {
576 policy = SecPolicyCreateAppleIDValidationRecordSigningPolicy();
577 }
578 #endif
579
580 errOut:
581 return policy;
582 }
583
584 CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) {
585 // Builds and returns a dictionary which the caller must release.
586
587 if (!policyRef) return NULL;
588 CFMutableDictionaryRef properties = CFDictionaryCreateMutable(NULL, 0,
589 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
590 if (!properties) return NULL;
591 CFStringRef oid = (CFStringRef) CFRetain(policyRef->_oid);
592 CFTypeRef nameKey = NULL;
593
594 // Convert private to public OID if we have one
595 CFStringRef outOid = oid;
596 if (CFEqual(oid, kSecPolicyOIDBasicX509)) {
597 outOid = kSecPolicyAppleX509Basic;
598 }
599 else if (CFEqual(oid, kSecPolicyOIDSSLServer) ||
600 CFEqual(oid, kSecPolicyOIDSSLClient)) {
601 outOid = kSecPolicyAppleSSL;
602 nameKey = kSecPolicyCheckSSLHostname;
603 }
604 else if (CFEqual(oid, kSecPolicyEAPServer) ||
605 CFEqual(oid, kSecPolicyEAPClient)) {
606 outOid = kSecPolicyAppleEAP;
607 nameKey = kSecPolicyCheckEAPTrustedServerNames;
608 }
609 else if (CFEqual(oid, kSecPolicyOIDIPSecServer) ||
610 CFEqual(oid, kSecPolicyOIDIPSecClient)) {
611 outOid = kSecPolicyAppleIPsec;
612 nameKey = kSecPolicyCheckSSLHostname;
613 }
614 else if (CFEqual(oid, kSecPolicyOIDRevocation)) {
615 outOid = kSecPolicyAppleRevocation;
616 }
617 else if (CFEqual(oid, kSecPolicyOIDSMIME)) {
618 outOid = kSecPolicyAppleSMIME;
619 nameKey = kSecPolicyCheckEmail;
620 }
621 else if (CFEqual(oid, kSecPolicyOIDCodeSigning)) {
622 outOid = kSecPolicyAppleCodeSigning;
623 }
624 else if (CFEqual(oid, kSecPolicyOIDAppleIDAuthority)) {
625 outOid = kSecPolicyAppleIDValidation;
626 }
627 else if (CFEqual(oid, kSecPolicyOIDApplePassbook)) {
628 outOid = kSecPolicyApplePassbookSigning;
629 }
630 else if (CFEqual(oid, kSecPolicyOIDAppleMobileStore)) {
631 outOid = kSecPolicyAppleMobileStore;
632 }
633 else if (CFEqual(oid, kSecPolicyOIDAppleTestMobileStore)) {
634 outOid = kSecPolicyAppleTestMobileStore;
635 }
636 else if (CFEqual(oid, kSecPolicyOIDAppleEscrowService)) {
637 outOid = kSecPolicyAppleEscrowService;
638 }
639 else if (CFEqual(oid, kSecPolicyOIDAppleProfileSigner)) {
640 outOid = kSecPolicyAppleProfileSigner;
641 }
642 else if (CFEqual(oid, kSecPolicyOIDAppleQAProfileSigner)) {
643 outOid = kSecPolicyAppleQAProfileSigner;
644 }
645 #if TARGET_OS_IPHONE
646 else if (CFEqual(oid, kSecPolicyOIDAppleOTAPKIAssetSigner)) {
647 outOid = kSecPolicyAppleOTAPKISigner;
648 }
649 else if (CFEqual(oid, kSecPolicyOIDAppleTestOTAPKIAssetSigner)) {
650 outOid = kSecPolicyAppleTestOTAPKISigner;
651 }
652 else if (CFEqual(oid, kSecPolicyOIDAppleIDValidationRecordSigningPolicy)) {
653 outOid = kSecPolicyAppleIDValidationRecordSigningPolicy;
654 }
655 #endif
656
657 // Set kSecPolicyOid
658 CFDictionarySetValue(properties, (const void *)kSecPolicyOid,
659 (const void *)outOid);
660
661 // Set kSecPolicyName if we have one
662 if (nameKey && policyRef->_options) {
663 CFTypeRef name = (CFTypeRef) CFDictionaryGetValue(policyRef->_options,
664 nameKey);
665 if (name) {
666 CFDictionarySetValue(properties, (const void *)kSecPolicyName,
667 (const void *)name);
668 }
669 }
670
671 // Set kSecPolicyClient
672 if (CFEqual(oid, kSecPolicyOIDSSLClient) ||
673 CFEqual(oid, kSecPolicyOIDIPSecClient) ||
674 CFEqual(oid, kSecPolicyEAPClient)) {
675 CFDictionarySetValue(properties, (const void *)kSecPolicyClient,
676 (const void *)kCFBooleanTrue);
677 }
678
679 CFRelease(oid);
680 return properties;
681 }
682
683 #if TARGET_OS_MAC && !TARGET_OS_IPHONE
684 static void SecPolicySetOid(SecPolicyRef policy, CFStringRef oid) {
685 if (!policy || !oid) return;
686 CFStringRef temp = policy->_oid;
687 CFRetain(oid);
688 policy->_oid = oid;
689 CFReleaseSafe(temp);
690 }
691
692 static void SecPolicySetOptionsValue(SecPolicyRef policy, CFStringRef key, CFTypeRef value) {
693 if (!policy || !key) return;
694 CFMutableDictionaryRef options = (CFMutableDictionaryRef) policy->_options;
695 if (!options) {
696 options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
697 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
698 if (!options) return;
699 policy->_options = options;
700 }
701 CFDictionarySetValue(options, key, value);
702 }
703
704 OSStatus SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properties) {
705 // Set policy options based on the provided dictionary keys.
706
707 if (!(policyRef && properties && (CFDictionaryGetTypeID() == CFGetTypeID(properties)))) {
708 return errSecParam;
709 }
710 CFStringRef oid = (CFStringRef) CFRetain(policyRef->_oid);
711 OSStatus result = errSecSuccess;
712
713 // kSecPolicyName
714 CFTypeRef name = NULL;
715 if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyName,
716 (const void **)&name) && name) {
717 CFTypeID typeID = CFGetTypeID(name);
718 if (CFEqual(oid, kSecPolicyOIDSSLServer) ||
719 CFEqual(oid, kSecPolicyOIDSSLClient) ||
720 CFEqual(oid, kSecPolicyOIDIPSecServer) ||
721 CFEqual(oid, kSecPolicyOIDIPSecClient)) {
722 if (CFStringGetTypeID() == typeID) {
723 SecPolicySetOptionsValue(policyRef, kSecPolicyCheckSSLHostname, name);
724 }
725 else result = errSecParam;
726 }
727 else if (CFEqual(oid, kSecPolicyEAPServer) ||
728 CFEqual(oid, kSecPolicyEAPClient)) {
729 if ((CFStringGetTypeID() == typeID) ||
730 (CFArrayGetTypeID() == typeID)) {
731 SecPolicySetOptionsValue(policyRef, kSecPolicyCheckEAPTrustedServerNames, name);
732 }
733 else result = errSecParam;
734 }
735 else if (CFEqual(oid, kSecPolicyOIDSMIME)) {
736 if (CFStringGetTypeID() == typeID) {
737 SecPolicySetOptionsValue(policyRef, kSecPolicyCheckEmail, name);
738 }
739 else result = errSecParam;
740 }
741 }
742
743 // kSecPolicyClient
744 CFTypeRef client = NULL;
745 if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyClient,
746 (const void **)&client) && client) {
747 if (!(CFBooleanGetTypeID() == CFGetTypeID(client))) {
748 result = errSecParam;
749 }
750 else if (CFEqual(client, kCFBooleanTrue)) {
751 if (CFEqual(oid, kSecPolicyOIDSSLServer)) {
752 SecPolicySetOid(policyRef, kSecPolicyOIDSSLClient);
753 }
754 else if (CFEqual(oid, kSecPolicyOIDIPSecServer)) {
755 SecPolicySetOid(policyRef, kSecPolicyOIDIPSecClient);
756 }
757 else if (CFEqual(oid, kSecPolicyEAPServer)) {
758 SecPolicySetOid(policyRef, kSecPolicyEAPClient);
759 }
760 }
761 else {
762 if (CFEqual(oid, kSecPolicyOIDSSLClient)) {
763 SecPolicySetOid(policyRef, kSecPolicyOIDSSLServer);
764 }
765 else if (CFEqual(oid, kSecPolicyOIDIPSecClient)) {
766 SecPolicySetOid(policyRef, kSecPolicyOIDIPSecServer);
767 }
768 else if (CFEqual(oid, kSecPolicyEAPClient)) {
769 SecPolicySetOid(policyRef, kSecPolicyEAPServer);
770 }
771 }
772 }
773
774 CFRelease(oid);
775 return result;
776 }
777 #endif
778
779 static xpc_object_t SecPolicyCopyXPCObject(SecPolicyRef policy, CFErrorRef *error) {
780 xpc_object_t xpc_policy = NULL;
781 xpc_object_t data[2] = {};
782 require_action_quiet(data[0] = _CFXPCCreateXPCObjectFromCFObject(policy->_oid), exit,
783 SecError(errSecParam, error, CFSTR("failed to create xpc_object from policy oid")));
784 require_action_quiet(data[1] = _CFXPCCreateXPCObjectFromCFObject(policy->_options), exit,
785 SecError(errSecParam, error, CFSTR("failed to create xpc_object from policy options")));
786 require_action_quiet(xpc_policy = xpc_array_create(data, array_size(data)), exit,
787 SecError(errSecAllocate, error, CFSTR("failed to create xpc_array for policy")));
788
789 exit:
790 if (data[0]) xpc_release(data[0]);
791 if (data[1]) xpc_release(data[1]);
792 return xpc_policy;
793 }
794
795 static bool SecPolicyAppendToXPCArray(SecPolicyRef policy, xpc_object_t policies, CFErrorRef *error) {
796 if (!policy)
797 return true; // NOOP
798
799 xpc_object_t xpc_policy = SecPolicyCopyXPCObject(policy, error);
800 if (!xpc_policy)
801 return false;
802
803 xpc_array_append_value(policies, xpc_policy);
804 xpc_release(xpc_policy);
805 return true;
806 }
807
808 xpc_object_t SecPolicyArrayCopyXPCArray(CFArrayRef policies, CFErrorRef *error) {
809 xpc_object_t xpc_policies;
810 require_action_quiet(xpc_policies = xpc_array_create(NULL, 0), exit,
811 SecError(errSecAllocate, error, CFSTR("failed to create xpc_array")));
812 CFIndex ix, count = CFArrayGetCount(policies);
813 for (ix = 0; ix < count; ++ix) {
814 if (!SecPolicyAppendToXPCArray((SecPolicyRef)CFArrayGetValueAtIndex(policies, ix), xpc_policies, error)) {
815 xpc_release(xpc_policies);
816 return NULL;
817 }
818 }
819 exit:
820 return xpc_policies;
821 }
822
823 static SecPolicyRef SecPolicyCreateWithXPCObject(xpc_object_t xpc_policy, CFErrorRef *error) {
824 SecPolicyRef policy = NULL;
825 CFTypeRef oid = NULL;
826 CFTypeRef options = NULL;
827
828 require_action_quiet(xpc_policy, exit, SecError(errSecParam, error, CFSTR("policy xpc value is NULL")));
829 require_action_quiet(xpc_get_type(xpc_policy) == XPC_TYPE_ARRAY, exit, SecError(errSecDecode, error, CFSTR("policy xpc value is not an array")));
830 require_action_quiet(xpc_array_get_count(xpc_policy) == 2, exit, SecError(errSecDecode, error, CFSTR("policy xpc array count != 2")));
831 oid = _CFXPCCreateCFObjectFromXPCObject(xpc_array_get_value(xpc_policy, 0));
832 require_action_quiet(isString(oid), exit,
833 SecError(errSecParam, error, CFSTR("failed to convert xpc policy[0]=%@ to CFString"), oid));
834 options = _CFXPCCreateCFObjectFromXPCObject(xpc_array_get_value(xpc_policy, 1));
835 require_action_quiet(isDictionary(options), exit,
836 SecError(errSecParam, error, CFSTR("failed to convert xpc policy[1]=%@ to CFDictionary"), options));
837 require_action_quiet(policy = SecPolicyCreate(oid, options), exit, SecError(errSecDecode, error, CFSTR("Failed to create policy")));
838
839 exit:
840 CFReleaseSafe(oid);
841 CFReleaseSafe(options);
842 return policy;
843 }
844
845 CFArrayRef SecPolicyXPCArrayCopyArray(xpc_object_t xpc_policies, CFErrorRef *error) {
846 CFMutableArrayRef policies = NULL;
847 require_action_quiet(xpc_get_type(xpc_policies) == XPC_TYPE_ARRAY, exit,
848 SecError(errSecParam, error, CFSTR("policies xpc value is not an array")));
849 size_t count = xpc_array_get_count(xpc_policies);
850 require_action_quiet(policies = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks), exit,
851 SecError(errSecAllocate, error, CFSTR("failed to create CFArray of capacity %zu"), count));
852
853 size_t ix;
854 for (ix = 0; ix < count; ++ix) {
855 SecPolicyRef policy = SecPolicyCreateWithXPCObject(xpc_array_get_value(xpc_policies, ix), error);
856 if (!policy) {
857 CFRelease(policies);
858 return NULL;
859 }
860 CFArraySetValueAtIndex(policies, ix, policy);
861 CFRelease(policy);
862 }
863
864 exit:
865 return policies;
866
867 }
868
869 static void add_element(CFMutableDictionaryRef options, CFStringRef key,
870 CFTypeRef value) {
871 CFTypeRef old_value = CFDictionaryGetValue(options, key);
872 if (old_value) {
873 CFMutableArrayRef array;
874 if (CFGetTypeID(old_value) == CFArrayGetTypeID()) {
875 array = (CFMutableArrayRef)old_value;
876 } else {
877 array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
878 &kCFTypeArrayCallBacks);
879 CFArrayAppendValue(array, old_value);
880 CFDictionarySetValue(options, key, array);
881 CFRelease(array);
882 }
883 CFArrayAppendValue(array, value);
884 } else {
885 CFDictionaryAddValue(options, key, value);
886 }
887 }
888
889 static void add_eku(CFMutableDictionaryRef options, const DERItem *ekuOid) {
890 CFDataRef eku = CFDataCreate(kCFAllocatorDefault,
891 ekuOid ? ekuOid->data : NULL,
892 ekuOid ? ekuOid->length : 0);
893 if (eku) {
894 add_element(options, kSecPolicyCheckExtendedKeyUsage, eku);
895 CFRelease(eku);
896 }
897 }
898
899 static void add_ku(CFMutableDictionaryRef options, SecKeyUsage keyUsage) {
900 SInt32 dku = keyUsage;
901 CFNumberRef ku = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
902 &dku);
903 if (ku) {
904 add_element(options, kSecPolicyCheckKeyUsage, ku);
905 CFRelease(ku);
906 }
907 }
908
909 static void add_oid(CFMutableDictionaryRef options, CFStringRef policy_key, const DERItem *oid) {
910 CFDataRef oid_data = CFDataCreate(kCFAllocatorDefault,
911 oid ? oid->data : NULL,
912 oid ? oid->length : 0);
913 if (oid_data) {
914 add_element(options, policy_key, oid_data);
915 CFRelease(oid_data);
916 }
917 }
918
919 static void add_leaf_marker_value(CFMutableDictionaryRef options, const DERItem *markerOid, CFStringRef string_value) {
920
921 CFTypeRef policyData = NULL;
922
923 if (NULL == string_value) {
924 policyData = CFDataCreate(kCFAllocatorDefault,
925 markerOid ? markerOid->data : NULL,
926 markerOid ? markerOid->length : 0);
927 } else {
928 CFStringRef oid_as_string = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, markerOid);
929
930 const void *key[1] = { oid_as_string };
931 const void *value[1] = { string_value };
932 policyData = CFDictionaryCreate(kCFAllocatorDefault,
933 key, value, 1,
934 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
935 CFReleaseNull(oid_as_string);
936 }
937
938 add_element(options, kSecPolicyCheckLeafMarkerOid, policyData);
939
940 CFReleaseNull(policyData);
941
942 }
943
944 static void add_leaf_marker(CFMutableDictionaryRef options, const DERItem *markerOid) {
945 add_leaf_marker_value(options, markerOid, NULL);
946 }
947
948
949 static void add_certificate_policy_oid(CFMutableDictionaryRef options, const DERItem *certificatePolicyOid, CFStringRef string_value) {
950 CFTypeRef certificatePolicyData = NULL;
951
952 if (NULL == string_value) {
953 certificatePolicyData = CFDataCreate(kCFAllocatorDefault,
954 certificatePolicyOid ? certificatePolicyOid->data : NULL,
955 certificatePolicyOid ? certificatePolicyOid->length : 0);
956 } else {
957 CFStringRef oid_as_string = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, certificatePolicyOid);
958
959 const void *key[1] = { oid_as_string };
960 const void *value[1] = { string_value };
961 certificatePolicyData = CFDictionaryCreate(kCFAllocatorDefault,
962 key, value, 1,
963 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
964 CFReleaseNull(oid_as_string);
965 }
966
967 add_element(options, kSecPolicyCheckCertificatePolicy, certificatePolicyData);
968
969 CFReleaseNull(certificatePolicyData);
970 }
971 //
972 // Routines for adding dictionary entries for policies.
973 //
974
975 // X.509, but missing validity requirements.
976 static void SecPolicyAddBasicCertOptions(CFMutableDictionaryRef options)
977 {
978 //CFDictionaryAddValue(options, kSecPolicyCheckBasicCertificateProcessing, kCFBooleanTrue);
979 CFDictionaryAddValue(options, kSecPolicyCheckCriticalExtensions, kCFBooleanTrue);
980 CFDictionaryAddValue(options, kSecPolicyCheckIdLinkage, kCFBooleanTrue);
981 CFDictionaryAddValue(options, kSecPolicyCheckBasicContraints, kCFBooleanTrue);
982 CFDictionaryAddValue(options, kSecPolicyCheckNonEmptySubject, kCFBooleanTrue);
983 CFDictionaryAddValue(options, kSecPolicyCheckQualifiedCertStatements, kCFBooleanTrue);
984 }
985
986 static void SecPolicyAddBasicX509Options(CFMutableDictionaryRef options)
987 {
988 SecPolicyAddBasicCertOptions(options);
989 CFDictionaryAddValue(options, kSecPolicyCheckValidIntermediates, kCFBooleanTrue);
990 CFDictionaryAddValue(options, kSecPolicyCheckValidLeaf, kCFBooleanTrue);
991 CFDictionaryAddValue(options, kSecPolicyCheckValidRoot, kCFBooleanTrue);
992
993 // Make sure that black and gray leaf checks are performed for basic X509 chain building
994 CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf, kCFBooleanTrue);
995 CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, kCFBooleanTrue);
996 }
997
998 static bool SecPolicyAddChainLengthOptions(CFMutableDictionaryRef options, CFIndex length)
999 {
1000 bool result = false;
1001 CFNumberRef lengthAsCF = NULL;
1002
1003 require(lengthAsCF = CFNumberCreate(kCFAllocatorDefault,
1004 kCFNumberCFIndexType, &length), errOut);
1005 CFDictionaryAddValue(options, kSecPolicyCheckChainLength, lengthAsCF);
1006
1007 result = true;
1008
1009 errOut:
1010 CFReleaseSafe(lengthAsCF);
1011 return result;
1012 }
1013
1014 static bool SecPolicyAddAnchorSHA1Options(CFMutableDictionaryRef options,
1015 const UInt8 anchorSha1[kSecPolicySHA1Size])
1016 {
1017 bool success = false;
1018 CFDataRef anchorData = NULL;
1019
1020 require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha1, kSecPolicySHA1Size), errOut);
1021 add_element(options, kSecPolicyCheckAnchorSHA1, anchorData);
1022
1023 success = true;
1024
1025 errOut:
1026 CFReleaseSafe(anchorData);
1027 return success;
1028 }
1029
1030 static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef options)
1031 {
1032 return SecPolicyAddAnchorSHA1Options(options, kAppleCASHA1);
1033 }
1034
1035 #if 0
1036 static bool SecPolicyAddAppleTESTAnchorOptions(CFMutableDictionaryRef options)
1037 {
1038 return SecPolicyAddAnchorSHA1Options(options, kAppleTESTCASHA1);
1039 }
1040 #endif
1041
1042 //
1043 // Policy Creation Functions
1044 //
1045 SecPolicyRef SecPolicyCreateBasicX509(void) {
1046 CFMutableDictionaryRef options = NULL;
1047 SecPolicyRef result = NULL;
1048
1049 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1050 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1051
1052 SecPolicyAddBasicX509Options(options);
1053 CFDictionaryAddValue(options, kSecPolicyCheckNoNetworkAccess,
1054 kCFBooleanTrue);
1055
1056 require(result = SecPolicyCreate(kSecPolicyOIDBasicX509, options), errOut);
1057
1058 errOut:
1059 CFReleaseSafe(options);
1060 return result;
1061 }
1062
1063 SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) {
1064 CFMutableDictionaryRef options = NULL;
1065 SecPolicyRef result = NULL;
1066
1067 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1068 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1069
1070 SecPolicyAddBasicX509Options(options);
1071
1072 #if 0
1073 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
1074 kCFBooleanTrue);
1075 #endif
1076
1077 if (hostname) {
1078 CFDictionaryAddValue(options, kSecPolicyCheckSSLHostname, hostname);
1079 }
1080
1081 CFDictionaryAddValue(options, kSecPolicyCheckBlackListedLeaf, kCFBooleanTrue);
1082 CFDictionaryAddValue(options, kSecPolicyCheckGrayListedLeaf, kCFBooleanTrue);
1083
1084 /* If server and EKU ext present then EKU ext should contain one of
1085 CSSMOID_ServerAuth or CSSMOID_ExtendedKeyUsageAny or
1086 CSSMOID_NetscapeSGC or CSSMOID_MicrosoftSGC.
1087 else if !server and EKU ext present then EKU ext should contain one of
1088 CSSMOID_ClientAuth or CSSMOID_ExtendedKeyUsageAny. */
1089
1090 /* We always allow certification that specify oidAnyExtendedKeyUsage. */
1091 add_eku(options, NULL); /* eku extension is optional */
1092 add_eku(options, &oidAnyExtendedKeyUsage);
1093 if (server) {
1094 add_eku(options, &oidExtendedKeyUsageServerAuth);
1095 add_eku(options, &oidExtendedKeyUsageMicrosoftSGC);
1096 add_eku(options, &oidExtendedKeyUsageNetscapeSGC);
1097 } else {
1098 add_eku(options, &oidExtendedKeyUsageClientAuth);
1099 }
1100
1101 require(result = SecPolicyCreate(
1102 server ? kSecPolicyOIDSSLServer : kSecPolicyOIDSSLClient,
1103 options), errOut);
1104
1105 errOut:
1106 CFReleaseSafe(options);
1107 return result;
1108 }
1109
1110 SecPolicyRef SecPolicyCreateiPhoneActivation(void) {
1111 CFMutableDictionaryRef options = NULL;
1112 SecPolicyRef result = NULL;
1113
1114 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1115 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1116
1117 SecPolicyAddBasicCertOptions(options);
1118
1119 #if 0
1120 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
1121 kCFBooleanTrue);
1122 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
1123 kCFBooleanTrue);
1124 #endif
1125
1126 /* Basic X.509 policy with the additional requirements that the chain
1127 length is 3, it's anchored at the AppleCA and the leaf certificate
1128 has issuer "Apple iPhone Certification Authority" and
1129 subject "Apple iPhone Activation" for the common name. */
1130 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
1131 CFSTR("Apple iPhone Certification Authority"));
1132 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName,
1133 CFSTR("Apple iPhone Activation"));
1134
1135 require(SecPolicyAddChainLengthOptions(options, 3), errOut);
1136 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1137
1138 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneActivation, options),
1139 errOut);
1140
1141 errOut:
1142 CFReleaseSafe(options);
1143 return result;
1144 }
1145
1146 SecPolicyRef SecPolicyCreateiPhoneDeviceCertificate(void) {
1147 CFMutableDictionaryRef options = NULL;
1148 SecPolicyRef result = NULL;
1149
1150 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1151 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1152
1153 SecPolicyAddBasicCertOptions(options);
1154
1155 #if 0
1156 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
1157 kCFBooleanTrue);
1158 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
1159 kCFBooleanTrue);
1160 #endif
1161
1162 /* Basic X.509 policy with the additional requirements that the chain
1163 length is 4, it's anchored at the AppleCA and the first intermediate
1164 has the subject "Apple iPhone Device CA". */
1165 CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
1166 CFSTR("Apple iPhone Device CA"));
1167
1168 require(SecPolicyAddChainLengthOptions(options, 4), errOut);
1169 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1170
1171 require(result = SecPolicyCreate(kSecPolicyOIDiPhoneDeviceCertificate, options),
1172 errOut);
1173
1174 errOut:
1175 CFReleaseSafe(options);
1176 return result;
1177 }
1178
1179 SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void) {
1180 CFMutableDictionaryRef options = NULL;
1181 SecPolicyRef result = NULL;
1182
1183 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1184 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1185
1186 SecPolicyAddBasicCertOptions(options);
1187
1188 #if 0
1189 CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage,
1190 kCFBooleanTrue);
1191 CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage,
1192 kCFBooleanTrue);
1193 #endif
1194
1195 /* Basic X.509 policy with the additional requirements that the chain
1196 is anchored at the factory device certificate issuer. */
1197 require(SecPolicyAddAnchorSHA1Options(options, kFactoryDeviceCASHA1), errOut);
1198
1199 require(result = SecPolicyCreate(kSecPolicyOIDFactoryDeviceCertificate, options),
1200 errOut);
1201
1202 errOut:
1203 CFReleaseSafe(options);
1204 return result;
1205 }
1206
1207 SecPolicyRef SecPolicyCreateiAP(void) {
1208 CFMutableDictionaryRef options = NULL;
1209 SecPolicyRef result = NULL;
1210 CFTimeZoneRef tz = NULL;
1211 CFDateRef date = NULL;
1212
1213 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1214 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
1215
1216 SecPolicyAddBasicCertOptions(options);
1217
1218 CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNamePrefix,
1219 CFSTR("IPA_"));
1220
1221 CFGregorianDate gd = {
1222 2006,
1223 5,
1224 31,
1225 0,
1226 0,
1227 0.0
1228 };
1229 require(tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0), errOut);
1230 CFAbsoluteTime at = CFGregorianDateGetAbsoluteTime(gd, tz);
1231 require(date = CFDateCreate(kCFAllocatorDefault, at), errOut);
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 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1784 &kCFTypeDictionaryKeyCallBacks,
1785 &kCFTypeDictionaryValueCallBacks), errOut);
1786
1787 SecPolicyAddBasicX509Options(options);
1788
1789
1790 add_ku(options, kSecKeyUsageKeyEncipherment);
1791
1792 //add_leaf_marker(options, &oidApplePolicyEscrowService);
1793 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
1794
1795
1796 Boolean anchorAdded = false;
1797 // Get the roots by calling the SecCertificateCopyEscrowRoots
1798 CFArrayRef anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot);
1799 CFIndex numRoots = 0;
1800 if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray)))
1801 {
1802 goto errOut;
1803 }
1804
1805 for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++)
1806 {
1807 SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt);
1808
1809 if (NULL != aCert)
1810 {
1811 CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert);
1812 if (NULL != sha_data)
1813 {
1814 const UInt8* pSHAData = CFDataGetBytePtr(sha_data);
1815 if (NULL != pSHAData)
1816 {
1817 SecPolicyAddAnchorSHA1Options(options, pSHAData);
1818 anchorAdded = true;
1819 }
1820 }
1821 }
1822 }
1823 CFRelease(anArray);
1824
1825 if (!anchorAdded)
1826 {
1827 goto errOut;
1828 }
1829
1830
1831 require(result = SecPolicyCreate(kSecPolicyOIDAppleEscrowService, options), errOut);
1832
1833 errOut:
1834 CFReleaseSafe(options);
1835 return result;
1836 }
1837
1838 SecCertificateRef SecPolicyCopyEscrowRootCertificate(void)
1839 {
1840 SecCertificateRef result = NULL;
1841
1842 return result;
1843 }
1844
1845 SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void)
1846 {
1847 SecPolicyRef result = NULL;
1848 CFMutableDictionaryRef options = NULL;
1849 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1850 &kCFTypeDictionaryKeyCallBacks,
1851 &kCFTypeDictionaryValueCallBacks), errOut);
1852
1853 SecPolicyAddBasicX509Options(options);
1854 SecPolicyAddAppleAnchorOptions(options);
1855
1856 // Require the profile signing EKU
1857 add_eku(options, &oidAppleExtendedKeyUsageProfileSigning);
1858
1859 require(result = SecPolicyCreate(kSecPolicyOIDAppleProfileSigner, options), errOut);
1860
1861 errOut:
1862 CFReleaseSafe(options);
1863 return result;
1864 }
1865
1866
1867 SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void)
1868 {
1869 SecPolicyRef result = NULL;
1870 CFMutableDictionaryRef options = NULL;
1871 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1872 &kCFTypeDictionaryKeyCallBacks,
1873 &kCFTypeDictionaryValueCallBacks), errOut);
1874
1875 SecPolicyAddBasicX509Options(options);
1876 SecPolicyAddAppleAnchorOptions(options);
1877
1878 // Require the QA profile signing EKU
1879 add_eku(options, &oidAppleExtendedKeyUsageQAProfileSigning);
1880
1881 require(result = SecPolicyCreate(kSecPolicyOIDAppleQAProfileSigner, options), errOut);
1882
1883 errOut:
1884 CFReleaseSafe(options);
1885 return result;
1886 }
1887
1888 #if TARGET_OS_IPHONE
1889 SecPolicyRef SecPolicyCreateOTAPKISigner(void)
1890 {
1891 SecPolicyRef result = NULL;
1892 CFMutableDictionaryRef options = NULL;
1893 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1894 &kCFTypeDictionaryKeyCallBacks,
1895 &kCFTypeDictionaryValueCallBacks), errOut);
1896 SecPolicyAddBasicX509Options(options);
1897
1898 SecPolicyAddAnchorSHA1Options(options, kApplePKISettingsAuthority);
1899 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
1900
1901 require(result = SecPolicyCreate(kSecPolicyOIDAppleOTAPKIAssetSigner, options), errOut);
1902
1903 errOut:
1904 CFReleaseSafe(options);
1905 return result;
1906
1907 }
1908
1909
1910 SecPolicyRef SecPolicyCreateTestOTAPKISigner(void)
1911 {
1912 SecPolicyRef result = NULL;
1913 CFMutableDictionaryRef options = NULL;
1914 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1915 &kCFTypeDictionaryKeyCallBacks,
1916 &kCFTypeDictionaryValueCallBacks), errOut);
1917 SecPolicyAddBasicX509Options(options);
1918
1919 SecPolicyAddAnchorSHA1Options(options, kAppleTestPKISettingsAuthority);
1920 require(SecPolicyAddChainLengthOptions(options, 2), errOut);
1921
1922 require(result = SecPolicyCreate(kSecPolicyOIDAppleTestOTAPKIAssetSigner, options), errOut);
1923
1924 errOut:
1925 CFReleaseSafe(options);
1926 return result;
1927 }
1928
1929
1930 SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void)
1931 {
1932 SecPolicyRef result = NULL;
1933 CFMutableDictionaryRef options = NULL;
1934 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
1935 &kCFTypeDictionaryKeyCallBacks,
1936 &kCFTypeDictionaryValueCallBacks), errOut);
1937
1938 //Leaf appears to be a SSL only cert, so policy should expand on that policy
1939 SecPolicyAddBasicX509Options(options);
1940
1941 // Apple CA anchored
1942 require(SecPolicyAddAppleAnchorOptions(options), errOut);
1943
1944 // Check for an extension with " Apple ID Validation Record Signing" oid (1.2.840.113635.100.6.25)
1945 add_leaf_marker(options, &oidAppleCertExtensionAppleIDRecordValidationSigning);
1946
1947 // and validate that intermediate has extension
1948 // Application Integration Intermediate Certificate (1.2.840.113635.100.6.2.3)
1949 // and also validate that intermediate has extension
1950 // System Integration 2 Intermediate Certificate (1.2.840.113635.100.6.2.10)
1951 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID);
1952 add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntg2);
1953
1954 // Ensure that revocation is checked (OCSP)
1955 CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse);
1956
1957 require(result = SecPolicyCreate(kSecPolicyOIDAppleIDValidationRecordSigningPolicy, options), errOut);
1958
1959 errOut:
1960 CFReleaseSafe(options);
1961 return result;
1962 }
1963
1964 #endif // TARGET_OS_IPHONE