2 * Copyright (c) 2007-2013 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * SecPolicy.c - Implementation of various X.509 certificate trust policies
28 #include <Security/SecPolicyInternal.h>
29 #include <Security/SecPolicyPriv.h>
30 #include <AssertMacros.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>
47 /********************************************************
48 **************** SecPolicy Constants *******************
49 ********************************************************/
51 // MARK: SecPolicy Constants
53 #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v));
55 /********************************************************
56 ************** Unverified Leaf Checks ******************
57 ********************************************************/
58 CFStringRef kSecPolicyCheckSSLHostname
= CFSTR("SSLHostname");
60 CFStringRef kSecPolicyCheckEmail
= CFSTR("email");
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");
66 /* Checks that the leaf has exactly one Common Name and that it
67 matches the specified string. */
68 CFStringRef kSecPolicyCheckSubjectCommonName
= CFSTR("SubjectCommonName");
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");
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");
78 /* Checks that the leaf has exactly one Organization and that it
79 matches the specified string. */
80 CFStringRef kSecPolicyCheckSubjectOrganization
= CFSTR("SubjectOrganization");
82 /* Checks that the leaf has exactly one Organizational Unit and that it
83 matches the specified string. */
84 CFStringRef kSecPolicyCheckSubjectOrganizationalUnit
= CFSTR("SubjectOrganizationalUnit");
86 /* Check that the leaf is not valid before the specified date (or verifyDate
87 if none is provided?). */
88 CFStringRef kSecPolicyCheckNotValidBefore
= CFSTR("NotValidBefore");
90 CFStringRef kSecPolicyCheckEAPTrustedServerNames
= CFSTR("EAPTrustedServerNames");
92 CFStringRef kSecPolicyCheckCertificatePolicy
= CFSTR("CertificatePolicy");
95 /* Check for basic constraints on leaf to be valid. (rfc5280 check) */
96 CFStringRef kSecPolicyCheckLeafBasicConstraints
= CFSTR("LeafBasicContraints");
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) */
108 /********************************************************
109 ************** Unverified Anchor Checks ****************
110 ********************************************************/
111 CFStringRef kSecPolicyCheckAnchorSHA1
= CFSTR("AnchorSHA1");
113 /* Fake key for isAnchored check. */
114 CFStringRef kSecPolicyCheckAnchorTrusted
= CFSTR("AnchorTrusted");
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) */
123 CFStringRef kSecPolicyCheckValidityStarted
= CFSTR("ValidStarted");
124 CFStringRef kSecPolicyCheckValidityExpired
= CFSTR("ValidExpired");
126 CFStringRef kSecPolicyCheckValidIntermediates
= CFSTR("ValidIntermediates");
127 CFStringRef kSecPolicyCheckValidLeaf
= CFSTR("ValidLeaf");
128 CFStringRef kSecPolicyCheckValidRoot
= CFSTR("ValidRoot");
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");
140 /* Check that the certificate chain length matches the specificed CFNumberRef
142 CFStringRef kSecPolicyCheckChainLength
= CFSTR("ChainLength");
144 /* (rfc5280 check) */
145 CFStringRef kSecPolicyCheckBasicCertificateProcessing
=
146 CFSTR("BasicCertificateProcessing");
148 /********************************************************
149 ******************* Feature toggles ********************
150 ********************************************************/
152 /* Check revocation if specified. */
153 CFStringRef kSecPolicyCheckExtendedValidation
= CFSTR("ExtendedValidation");
154 CFStringRef kSecPolicyCheckRevocation
= CFSTR("Revocation");
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");
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");
166 CFStringRef kSecPolicyCheckLeafMarkerOid
= CFSTR("CheckLeafMarkerOid");
167 CFStringRef kSecPolicyCheckIntermediateMarkerOid
= CFSTR("CheckIntermediateMarkerOid");
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");
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");
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");
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");
243 /* Policies will now change to multiple categories of checks.
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.
248 kSecPolicySLCheck Static Subscriber Certificate Checks
249 kSecPolicySICheck Static Subsidiary CA Checks
250 kSecPolicySACheck Static Anchor Checks
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
302 We need to remember the best successful chain we find, where best is defined by: satisfies as many optional policies as possible.
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.
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.
308 Example sectrust operation in psuedocode:
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
})
320 propagate_subpolicy_results(builder
, chain
, details
);
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
)
326 /* Modify SecPathBuilderIsPartial() to
327 run builder_check(buildier, policies, kSecPolicySICheck) instead
328 of SecCertificateIsValid. Also rename considerExpired to
331 foreach (policy in p_d
) {
332 check_policy(builder
, chain
, policy
, kSecPolicySICheck
, depth
);
334 /* Recalculate since the static checks might have added new dynamic
336 d_p_d
= dynamic_policies
.at_depth(depth
);
337 foreach (policy in d_p_d
) {
338 check_policy(builder
, chain
, policy
, kSecPolicySICheck
, depth
);
340 if (chain
.is_anchored
) {
341 foreach (policy in p_d
) {
342 check_policy(builder
, chain
, policy
, kSecPolicySACheck
, depth
);
344 foreach (policy in d_p_d
) {
345 check_policy(builder
, chain
, policy
, kSecPolicySACheck
, depth
);
347 foreach (policy in p_d
) {
348 check_policy(builder
, chain
, policy
, kSecPolicyDACheck
, depth
);
350 foreach (policy in d_p_d
) {
351 check_policy(builder
, chain
, policy
, kSecPolicyDACheck
, depth
);
354 foreach (policy in policies
) {
355 check_policy(builder
, chain
, policy
, kSecPolicySACheck
, depth
);
356 check_policy(builder
, chain
, policy
, kSecPolicyDACheck
, depth
);
358 foreach (policy in policies
{kSecPolicySDCheck
}) {
363 check_policy(builder
, chain
, policy
, check_class
, details
, depth
) {
365 foreach(check in policy
{check_class
}) {
366 SecPolicyRunCheck(builder
, chain
, check
, details
);
370 foreach (subpolicy in policy
) {
371 if (!check_policy(builder
, chain
, subpolicy
, check_class
,
372 details
{subpolicy
.name
}) && subpolicy
.is_required
, depth
)
376 propagate_subpolicy_results(builder
, chain
, details
);
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
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
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
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
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
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
416 /********************************************************
417 ****************** SecPolicy object ********************
418 ********************************************************/
420 /* CFRuntime registration data. */
421 static pthread_once_t kSecPolicyRegisterClass
= PTHREAD_ONCE_INIT
;
422 static CFTypeID kSecPolicyTypeID
= _kCFRuntimeNotATypeID
;
424 static void SecPolicyDestroy(CFTypeRef cf
) {
425 SecPolicyRef policy
= (SecPolicyRef
) cf
;
426 CFRelease(policy
->_oid
);
427 CFRelease(policy
->_options
);
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
);
437 static CFHashCode
SecPolicyHash(CFTypeRef cf
) {
438 SecPolicyRef policy
= (SecPolicyRef
) cf
;
440 return CFHash(policy
->_oid
) + CFHash(policy
->_options
);
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
);
451 CFStringAppend(desc
, CFSTR(" >"));
456 static void SecPolicyRegisterClass(void) {
457 static const CFRuntimeClass kSecPolicyClass
= {
459 "SecPolicy", /* class name */
462 SecPolicyDestroy
, /* dealloc */
463 SecPolicyEqual
, /* equal */
464 SecPolicyHash
, /* hash */
465 NULL
, /* copyFormattingDesc */
466 SecPolicyDescribe
/* copyDebugDesc */
469 kSecPolicyTypeID
= _CFRuntimeRegisterClass(&kSecPolicyClass
);
472 /* SecPolicy API functions. */
473 CFTypeID
SecPolicyGetTypeID(void) {
474 pthread_once(&kSecPolicyRegisterClass
, SecPolicyRegisterClass
);
475 return kSecPolicyTypeID
;
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.
482 SecPolicyRef
SecPolicyCreate(CFStringRef oid
, CFDictionaryRef options
) {
483 SecPolicyRef result
= NULL
;
485 require(oid
, errOut
);
486 require(options
, errOut
);
488 (SecPolicyRef
)_CFRuntimeCreateInstance(kCFAllocatorDefault
,
489 SecPolicyGetTypeID(),
490 sizeof(struct __SecPolicy
) - sizeof(CFRuntimeBase
), 0), errOut
);
495 result
->_options
= options
;
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.
508 SecPolicyRef policy
= NULL
;
509 CFStringRef name
= NULL
;
510 CFStringRef teamID
= NULL
;
511 Boolean client
= false;
512 require(policyIdentifier
&& (CFStringGetTypeID() == CFGetTypeID(policyIdentifier
)), errOut
);
515 name
= CFDictionaryGetValue(properties
, kSecPolicyName
);
516 teamID
= CFDictionaryGetValue(properties
, kSecPolicyTeamIdentifier
);
518 CFBooleanRef dictionaryClientValue
;
519 client
= (CFDictionaryGetValueIfPresent(properties
, kSecPolicyClient
, (const void **)&dictionaryClientValue
) &&
520 (dictionaryClientValue
!= NULL
) && CFEqual(kCFBooleanTrue
, dictionaryClientValue
));
523 if (CFEqual(policyIdentifier
, kSecPolicyAppleX509Basic
)) {
524 policy
= SecPolicyCreateBasicX509();
526 else if (CFEqual(policyIdentifier
, kSecPolicyAppleSSL
)) {
527 policy
= SecPolicyCreateSSL(!client
, name
);
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
);
535 else if (CFEqual(policyIdentifier
, kSecPolicyAppleIPsec
)) {
536 policy
= SecPolicyCreateIPSec(!client
, name
);
538 else if (CFEqual(policyIdentifier
, kSecPolicyAppleRevocation
)) {
539 policy
= SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod
);
541 else if (CFEqual(policyIdentifier
, kSecPolicyAppleSMIME
)) {
542 policy
= SecPolicyCreateSMIME(kSecSignSMIMEUsage
| kSecAnyEncryptSMIME
, name
);
544 else if (CFEqual(policyIdentifier
, kSecPolicyAppleCodeSigning
)) {
545 policy
= SecPolicyCreateCodeSigning();
547 else if (CFEqual(policyIdentifier
, kSecPolicyAppleIDValidation
)) {
548 policy
= SecPolicyCreateAppleIDAuthorityPolicy();
550 else if (CFEqual(policyIdentifier
, kSecPolicyApplePassbookSigning
)) {
551 policy
= SecPolicyCreatePassbookCardSigner(name
, teamID
);
553 else if (CFEqual(policyIdentifier
, kSecPolicyAppleMobileStore
)) {
554 policy
= SecPolicyCreateMobileStoreSigner();
556 else if (CFEqual(policyIdentifier
, kSecPolicyAppleTestMobileStore
)) {
557 policy
= SecPolicyCreateTestMobileStoreSigner();
559 else if (CFEqual(policyIdentifier
, kSecPolicyAppleEscrowService
)) {
560 policy
= SecPolicyCreateEscrowServiceSigner();
562 else if (CFEqual(policyIdentifier
, kSecPolicyAppleProfileSigner
)) {
563 policy
= SecPolicyCreateConfigurationProfileSigner();
565 else if (CFEqual(policyIdentifier
, kSecPolicyAppleQAProfileSigner
)) {
566 policy
= SecPolicyCreateQAConfigurationProfileSigner();
569 else if (CFEqual(policyIdentifier
, kSecPolicyAppleOTAPKISigner
)) {
570 policy
= SecPolicyCreateOTAPKISigner();
572 else if (CFEqual(policyIdentifier
, kSecPolicyAppleTestOTAPKISigner
)) {
573 policy
= SecPolicyCreateTestOTAPKISigner();
575 else if (CFEqual(policyIdentifier
, kSecPolicyAppleIDValidationRecordSigningPolicy
)) {
576 policy
= SecPolicyCreateAppleIDValidationRecordSigningPolicy();
584 CFDictionaryRef
SecPolicyCopyProperties(SecPolicyRef policyRef
) {
585 // Builds and returns a dictionary which the caller must release.
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
;
594 // Convert private to public OID if we have one
595 CFStringRef outOid
= oid
;
596 if (CFEqual(oid
, kSecPolicyOIDBasicX509
)) {
597 outOid
= kSecPolicyAppleX509Basic
;
599 else if (CFEqual(oid
, kSecPolicyOIDSSLServer
) ||
600 CFEqual(oid
, kSecPolicyOIDSSLClient
)) {
601 outOid
= kSecPolicyAppleSSL
;
602 nameKey
= kSecPolicyCheckSSLHostname
;
604 else if (CFEqual(oid
, kSecPolicyEAPServer
) ||
605 CFEqual(oid
, kSecPolicyEAPClient
)) {
606 outOid
= kSecPolicyAppleEAP
;
607 nameKey
= kSecPolicyCheckEAPTrustedServerNames
;
609 else if (CFEqual(oid
, kSecPolicyOIDIPSecServer
) ||
610 CFEqual(oid
, kSecPolicyOIDIPSecClient
)) {
611 outOid
= kSecPolicyAppleIPsec
;
612 nameKey
= kSecPolicyCheckSSLHostname
;
614 else if (CFEqual(oid
, kSecPolicyOIDRevocation
)) {
615 outOid
= kSecPolicyAppleRevocation
;
617 else if (CFEqual(oid
, kSecPolicyOIDSMIME
)) {
618 outOid
= kSecPolicyAppleSMIME
;
619 nameKey
= kSecPolicyCheckEmail
;
621 else if (CFEqual(oid
, kSecPolicyOIDCodeSigning
)) {
622 outOid
= kSecPolicyAppleCodeSigning
;
624 else if (CFEqual(oid
, kSecPolicyOIDAppleIDAuthority
)) {
625 outOid
= kSecPolicyAppleIDValidation
;
627 else if (CFEqual(oid
, kSecPolicyOIDApplePassbook
)) {
628 outOid
= kSecPolicyApplePassbookSigning
;
630 else if (CFEqual(oid
, kSecPolicyOIDAppleMobileStore
)) {
631 outOid
= kSecPolicyAppleMobileStore
;
633 else if (CFEqual(oid
, kSecPolicyOIDAppleTestMobileStore
)) {
634 outOid
= kSecPolicyAppleTestMobileStore
;
636 else if (CFEqual(oid
, kSecPolicyOIDAppleEscrowService
)) {
637 outOid
= kSecPolicyAppleEscrowService
;
639 else if (CFEqual(oid
, kSecPolicyOIDAppleProfileSigner
)) {
640 outOid
= kSecPolicyAppleProfileSigner
;
642 else if (CFEqual(oid
, kSecPolicyOIDAppleQAProfileSigner
)) {
643 outOid
= kSecPolicyAppleQAProfileSigner
;
646 else if (CFEqual(oid
, kSecPolicyOIDAppleOTAPKIAssetSigner
)) {
647 outOid
= kSecPolicyAppleOTAPKISigner
;
649 else if (CFEqual(oid
, kSecPolicyOIDAppleTestOTAPKIAssetSigner
)) {
650 outOid
= kSecPolicyAppleTestOTAPKISigner
;
652 else if (CFEqual(oid
, kSecPolicyOIDAppleIDValidationRecordSigningPolicy
)) {
653 outOid
= kSecPolicyAppleIDValidationRecordSigningPolicy
;
658 CFDictionarySetValue(properties
, (const void *)kSecPolicyOid
,
659 (const void *)outOid
);
661 // Set kSecPolicyName if we have one
662 if (nameKey
&& policyRef
->_options
) {
663 CFTypeRef name
= (CFTypeRef
) CFDictionaryGetValue(policyRef
->_options
,
666 CFDictionarySetValue(properties
, (const void *)kSecPolicyName
,
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
);
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
;
692 static void SecPolicySetOptionsValue(SecPolicyRef policy
, CFStringRef key
, CFTypeRef value
) {
693 if (!policy
|| !key
) return;
694 CFMutableDictionaryRef options
= (CFMutableDictionaryRef
) policy
->_options
;
696 options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
697 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
698 if (!options
) return;
699 policy
->_options
= options
;
701 CFDictionarySetValue(options
, key
, value
);
704 OSStatus
SecPolicySetProperties(SecPolicyRef policyRef
, CFDictionaryRef properties
) {
705 // Set policy options based on the provided dictionary keys.
707 if (!(policyRef
&& properties
&& (CFDictionaryGetTypeID() == CFGetTypeID(properties
)))) {
710 CFStringRef oid
= (CFStringRef
) CFRetain(policyRef
->_oid
);
711 OSStatus result
= errSecSuccess
;
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
);
725 else result
= errSecParam
;
727 else if (CFEqual(oid
, kSecPolicyEAPServer
) ||
728 CFEqual(oid
, kSecPolicyEAPClient
)) {
729 if ((CFStringGetTypeID() == typeID
) ||
730 (CFArrayGetTypeID() == typeID
)) {
731 SecPolicySetOptionsValue(policyRef
, kSecPolicyCheckEAPTrustedServerNames
, name
);
733 else result
= errSecParam
;
735 else if (CFEqual(oid
, kSecPolicyOIDSMIME
)) {
736 if (CFStringGetTypeID() == typeID
) {
737 SecPolicySetOptionsValue(policyRef
, kSecPolicyCheckEmail
, name
);
739 else result
= errSecParam
;
744 CFTypeRef client
= NULL
;
745 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyClient
,
746 (const void **)&client
) && client
) {
747 if (!(CFBooleanGetTypeID() == CFGetTypeID(client
))) {
748 result
= errSecParam
;
750 else if (CFEqual(client
, kCFBooleanTrue
)) {
751 if (CFEqual(oid
, kSecPolicyOIDSSLServer
)) {
752 SecPolicySetOid(policyRef
, kSecPolicyOIDSSLClient
);
754 else if (CFEqual(oid
, kSecPolicyOIDIPSecServer
)) {
755 SecPolicySetOid(policyRef
, kSecPolicyOIDIPSecClient
);
757 else if (CFEqual(oid
, kSecPolicyEAPServer
)) {
758 SecPolicySetOid(policyRef
, kSecPolicyEAPClient
);
762 if (CFEqual(oid
, kSecPolicyOIDSSLClient
)) {
763 SecPolicySetOid(policyRef
, kSecPolicyOIDSSLServer
);
765 else if (CFEqual(oid
, kSecPolicyOIDIPSecClient
)) {
766 SecPolicySetOid(policyRef
, kSecPolicyOIDIPSecServer
);
768 else if (CFEqual(oid
, kSecPolicyEAPClient
)) {
769 SecPolicySetOid(policyRef
, kSecPolicyEAPServer
);
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")));
790 if (data
[0]) xpc_release(data
[0]);
791 if (data
[1]) xpc_release(data
[1]);
795 static bool SecPolicyAppendToXPCArray(SecPolicyRef policy
, xpc_object_t policies
, CFErrorRef
*error
) {
799 xpc_object_t xpc_policy
= SecPolicyCopyXPCObject(policy
, error
);
803 xpc_array_append_value(policies
, xpc_policy
);
804 xpc_release(xpc_policy
);
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
);
823 static SecPolicyRef
SecPolicyCreateWithXPCObject(xpc_object_t xpc_policy
, CFErrorRef
*error
) {
824 SecPolicyRef policy
= NULL
;
825 CFTypeRef oid
= NULL
;
826 CFTypeRef options
= NULL
;
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")));
841 CFReleaseSafe(options
);
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
));
854 for (ix
= 0; ix
< count
; ++ix
) {
855 SecPolicyRef policy
= SecPolicyCreateWithXPCObject(xpc_array_get_value(xpc_policies
, ix
), error
);
860 CFArraySetValueAtIndex(policies
, ix
, policy
);
869 static void add_element(CFMutableDictionaryRef options
, CFStringRef key
,
871 CFTypeRef old_value
= CFDictionaryGetValue(options
, key
);
873 CFMutableArrayRef array
;
874 if (CFGetTypeID(old_value
) == CFArrayGetTypeID()) {
875 array
= (CFMutableArrayRef
)old_value
;
877 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0,
878 &kCFTypeArrayCallBacks
);
879 CFArrayAppendValue(array
, old_value
);
880 CFDictionarySetValue(options
, key
, array
);
883 CFArrayAppendValue(array
, value
);
885 CFDictionaryAddValue(options
, key
, value
);
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);
894 add_element(options
, kSecPolicyCheckExtendedKeyUsage
, eku
);
899 static void add_ku(CFMutableDictionaryRef options
, SecKeyUsage keyUsage
) {
900 SInt32 dku
= keyUsage
;
901 CFNumberRef ku
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
,
904 add_element(options
, kSecPolicyCheckKeyUsage
, ku
);
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);
914 add_element(options
, policy_key
, oid_data
);
919 static void add_leaf_marker_value(CFMutableDictionaryRef options
, const DERItem
*markerOid
, CFStringRef string_value
) {
921 CFTypeRef policyData
= NULL
;
923 if (NULL
== string_value
) {
924 policyData
= CFDataCreate(kCFAllocatorDefault
,
925 markerOid
? markerOid
->data
: NULL
,
926 markerOid
? markerOid
->length
: 0);
928 CFStringRef oid_as_string
= SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault
, markerOid
);
930 const void *key
[1] = { oid_as_string
};
931 const void *value
[1] = { string_value
};
932 policyData
= CFDictionaryCreate(kCFAllocatorDefault
,
934 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
935 CFReleaseNull(oid_as_string
);
938 add_element(options
, kSecPolicyCheckLeafMarkerOid
, policyData
);
940 CFReleaseNull(policyData
);
944 static void add_leaf_marker(CFMutableDictionaryRef options
, const DERItem
*markerOid
) {
945 add_leaf_marker_value(options
, markerOid
, NULL
);
949 static void add_certificate_policy_oid(CFMutableDictionaryRef options
, const DERItem
*certificatePolicyOid
, CFStringRef string_value
) {
950 CFTypeRef certificatePolicyData
= NULL
;
952 if (NULL
== string_value
) {
953 certificatePolicyData
= CFDataCreate(kCFAllocatorDefault
,
954 certificatePolicyOid
? certificatePolicyOid
->data
: NULL
,
955 certificatePolicyOid
? certificatePolicyOid
->length
: 0);
957 CFStringRef oid_as_string
= SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault
, certificatePolicyOid
);
959 const void *key
[1] = { oid_as_string
};
960 const void *value
[1] = { string_value
};
961 certificatePolicyData
= CFDictionaryCreate(kCFAllocatorDefault
,
963 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
964 CFReleaseNull(oid_as_string
);
967 add_element(options
, kSecPolicyCheckCertificatePolicy
, certificatePolicyData
);
969 CFReleaseNull(certificatePolicyData
);
972 // Routines for adding dictionary entries for policies.
975 // X.509, but missing validity requirements.
976 static void SecPolicyAddBasicCertOptions(CFMutableDictionaryRef options
)
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
);
986 static void SecPolicyAddBasicX509Options(CFMutableDictionaryRef options
)
988 SecPolicyAddBasicCertOptions(options
);
989 CFDictionaryAddValue(options
, kSecPolicyCheckValidIntermediates
, kCFBooleanTrue
);
990 CFDictionaryAddValue(options
, kSecPolicyCheckValidLeaf
, kCFBooleanTrue
);
991 CFDictionaryAddValue(options
, kSecPolicyCheckValidRoot
, kCFBooleanTrue
);
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
);
998 static bool SecPolicyAddChainLengthOptions(CFMutableDictionaryRef options
, CFIndex length
)
1000 bool result
= false;
1001 CFNumberRef lengthAsCF
= NULL
;
1003 require(lengthAsCF
= CFNumberCreate(kCFAllocatorDefault
,
1004 kCFNumberCFIndexType
, &length
), errOut
);
1005 CFDictionaryAddValue(options
, kSecPolicyCheckChainLength
, lengthAsCF
);
1010 CFReleaseSafe(lengthAsCF
);
1014 static bool SecPolicyAddAnchorSHA1Options(CFMutableDictionaryRef options
,
1015 const UInt8 anchorSha1
[kSecPolicySHA1Size
])
1017 bool success
= false;
1018 CFDataRef anchorData
= NULL
;
1020 require(anchorData
= CFDataCreate(kCFAllocatorDefault
, anchorSha1
, kSecPolicySHA1Size
), errOut
);
1021 add_element(options
, kSecPolicyCheckAnchorSHA1
, anchorData
);
1026 CFReleaseSafe(anchorData
);
1030 static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef options
)
1032 return SecPolicyAddAnchorSHA1Options(options
, kAppleCASHA1
);
1036 static bool SecPolicyAddAppleTESTAnchorOptions(CFMutableDictionaryRef options
)
1038 return SecPolicyAddAnchorSHA1Options(options
, kAppleTESTCASHA1
);
1043 // Policy Creation Functions
1045 SecPolicyRef
SecPolicyCreateBasicX509(void) {
1046 CFMutableDictionaryRef options
= NULL
;
1047 SecPolicyRef result
= NULL
;
1049 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1050 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1052 SecPolicyAddBasicX509Options(options
);
1053 CFDictionaryAddValue(options
, kSecPolicyCheckNoNetworkAccess
,
1056 require(result
= SecPolicyCreate(kSecPolicyOIDBasicX509
, options
), errOut
);
1059 CFReleaseSafe(options
);
1063 SecPolicyRef
SecPolicyCreateSSL(Boolean server
, CFStringRef hostname
) {
1064 CFMutableDictionaryRef options
= NULL
;
1065 SecPolicyRef result
= NULL
;
1067 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1068 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1070 SecPolicyAddBasicX509Options(options
);
1073 CFDictionaryAddValue(options
, kSecPolicyCheckKeyUsage
,
1078 CFDictionaryAddValue(options
, kSecPolicyCheckSSLHostname
, hostname
);
1081 CFDictionaryAddValue(options
, kSecPolicyCheckBlackListedLeaf
, kCFBooleanTrue
);
1082 CFDictionaryAddValue(options
, kSecPolicyCheckGrayListedLeaf
, kCFBooleanTrue
);
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. */
1090 /* We always allow certification that specify oidAnyExtendedKeyUsage. */
1091 add_eku(options
, NULL
); /* eku extension is optional */
1092 add_eku(options
, &oidAnyExtendedKeyUsage
);
1094 add_eku(options
, &oidExtendedKeyUsageServerAuth
);
1095 add_eku(options
, &oidExtendedKeyUsageMicrosoftSGC
);
1096 add_eku(options
, &oidExtendedKeyUsageNetscapeSGC
);
1098 add_eku(options
, &oidExtendedKeyUsageClientAuth
);
1101 require(result
= SecPolicyCreate(
1102 server
? kSecPolicyOIDSSLServer
: kSecPolicyOIDSSLClient
,
1106 CFReleaseSafe(options
);
1110 SecPolicyRef
SecPolicyCreateiPhoneActivation(void) {
1111 CFMutableDictionaryRef options
= NULL
;
1112 SecPolicyRef result
= NULL
;
1114 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1115 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1117 SecPolicyAddBasicCertOptions(options
);
1120 CFDictionaryAddValue(options
, kSecPolicyCheckKeyUsage
,
1122 CFDictionaryAddValue(options
, kSecPolicyCheckExtendedKeyUsage
,
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"));
1135 require(SecPolicyAddChainLengthOptions(options
, 3), errOut
);
1136 require(SecPolicyAddAppleAnchorOptions(options
), errOut
);
1138 require(result
= SecPolicyCreate(kSecPolicyOIDiPhoneActivation
, options
),
1142 CFReleaseSafe(options
);
1146 SecPolicyRef
SecPolicyCreateiPhoneDeviceCertificate(void) {
1147 CFMutableDictionaryRef options
= NULL
;
1148 SecPolicyRef result
= NULL
;
1150 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1151 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1153 SecPolicyAddBasicCertOptions(options
);
1156 CFDictionaryAddValue(options
, kSecPolicyCheckKeyUsage
,
1158 CFDictionaryAddValue(options
, kSecPolicyCheckExtendedKeyUsage
,
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"));
1168 require(SecPolicyAddChainLengthOptions(options
, 4), errOut
);
1169 require(SecPolicyAddAppleAnchorOptions(options
), errOut
);
1171 require(result
= SecPolicyCreate(kSecPolicyOIDiPhoneDeviceCertificate
, options
),
1175 CFReleaseSafe(options
);
1179 SecPolicyRef
SecPolicyCreateFactoryDeviceCertificate(void) {
1180 CFMutableDictionaryRef options
= NULL
;
1181 SecPolicyRef result
= NULL
;
1183 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1184 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1186 SecPolicyAddBasicCertOptions(options
);
1189 CFDictionaryAddValue(options
, kSecPolicyCheckKeyUsage
,
1191 CFDictionaryAddValue(options
, kSecPolicyCheckExtendedKeyUsage
,
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
);
1199 require(result
= SecPolicyCreate(kSecPolicyOIDFactoryDeviceCertificate
, options
),
1203 CFReleaseSafe(options
);
1207 SecPolicyRef
SecPolicyCreateiAP(void) {
1208 CFMutableDictionaryRef options
= NULL
;
1209 SecPolicyRef result
= NULL
;
1210 CFTimeZoneRef tz
= NULL
;
1211 CFDateRef date
= NULL
;
1213 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1214 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1216 SecPolicyAddBasicCertOptions(options
);
1218 CFDictionaryAddValue(options
, kSecPolicyCheckSubjectCommonNamePrefix
,
1221 CFGregorianDate gd
= {
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
);
1234 require(result
= SecPolicyCreate(kSecPolicyOIDiAP
, options
),
1238 CFReleaseSafe(date
);
1240 CFReleaseSafe(options
);
1244 SecPolicyRef
SecPolicyCreateiTunesStoreURLBag(void) {
1245 CFMutableDictionaryRef options
= NULL
;
1246 SecPolicyRef result
= NULL
;
1249 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1250 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1252 SecPolicyAddBasicCertOptions(options
);
1254 CFDictionaryAddValue(options
, kSecPolicyCheckSubjectOrganization
,
1255 CFSTR("Apple Inc."));
1256 CFDictionaryAddValue(options
, kSecPolicyCheckSubjectCommonName
,
1257 CFSTR("iTunes Store URL Bag"));
1259 require(SecPolicyAddChainLengthOptions(options
, 2), errOut
);
1260 require(SecPolicyAddAnchorSHA1Options(options
, kITMSCASHA1
), errOut
);
1262 require(result
= SecPolicyCreate(kSecPolicyOIDiTunesStoreURLBag
, options
), errOut
);
1265 CFReleaseSafe(options
);
1269 SecPolicyRef
SecPolicyCreateEAP(Boolean server
, CFArrayRef trustedServerNames
) {
1270 CFMutableDictionaryRef options
= NULL
;
1271 SecPolicyRef result
= NULL
;
1273 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1274 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1276 SecPolicyAddBasicX509Options(options
);
1279 CFDictionaryAddValue(options
, kSecPolicyCheckKeyUsage
,
1281 CFDictionaryAddValue(options
, kSecPolicyCheckExtendedKeyUsage
,
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
,
1289 if (trustedServerNames
) {
1290 CFDictionaryAddValue(options
, kSecPolicyCheckEAPTrustedServerNames
, trustedServerNames
);
1293 require(result
= SecPolicyCreate(
1294 server
? kSecPolicyEAPServer
: kSecPolicyEAPClient
,
1298 CFReleaseSafe(options
);
1302 SecPolicyRef
SecPolicyCreateIPSec(Boolean server
, CFStringRef hostname
) {
1303 CFMutableDictionaryRef options
= NULL
;
1304 SecPolicyRef result
= NULL
;
1306 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1307 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1309 SecPolicyAddBasicX509Options(options
);
1312 CFDictionaryAddValue(options
, kSecPolicyCheckSSLHostname
, hostname
);
1315 /* Require oidExtendedKeyUsageIPSec if Extended Keyusage Extention is
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
1321 ipsecEndSystem 1.3.6.1.5.5.7.3.5
1323 ipsecTunnel 1.3.6.1.5.5.7.3.6
1324 ipsecUser 1.3.6.1.5.5.7.3.7
1326 //add_eku(options, NULL); /* eku extension is optional */
1327 //add_eku(options, &oidAnyExtendedKeyUsage);
1328 //add_eku(options, &oidExtendedKeyUsageIPSec);
1330 require(result
= SecPolicyCreate(
1331 server
? kSecPolicyOIDIPSecServer
: kSecPolicyOIDIPSecClient
,
1335 CFReleaseSafe(options
);
1339 SecPolicyRef
SecPolicyCreateiPhoneApplicationSigning(void) {
1340 CFMutableDictionaryRef options
= NULL
;
1341 SecPolicyRef result
= NULL
;
1343 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1344 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1346 SecPolicyAddBasicCertOptions(options
);
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"));
1357 require(SecPolicyAddChainLengthOptions(options
, 3), errOut
);
1358 require(SecPolicyAddAppleAnchorOptions(options
), errOut
);
1360 add_eku(options
, NULL
); /* eku extension is optional */
1361 add_eku(options
, &oidAnyExtendedKeyUsage
);
1362 add_eku(options
, &oidExtendedKeyUsageCodeSigning
);
1364 require(result
= SecPolicyCreate(kSecPolicyOIDiPhoneApplicationSigning
, options
),
1367 /* 1.2.840.113635.100.6.1.3, non-critical: DER:05:00 - application signing */
1370 CFReleaseSafe(options
);
1374 SecPolicyRef
SecPolicyCreateiPhoneProfileApplicationSigning(void) {
1375 CFMutableDictionaryRef options
= NULL
;
1376 SecPolicyRef result
= NULL
;
1378 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1379 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1380 CFDictionaryAddValue(options
, kSecPolicyCheckRevocation
, kCFBooleanFalse
);
1381 CFDictionaryAddValue(options
, kSecPolicyCheckValidLeaf
, kCFBooleanFalse
);
1383 require(result
= SecPolicyCreate(kSecPolicyOIDiPhoneProfileApplicationSigning
,
1387 CFReleaseSafe(options
);
1391 SecPolicyRef
SecPolicyCreateiPhoneProvisioningProfileSigning(void) {
1392 CFMutableDictionaryRef options
= NULL
;
1393 SecPolicyRef result
= NULL
;
1395 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1396 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1398 SecPolicyAddBasicCertOptions(options
);
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"));
1409 require(SecPolicyAddChainLengthOptions(options
, 3), errOut
);
1410 require(SecPolicyAddAppleAnchorOptions(options
), errOut
);
1412 require(result
= SecPolicyCreate(kSecPolicyOIDiPhoneProvisioningProfileSigning
, options
),
1415 /* 1.2.840.113635.100.6.2.2.1, non-critical: DER:05:00 - provisioning profile */
1418 CFReleaseSafe(options
);
1422 SecPolicyRef
SecPolicyCreateOCSPSigner(void) {
1423 CFMutableDictionaryRef options
= NULL
;
1424 SecPolicyRef result
= NULL
;
1426 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1427 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1429 SecPolicyAddBasicX509Options(options
);
1431 /* Require id-kp-OCSPSigning extendedKeyUsage to be present, not optional. */
1432 add_eku(options
, &oidExtendedKeyUsageOCSPSigning
);
1434 require(result
= SecPolicyCreate(kSecPolicyOIDOCSPSigner
, options
), errOut
);
1437 CFReleaseSafe(options
);
1441 SecPolicyRef
SecPolicyCreateRevocation(CFOptionFlags revocationFlags
) {
1442 CFMutableDictionaryRef options
= NULL
;
1443 SecPolicyRef result
= NULL
;
1445 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1446 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
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.
1452 if (revocationFlags
& kSecRevocationOCSPMethod
) {
1453 CFDictionaryAddValue(options
, kSecPolicyCheckRevocation
, kCFBooleanFalse
);
1455 else if (revocationFlags
& kSecRevocationCRLMethod
) {
1456 CFDictionaryAddValue(options
, kSecPolicyCheckRevocation
, kCFBooleanTrue
);
1459 //FIXME: check additional revocation flags
1462 /* Only flag bits 0-4 are currently defined */
1463 require(((revocationFlags
>> 5) == 0), errOut
);
1465 require(result
= SecPolicyCreate(kSecPolicyOIDRevocation
, options
), errOut
);
1468 CFReleaseSafe(options
);
1472 SecPolicyRef
SecPolicyCreateSMIME(CFIndex smimeUsage
, CFStringRef email
) {
1473 CFMutableDictionaryRef options
= NULL
;
1474 SecPolicyRef result
= NULL
;
1476 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1477 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1479 SecPolicyAddBasicX509Options(options
);
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
);
1487 if (smimeUsage
& kSecKeyEncryptSMIMEUsage
) {
1488 add_ku(options
, kSecKeyUsageKeyEncipherment
);
1490 if (smimeUsage
& kSecDataEncryptSMIMEUsage
) {
1491 add_ku(options
, kSecKeyUsageDataEncipherment
);
1493 if (smimeUsage
& kSecKeyExchangeDecryptSMIMEUsage
) {
1494 add_ku(options
, kSecKeyUsageKeyAgreement
| kSecKeyUsageDecipherOnly
);
1496 if (smimeUsage
& kSecKeyExchangeEncryptSMIMEUsage
) {
1497 add_ku(options
, kSecKeyUsageKeyAgreement
| kSecKeyUsageEncipherOnly
);
1499 if (smimeUsage
& kSecKeyExchangeBothSMIMEUsage
) {
1500 add_ku(options
, kSecKeyUsageKeyAgreement
| kSecKeyUsageEncipherOnly
| kSecKeyUsageDecipherOnly
);
1504 CFDictionaryAddValue(options
, kSecPolicyCheckEmail
, email
);
1507 /* RFC 3850 paragraph 4.4.4
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.
1516 add_eku(options
, NULL
); /* eku extension is optional */
1517 add_eku(options
, &oidAnyExtendedKeyUsage
);
1518 add_eku(options
, &oidExtendedKeyUsageEmailProtection
);
1520 require(result
= SecPolicyCreate(kSecPolicyOIDSMIME
, options
), errOut
);
1523 CFReleaseSafe(options
);
1527 SecPolicyRef
SecPolicyCreateCodeSigning(void) {
1528 CFMutableDictionaryRef options
= NULL
;
1529 SecPolicyRef result
= NULL
;
1531 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1532 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1534 SecPolicyAddBasicX509Options(options
);
1536 /* If the key usage extension is present we accept it having either of
1538 add_ku(options
, kSecKeyUsageDigitalSignature
);
1539 add_ku(options
, kSecKeyUsageNonRepudiation
);
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
);
1548 require(result
= SecPolicyCreate(kSecPolicyOIDCodeSigning
, options
),
1552 CFReleaseSafe(options
);
1556 /* Explicitly leave out empty subject/subjectaltname check */
1557 SecPolicyRef
SecPolicyCreateLockdownPairing(void) {
1558 CFMutableDictionaryRef options
= NULL
;
1559 SecPolicyRef result
= NULL
;
1561 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1562 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1563 //CFDictionaryAddValue(options, kSecPolicyCheckBasicCertificateProcessing,
1565 CFDictionaryAddValue(options
, kSecPolicyCheckCriticalExtensions
,
1567 CFDictionaryAddValue(options
, kSecPolicyCheckIdLinkage
,
1569 CFDictionaryAddValue(options
, kSecPolicyCheckBasicContraints
,
1571 CFDictionaryAddValue(options
, kSecPolicyCheckQualifiedCertStatements
,
1574 require(result
= SecPolicyCreate(kSecPolicyOIDLockdownPairing
, options
), errOut
);
1577 CFReleaseSafe(options
);
1581 SecPolicyRef
SecPolicyCreateURLBag(void) {
1582 CFMutableDictionaryRef options
= NULL
;
1583 SecPolicyRef result
= NULL
;
1585 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1586 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1588 SecPolicyAddBasicCertOptions(options
);
1590 add_eku(options
, &oidExtendedKeyUsageCodeSigning
);
1592 require(result
= SecPolicyCreate(kSecPolicyOIDURLBag
, options
), errOut
);
1595 CFReleaseSafe(options
);
1599 static bool SecPolicyAddAppleCertificationAuthorityOptions(CFMutableDictionaryRef options
, bool honorValidity
)
1601 bool success
= false;
1604 SecPolicyAddBasicX509Options(options
);
1606 SecPolicyAddBasicCertOptions(options
);
1609 CFDictionaryAddValue(options
, kSecPolicyCheckKeyUsage
,
1611 CFDictionaryAddValue(options
, kSecPolicyCheckExtendedKeyUsage
,
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"));
1621 require(SecPolicyAddChainLengthOptions(options
, 3), errOut
);
1622 require(SecPolicyAddAppleAnchorOptions(options
), errOut
);
1630 static SecPolicyRef
SecPolicyCreateAppleCertificationAuthorityPolicy(CFStringRef policyOID
, CFStringRef leafName
, bool honorValidity
)
1632 CFMutableDictionaryRef options
= NULL
;
1633 SecPolicyRef result
= NULL
;
1635 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1636 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), errOut
);
1638 require(SecPolicyAddAppleCertificationAuthorityOptions(options
, honorValidity
), errOut
);
1640 CFDictionaryAddValue(options
, kSecPolicyCheckSubjectCommonName
, leafName
);
1642 require(result
= SecPolicyCreate(policyOID
, options
),
1646 CFReleaseSafe(options
);
1651 SecPolicyRef
SecPolicyCreateOTATasking(void)
1653 return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDOTATasking
, CFSTR("OTA Task Signing"), true);
1656 SecPolicyRef
SecPolicyCreateMobileAsset(void)
1658 return SecPolicyCreateAppleCertificationAuthorityPolicy(kSecPolicyOIDMobileAsset
, CFSTR("Asset Manifest Signing"), false);
1661 SecPolicyRef
SecPolicyCreateAppleIDAuthorityPolicy(void)
1663 SecPolicyRef result
= NULL
;
1664 CFMutableDictionaryRef options
= NULL
;
1665 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1666 &kCFTypeDictionaryKeyCallBacks
,
1667 &kCFTypeDictionaryValueCallBacks
), out
);
1669 //Leaf appears to be a SSL only cert, so policy should expand on that policy
1670 SecPolicyAddBasicX509Options(options
);
1672 // Apple CA anchored
1673 require(SecPolicyAddAppleAnchorOptions(options
), out
);
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
);
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
);
1683 require(result
= SecPolicyCreate(kSecPolicyOIDAppleIDAuthority
, options
), out
);
1686 CFReleaseSafe(options
);
1690 static SecPolicyRef
_SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer
, CFStringRef teamIdentifier
, bool requireTeamID
)
1692 SecPolicyRef result
= NULL
;
1693 CFMutableDictionaryRef options
= NULL
;
1694 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1695 &kCFTypeDictionaryKeyCallBacks
,
1696 &kCFTypeDictionaryValueCallBacks
), out
);
1698 SecPolicyAddBasicX509Options(options
);
1699 SecPolicyAddAppleAnchorOptions(options
);
1701 if (teamIdentifier
) {
1702 // If supplied, teamIdentifier must match subject OU field
1703 CFDictionaryAddValue(options
, kSecPolicyCheckSubjectOrganizationalUnit
, teamIdentifier
);
1706 // If not supplied, and it was required, fail
1707 require(!requireTeamID
, out
);
1710 // Must be both push and 3rd party package signing
1711 add_leaf_marker_value(options
, &oidAppleInstallerPackagingSigningExternal
, cardIssuer
);
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);
1716 // And Shoebox signing eku
1717 add_eku(options
, &oidAppleExtendedKeyUsageShoebox
);
1719 require(result
= SecPolicyCreate(kSecPolicyOIDApplePassbook
, options
), out
);
1722 CFReleaseSafe(options
);
1726 SecPolicyRef
SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer
, CFStringRef teamIdentifier
)
1728 return _SecPolicyCreatePassbookCardSigner(cardIssuer
, teamIdentifier
, true);
1732 SecPolicyRef
SecPolicyCreateShoeboxCardSigner(CFStringRef cardIssuer
)
1734 return _SecPolicyCreatePassbookCardSigner(cardIssuer
, nil
, false);
1737 static SecPolicyRef
CreateMobileStoreSigner(Boolean forTest
)
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
);
1748 require(SecPolicyAddChainLengthOptions(options
, 3), errOut
);
1750 CFDictionaryAddValue(options
, kSecPolicyCheckIssuerCommonName
,
1751 CFSTR("Apple System Integration 2 Certification Authority"));
1753 add_ku(options
, kSecKeyUsageDigitalSignature
);
1755 const DERItem
* pOID
= (forTest
) ? &oidApplePolicyTestMobileStore
: &oidApplePolicyMobileStore
;
1757 add_certificate_policy_oid(options
, pOID
, NULL
);
1759 require(result
= SecPolicyCreate(kSecPolicyOIDAppleMobileStore
, options
), errOut
);
1762 CFReleaseSafe(options
);
1766 SecPolicyRef
SecPolicyCreateMobileStoreSigner(void)
1769 return CreateMobileStoreSigner(false);
1772 SecPolicyRef
SecPolicyCreateTestMobileStoreSigner(void)
1775 return CreateMobileStoreSigner(true);
1779 CF_RETURNS_RETAINED SecPolicyRef
SecPolicyCreateEscrowServiceSigner(void)
1781 SecPolicyRef result
= NULL
;
1782 CFMutableDictionaryRef options
= NULL
;
1783 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1784 &kCFTypeDictionaryKeyCallBacks
,
1785 &kCFTypeDictionaryValueCallBacks
), errOut
);
1787 SecPolicyAddBasicX509Options(options
);
1790 add_ku(options
, kSecKeyUsageKeyEncipherment
);
1792 //add_leaf_marker(options, &oidApplePolicyEscrowService);
1793 require(SecPolicyAddChainLengthOptions(options
, 2), errOut
);
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
)))
1805 for (CFIndex iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1807 SecCertificateRef aCert
= (SecCertificateRef
)CFArrayGetValueAtIndex(anArray
, iCnt
);
1811 CFDataRef sha_data
= SecCertificateGetSHA1Digest(aCert
);
1812 if (NULL
!= sha_data
)
1814 const UInt8
* pSHAData
= CFDataGetBytePtr(sha_data
);
1815 if (NULL
!= pSHAData
)
1817 SecPolicyAddAnchorSHA1Options(options
, pSHAData
);
1831 require(result
= SecPolicyCreate(kSecPolicyOIDAppleEscrowService
, options
), errOut
);
1834 CFReleaseSafe(options
);
1838 SecCertificateRef
SecPolicyCopyEscrowRootCertificate(void)
1840 SecCertificateRef result
= NULL
;
1845 SecPolicyRef
SecPolicyCreateConfigurationProfileSigner(void)
1847 SecPolicyRef result
= NULL
;
1848 CFMutableDictionaryRef options
= NULL
;
1849 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1850 &kCFTypeDictionaryKeyCallBacks
,
1851 &kCFTypeDictionaryValueCallBacks
), errOut
);
1853 SecPolicyAddBasicX509Options(options
);
1854 SecPolicyAddAppleAnchorOptions(options
);
1856 // Require the profile signing EKU
1857 add_eku(options
, &oidAppleExtendedKeyUsageProfileSigning
);
1859 require(result
= SecPolicyCreate(kSecPolicyOIDAppleProfileSigner
, options
), errOut
);
1862 CFReleaseSafe(options
);
1867 SecPolicyRef
SecPolicyCreateQAConfigurationProfileSigner(void)
1869 SecPolicyRef result
= NULL
;
1870 CFMutableDictionaryRef options
= NULL
;
1871 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1872 &kCFTypeDictionaryKeyCallBacks
,
1873 &kCFTypeDictionaryValueCallBacks
), errOut
);
1875 SecPolicyAddBasicX509Options(options
);
1876 SecPolicyAddAppleAnchorOptions(options
);
1878 // Require the QA profile signing EKU
1879 add_eku(options
, &oidAppleExtendedKeyUsageQAProfileSigning
);
1881 require(result
= SecPolicyCreate(kSecPolicyOIDAppleQAProfileSigner
, options
), errOut
);
1884 CFReleaseSafe(options
);
1888 #if TARGET_OS_IPHONE
1889 SecPolicyRef
SecPolicyCreateOTAPKISigner(void)
1891 SecPolicyRef result
= NULL
;
1892 CFMutableDictionaryRef options
= NULL
;
1893 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1894 &kCFTypeDictionaryKeyCallBacks
,
1895 &kCFTypeDictionaryValueCallBacks
), errOut
);
1896 SecPolicyAddBasicX509Options(options
);
1898 SecPolicyAddAnchorSHA1Options(options
, kApplePKISettingsAuthority
);
1899 require(SecPolicyAddChainLengthOptions(options
, 2), errOut
);
1901 require(result
= SecPolicyCreate(kSecPolicyOIDAppleOTAPKIAssetSigner
, options
), errOut
);
1904 CFReleaseSafe(options
);
1910 SecPolicyRef
SecPolicyCreateTestOTAPKISigner(void)
1912 SecPolicyRef result
= NULL
;
1913 CFMutableDictionaryRef options
= NULL
;
1914 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1915 &kCFTypeDictionaryKeyCallBacks
,
1916 &kCFTypeDictionaryValueCallBacks
), errOut
);
1917 SecPolicyAddBasicX509Options(options
);
1919 SecPolicyAddAnchorSHA1Options(options
, kAppleTestPKISettingsAuthority
);
1920 require(SecPolicyAddChainLengthOptions(options
, 2), errOut
);
1922 require(result
= SecPolicyCreate(kSecPolicyOIDAppleTestOTAPKIAssetSigner
, options
), errOut
);
1925 CFReleaseSafe(options
);
1930 SecPolicyRef
SecPolicyCreateAppleIDValidationRecordSigningPolicy(void)
1932 SecPolicyRef result
= NULL
;
1933 CFMutableDictionaryRef options
= NULL
;
1934 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
1935 &kCFTypeDictionaryKeyCallBacks
,
1936 &kCFTypeDictionaryValueCallBacks
), errOut
);
1938 //Leaf appears to be a SSL only cert, so policy should expand on that policy
1939 SecPolicyAddBasicX509Options(options
);
1941 // Apple CA anchored
1942 require(SecPolicyAddAppleAnchorOptions(options
), errOut
);
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
);
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
);
1954 // Ensure that revocation is checked (OCSP)
1955 CFDictionaryAddValue(options
, kSecPolicyCheckRevocation
, kCFBooleanFalse
);
1957 require(result
= SecPolicyCreate(kSecPolicyOIDAppleIDValidationRecordSigningPolicy
, options
), errOut
);
1960 CFReleaseSafe(options
);
1964 #endif // TARGET_OS_IPHONE