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 ********************************************************/
58CFStringRef kSecPolicyCheckSSLHostname = CFSTR("SSLHostname");
59
60CFStringRef 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. */
64CFStringRef kSecPolicyCheckIssuerCommonName = CFSTR("IssuerCommonName");
65
66/* Checks that the leaf has exactly one Common Name and that it
67   matches the specified string. */
68CFStringRef 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. */
72CFStringRef 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". */
76CFStringRef kSecPolicyCheckSubjectCommonNameTEST = CFSTR("SubjectCommonNameTEST");
77
78/* Checks that the leaf has exactly one Organization and that it
79   matches the specified string. */
80CFStringRef kSecPolicyCheckSubjectOrganization = CFSTR("SubjectOrganization");
81
82/* Checks that the leaf has exactly one Organizational Unit and that it
83   matches the specified string. */
84CFStringRef kSecPolicyCheckSubjectOrganizationalUnit = CFSTR("SubjectOrganizationalUnit");
85
86/* Check that the leaf is not valid before the specified date (or verifyDate
87   if none is provided?). */
88CFStringRef kSecPolicyCheckNotValidBefore = CFSTR("NotValidBefore");
89
90CFStringRef kSecPolicyCheckEAPTrustedServerNames = CFSTR("EAPTrustedServerNames");
91
92CFStringRef kSecPolicyCheckCertificatePolicy = CFSTR("CertificatePolicy");
93
94#if 0
95/* Check for basic constraints on leaf to be valid.  (rfc5280 check) */
96CFStringRef kSecPolicyCheckLeafBasicConstraints = CFSTR("LeafBasicContraints");
97#endif
98
99/********************************************************
100 *********** Unverified Intermediate Checks *************
101 ********************************************************/
102CFStringRef kSecPolicyCheckKeyUsage = CFSTR("KeyUsage"); /* (rfc5280 check) */
103CFStringRef kSecPolicyCheckExtendedKeyUsage = CFSTR("ExtendedKeyUsage"); /* (rfc5280 check) */
104CFStringRef kSecPolicyCheckBasicContraints = CFSTR("BasicContraints"); /* (rfc5280 check) */
105CFStringRef kSecPolicyCheckQualifiedCertStatements =
106    CFSTR("QualifiedCertStatements"); /* (rfc5280 check) */
107
108/********************************************************
109 ************** Unverified Anchor Checks ****************
110 ********************************************************/
111CFStringRef kSecPolicyCheckAnchorSHA1 = CFSTR("AnchorSHA1");
112
113/* Fake key for isAnchored check. */
114CFStringRef kSecPolicyCheckAnchorTrusted = CFSTR("AnchorTrusted");
115
116/********************************************************
117 *********** Unverified Certificate Checks **************
118 ********************************************************/
119/* Unverified Certificate Checks (any of the above) */
120CFStringRef kSecPolicyCheckNonEmptySubject = CFSTR("NonEmptySubject");
121CFStringRef kSecPolicyCheckIdLinkage = CFSTR("IdLinkage"); /* (rfc5280 check) */
122#if 0
123CFStringRef kSecPolicyCheckValidityStarted = CFSTR("ValidStarted");
124CFStringRef kSecPolicyCheckValidityExpired = CFSTR("ValidExpired");
125#else
126CFStringRef kSecPolicyCheckValidIntermediates = CFSTR("ValidIntermediates");
127CFStringRef kSecPolicyCheckValidLeaf = CFSTR("ValidLeaf");
128CFStringRef 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. */
138CFStringRef kSecPolicyCheckCriticalExtensions = CFSTR("CriticalExtensions");
139
140/* Check that the certificate chain length matches the specificed CFNumberRef
141   length. */
142CFStringRef kSecPolicyCheckChainLength = CFSTR("ChainLength");
143
144/* (rfc5280 check) */
145CFStringRef kSecPolicyCheckBasicCertificateProcessing =
146    CFSTR("BasicCertificateProcessing");
147
148/********************************************************
149 ******************* Feature toggles ********************
150 ********************************************************/
151
152/* Check revocation if specified. */
153CFStringRef kSecPolicyCheckExtendedValidation = CFSTR("ExtendedValidation");
154CFStringRef 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. */
158CFStringRef kSecPolicyCheckNoNetworkAccess = CFSTR("NoNetworkAccess");
159
160/* Hack to quickly blacklist certain certs. */
161CFStringRef kSecPolicyCheckBlackListedLeaf = CFSTR("BlackListedLeaf");
162CFStringRef kSecPolicyCheckGrayListedLeaf  = CFSTR("GrayListedLeaf");
163CFStringRef kSecPolicyCheckGrayListedKey   = CFSTR("GrayListedKey");
164CFStringRef kSecPolicyCheckBlackListedKey  = CFSTR("BlackListedKey");
165
166CFStringRef kSecPolicyCheckLeafMarkerOid = CFSTR("CheckLeafMarkerOid");
167CFStringRef kSecPolicyCheckIntermediateMarkerOid = CFSTR("CheckIntermediateMarkerOid");
168
169/* Public policy names. */
170SEC_CONST_DECL (kSecPolicyAppleX509Basic, "1.2.840.113635.100.1.2");
171SEC_CONST_DECL (kSecPolicyAppleSSL, "1.2.840.113635.100.1.3");
172SEC_CONST_DECL (kSecPolicyAppleSMIME, "1.2.840.113635.100.1.8");
173SEC_CONST_DECL (kSecPolicyAppleEAP, "1.2.840.113635.100.1.9");
174SEC_CONST_DECL (kSecPolicyAppleIPsec, "1.2.840.113635.100.1.11");
175SEC_CONST_DECL (kSecPolicyApplePKINITClient, "1.2.840.113635.100.1.14");
176SEC_CONST_DECL (kSecPolicyApplePKINITServer, "1.2.840.113635.100.1.15");
177SEC_CONST_DECL (kSecPolicyAppleCodeSigning, "1.2.840.113635.100.1.16");
178SEC_CONST_DECL (kSecPolicyApplePackageSigning, "1.2.840.113635.100.1.17");
179SEC_CONST_DECL (kSecPolicyAppleIDValidation, "1.2.840.113635.100.1.18");
180SEC_CONST_DECL (kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19");
181SEC_CONST_DECL (kSecPolicyAppleTimeStamping, "1.2.840.113635.100.1.20");
182SEC_CONST_DECL (kSecPolicyAppleRevocation, "1.2.840.113635.100.1.21");
183SEC_CONST_DECL (kSecPolicyApplePassbookSigning, "1.2.840.113635.100.1.22");
184SEC_CONST_DECL (kSecPolicyAppleMobileStore, "1.2.840.113635.100.1.23");
185SEC_CONST_DECL (kSecPolicyAppleEscrowService, "1.2.840.113635.100.1.24");
186SEC_CONST_DECL (kSecPolicyAppleProfileSigner, "1.2.840.113635.100.1.25");
187SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner, "1.2.840.113635.100.1.26");
188SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27");
189#if TARGET_OS_IPHONE
190SEC_CONST_DECL (kSecPolicyAppleOTAPKISigner, "1.2.840.113635.100.1.28");
191SEC_CONST_DECL (kSecPolicyAppleTestOTAPKISigner, "1.2.840.113635.100.1.29");
192/* FIXME: this policy name should be deprecated and replaced with "kSecPolicyAppleIDValidationRecordSigning" */
193SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113625.100.1.30");
194SEC_CONST_DECL (kSecPolicyAppleSMPEncryption, "1.2.840.113625.100.1.31");
195SEC_CONST_DECL (kSecPolicyAppleTestSMPEncryption, "1.2.840.113625.100.1.32");
196#endif
197SEC_CONST_DECL (kSecPolicyAppleServerAuthentication, "1.2.840.113635.100.1.33");
198SEC_CONST_DECL (kSecPolicyApplePCSEscrowService, "1.2.840.113635.100.1.34");
199
200SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid");
201SEC_CONST_DECL (kSecPolicyName, "SecPolicyName");
202SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient");
203SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags");
204SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier");
205
206/* Private policy names */
207static CFStringRef kSecPolicyOIDBasicX509 = CFSTR("basicX509");
208static CFStringRef kSecPolicyOIDSSLServer = CFSTR("sslServer");
209static CFStringRef kSecPolicyOIDSSLClient = CFSTR("sslClient");
210static CFStringRef kSecPolicyOIDiPhoneActivation = CFSTR("iPhoneActivation");
211static CFStringRef kSecPolicyOIDiPhoneDeviceCertificate =
212    CFSTR("iPhoneDeviceCertificate");
213static CFStringRef kSecPolicyOIDFactoryDeviceCertificate =
214    CFSTR("FactoryDeviceCertificate");
215static CFStringRef kSecPolicyOIDiAP = CFSTR("iAP");
216static CFStringRef kSecPolicyOIDiTunesStoreURLBag = CFSTR("iTunesStoreURLBag");
217static CFStringRef kSecPolicyEAPServer = CFSTR("eapServer");
218static CFStringRef kSecPolicyEAPClient = CFSTR("eapClient");
219static CFStringRef kSecPolicyOIDIPSecServer = CFSTR("ipsecServer");
220static CFStringRef kSecPolicyOIDIPSecClient = CFSTR("ipsecClient");
221static CFStringRef kSecPolicyOIDiPhoneApplicationSigning =
222    CFSTR("iPhoneApplicationSigning");
223static CFStringRef kSecPolicyOIDiPhoneProfileApplicationSigning =
224    CFSTR("iPhoneProfileApplicationSigning");
225static CFStringRef kSecPolicyOIDiPhoneProvisioningProfileSigning =
226    CFSTR("iPhoneProvisioningProfileSigning");
227static CFStringRef kSecPolicyOIDRevocation = CFSTR("revocation");
228static CFStringRef kSecPolicyOIDOCSPSigner = CFSTR("OCSPSigner");
229static CFStringRef kSecPolicyOIDSMIME = CFSTR("SMIME");
230static CFStringRef kSecPolicyOIDCodeSigning = CFSTR("CodeSigning");
231static CFStringRef kSecPolicyOIDLockdownPairing = CFSTR("LockdownPairing");
232static CFStringRef kSecPolicyOIDURLBag = CFSTR("URLBag");
233static CFStringRef kSecPolicyOIDOTATasking = CFSTR("OTATasking");
234static CFStringRef kSecPolicyOIDMobileAsset = CFSTR("MobileAsset");
235static CFStringRef kSecPolicyOIDAppleIDAuthority = CFSTR("AppleIDAuthority");
236static CFStringRef kSecPolicyOIDAppleShoebox = CFSTR("AppleShoebox");
237static CFStringRef kSecPolicyOIDApplePassbook = CFSTR("ApplePassbook");
238static CFStringRef kSecPolicyOIDAppleMobileStore = CFSTR("AppleMobileStore");
239static CFStringRef kSecPolicyOIDAppleTestMobileStore = CFSTR("AppleTestMobileStore");
240static CFStringRef kSecPolicyOIDAppleEscrowService = CFSTR("AppleEscrowService");
241static CFStringRef kSecPolicyOIDApplePCSEscrowService = CFSTR("ApplePCSEscrowService");
242static CFStringRef kSecPolicyOIDAppleProfileSigner = CFSTR("AppleProfileSigner");
243static CFStringRef kSecPolicyOIDAppleQAProfileSigner = CFSTR("AppleQAProfileSigner");
244static CFStringRef kSecPolicyOIDAppleOTAPKIAssetSigner = CFSTR("AppleOTAPKIAssetSigner");
245static CFStringRef kSecPolicyOIDAppleTestOTAPKIAssetSigner = CFSTR("AppleTestOTAPKIAssetSigner");
246static 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
314Example 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
369check_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
390const 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
400static 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
405static 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
411static 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
416static 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
421static 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
426static 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
438static void SecPolicyDestroy(CFTypeRef cf) {
439	SecPolicyRef policy = (SecPolicyRef) cf;
440	CFRelease(policy->_oid);
441	CFRelease(policy->_options);
442}
443
444static 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
451static CFHashCode SecPolicyHash(CFTypeRef cf) {
452	SecPolicyRef policy = (SecPolicyRef) cf;
453
454	return CFHash(policy->_oid) + CFHash(policy->_options);
455}
456
457static CFStringRef SecPolicyCopyDescription(CFTypeRef cf) {
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. */
471CFGiblisWithHashFor(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 */
477SecPolicyRef 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
492errOut:
493    return result;
494}
495
496SecPolicyRef 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
587errOut:
588	return policy;
589}
590
591CFDictionaryRef 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
694static 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
702static 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
714OSStatus 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
789static 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
799exit:
800    if (data[0]) xpc_release(data[0]);
801    if (data[1]) xpc_release(data[1]);
802    return xpc_policy;
803}
804
805static 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
818xpc_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    }
829exit:
830    return xpc_policies;
831}
832
833static 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
849exit:
850    CFReleaseSafe(oid);
851    CFReleaseSafe(options);
852    return policy;
853}
854
855CFArrayRef 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
874exit:
875    return policies;
876
877}
878
879static 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
899static 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
909static 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
919static 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
929static 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
954static void add_leaf_marker(CFMutableDictionaryRef options, const DERItem *markerOid) {
955    add_leaf_marker_value(options, markerOid, NULL);
956}
957
958
959static 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.
986static 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
996static 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
1008static 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
1019errOut:
1020	CFReleaseSafe(lengthAsCF);
1021    return result;
1022}
1023
1024static 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
1035errOut:
1036    CFReleaseSafe(anchorData);
1037    return success;
1038}
1039
1040static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef options)
1041{
1042    return SecPolicyAddAnchorSHA1Options(options, kAppleCASHA1);
1043}
1044
1045#if 0
1046static bool SecPolicyAddAppleTESTAnchorOptions(CFMutableDictionaryRef options)
1047{
1048    return SecPolicyAddAnchorSHA1Options(options, kAppleTESTCASHA1);
1049}
1050#endif
1051
1052//
1053// Policy Creation Functions
1054//
1055SecPolicyRef 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
1068errOut:
1069	CFReleaseSafe(options);
1070	return result;
1071}
1072
1073SecPolicyRef 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
1115errOut:
1116	CFReleaseSafe(options);
1117	return result;
1118}
1119
1120SecPolicyRef 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
1151errOut:
1152	CFReleaseSafe(options);
1153	return result;
1154}
1155
1156SecPolicyRef 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
1184errOut:
1185	CFReleaseSafe(options);
1186	return result;
1187}
1188
1189SecPolicyRef 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
1212errOut:
1213	CFReleaseSafe(options);
1214	return result;
1215}
1216
1217SecPolicyRef 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
1237errOut:
1238	CFReleaseSafe(date);
1239	CFReleaseSafe(tz);
1240	CFReleaseSafe(options);
1241	return result;
1242}
1243
1244SecPolicyRef 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
1264errOut:
1265	CFReleaseSafe(options);
1266	return result;
1267}
1268
1269SecPolicyRef 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
1297errOut:
1298	CFReleaseSafe(options);
1299	return result;
1300}
1301
1302SecPolicyRef 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
1334errOut:
1335	CFReleaseSafe(options);
1336	return result;
1337}
1338
1339SecPolicyRef 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
1369errOut:
1370	CFReleaseSafe(options);
1371	return result;
1372}
1373
1374SecPolicyRef 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
1386errOut:
1387	CFReleaseSafe(options);
1388	return result;
1389}
1390
1391SecPolicyRef 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
1417errOut:
1418	CFReleaseSafe(options);
1419	return result;
1420}
1421
1422SecPolicyRef 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
1436errOut:
1437	CFReleaseSafe(options);
1438	return result;
1439}
1440
1441SecPolicyRef 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
1467errOut:
1468	CFReleaseSafe(options);
1469	return result;
1470}
1471
1472SecPolicyRef 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
1522errOut:
1523	CFReleaseSafe(options);
1524	return result;
1525}
1526
1527SecPolicyRef 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
1551errOut:
1552	CFReleaseSafe(options);
1553	return result;
1554}
1555
1556/* Explicitly leave out empty subject/subjectaltname check */
1557SecPolicyRef 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
1576errOut:
1577	CFReleaseSafe(options);
1578	return result;
1579}
1580
1581SecPolicyRef 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
1594errOut:
1595	CFReleaseSafe(options);
1596	return result;
1597}
1598
1599static 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
1626errOut:
1627    return success;
1628}
1629
1630static 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
1645errOut:
1646    CFReleaseSafe(options);
1647    return result;
1648}
1649
1650
1651SecPolicyRef SecPolicyCreateOTATasking(void)
1652{
1653    return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDOTATasking, CFSTR("OTA Task Signing"), true);
1654}
1655
1656SecPolicyRef SecPolicyCreateMobileAsset(void)
1657{
1658    return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDMobileAsset, CFSTR("Asset Manifest Signing"), false);
1659}
1660
1661SecPolicyRef 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
1685out:
1686    CFReleaseSafe(options);
1687    return result;
1688}
1689
1690static 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
1721out:
1722	CFReleaseSafe(options);
1723	return result;
1724}
1725
1726SecPolicyRef SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, CFStringRef teamIdentifier)
1727{
1728    return _SecPolicyCreatePassbookCardSigner(cardIssuer, teamIdentifier, true);
1729}
1730
1731
1732SecPolicyRef SecPolicyCreateShoeboxCardSigner(CFStringRef cardIssuer)
1733{
1734	return _SecPolicyCreatePassbookCardSigner(cardIssuer, nil, false);
1735}
1736
1737static 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
1761errOut:
1762    CFReleaseSafe(options);
1763    return result;
1764}
1765
1766SecPolicyRef SecPolicyCreateMobileStoreSigner(void)
1767{
1768
1769	return CreateMobileStoreSigner(false);
1770}
1771
1772SecPolicyRef SecPolicyCreateTestMobileStoreSigner(void)
1773{
1774
1775	return CreateMobileStoreSigner(true);
1776}
1777
1778
1779CF_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
1834errOut:
1835    CFReleaseSafe(anArray);
1836	CFReleaseSafe(options);
1837	return result;
1838}
1839
1840CF_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
1894errOut:
1895    CFReleaseSafe(anArray);
1896	CFReleaseSafe(options);
1897	return result;
1898}
1899SecCertificateRef SecPolicyCopyEscrowRootCertificate(void)
1900{
1901	SecCertificateRef result = NULL;
1902
1903	return result;
1904}
1905
1906SecPolicyRef 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
1922errOut:
1923  CFReleaseSafe(options);
1924  return result;
1925}
1926
1927
1928SecPolicyRef 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
1944errOut:
1945  CFReleaseSafe(options);
1946  return result;
1947}
1948
1949#if TARGET_OS_IPHONE
1950SecPolicyRef 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
1964errOut:
1965  CFReleaseSafe(options);
1966  return result;
1967
1968}
1969
1970
1971SecPolicyRef 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
1985errOut:
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 */
1998SecPolicyRef 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
2026errOut:
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 */
2037SecPolicyRef 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
2059errOut:
2060	CFReleaseSafe(options);
2061	return result;
2062}
2063
2064
2065SecPolicyRef 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
2094errOut:
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 */
2103SecPolicyRef 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 */
2112SecPolicyRef 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 */
2121SecPolicyRef 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 */
2130SecPolicyRef 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
2154errOut:
2155	CFReleaseSafe(options);
2156	CFReleaseSafe(policy);
2157	return NULL;
2158}
2159
2160#endif // TARGET_OS_IPHONE
2161