2 * Copyright (c) 2002-2014 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@
24 #include <CoreFoundation/CFString.h>
25 #include <CoreFoundation/CFNumber.h>
26 #include <CoreFoundation/CFArray.h>
27 #include <Security/SecItem.h>
28 #include <Security/SecPolicy.h>
29 #include <Security/SecPolicyPriv.h>
30 #include <Security/SecCertificate.h>
31 #include <Security/SecCertificatePriv.h>
32 #include <security_keychain/Policies.h>
33 #include <security_keychain/PolicyCursor.h>
34 #include "SecBridge.h"
35 #include "utilities/SecCFRelease.h"
38 // String constant declarations
40 #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v));
42 SEC_CONST_DECL (kSecPolicyAppleX509Basic
, "1.2.840.113635.100.1.2");
43 SEC_CONST_DECL (kSecPolicyAppleSSL
, "1.2.840.113635.100.1.3");
44 SEC_CONST_DECL (kSecPolicyAppleSMIME
, "1.2.840.113635.100.1.8");
45 SEC_CONST_DECL (kSecPolicyAppleEAP
, "1.2.840.113635.100.1.9");
46 SEC_CONST_DECL (kSecPolicyAppleIPsec
, "1.2.840.113635.100.1.11");
47 SEC_CONST_DECL (kSecPolicyAppleiChat
, "1.2.840.113635.100.1.12");
48 SEC_CONST_DECL (kSecPolicyApplePKINITClient
, "1.2.840.113635.100.1.14");
49 SEC_CONST_DECL (kSecPolicyApplePKINITServer
, "1.2.840.113635.100.1.15");
50 SEC_CONST_DECL (kSecPolicyAppleCodeSigning
, "1.2.840.113635.100.1.16");
51 SEC_CONST_DECL (kSecPolicyApplePackageSigning
, "1.2.840.113635.100.1.17");
52 SEC_CONST_DECL (kSecPolicyAppleIDValidation
, "1.2.840.113635.100.1.18");
53 SEC_CONST_DECL (kSecPolicyMacAppStoreReceipt
, "1.2.840.113635.100.1.19");
54 SEC_CONST_DECL (kSecPolicyAppleTimeStamping
, "1.2.840.113635.100.1.20");
55 SEC_CONST_DECL (kSecPolicyAppleRevocation
, "1.2.840.113635.100.1.21");
56 SEC_CONST_DECL (kSecPolicyApplePassbookSigning
, "1.2.840.113635.100.1.22");
57 SEC_CONST_DECL (kSecPolicyAppleMobileStore
, "1.2.840.113635.100.1.23");
58 SEC_CONST_DECL (kSecPolicyAppleEscrowService
, "1.2.840.113635.100.1.24");
59 SEC_CONST_DECL (kSecPolicyAppleProfileSigner
, "1.2.840.113635.100.1.25");
60 SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner
, "1.2.840.113635.100.1.26");
61 SEC_CONST_DECL (kSecPolicyAppleTestMobileStore
, "1.2.840.113635.100.1.27");
63 SEC_CONST_DECL (kSecPolicyAppleOTAPKISigner
, "1.2.840.113635.100.1.28");
64 SEC_CONST_DECL (kSecPolicyAppleTestOTAPKISigner
, "1.2.840.113635.100.1.29");
65 /* FIXME: this policy name should be deprecated and replaced with "kSecPolicyAppleIDValidationRecordSigning" */
66 SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy
, "1.2.840.113625.100.1.30");
67 SEC_CONST_DECL (kSecPolicyAppleSMPEncryption
, "1.2.840.113625.100.1.31");
68 SEC_CONST_DECL (kSecPolicyAppleTestSMPEncryption
, "1.2.840.113625.100.1.32");
70 SEC_CONST_DECL (kSecPolicyAppleServerAuthentication
, "1.2.840.113635.100.1.33");
71 SEC_CONST_DECL (kSecPolicyApplePCSEscrowService
, "1.2.840.113635.100.1.34");
73 SEC_CONST_DECL (kSecPolicyOid
, "SecPolicyOid");
74 SEC_CONST_DECL (kSecPolicyName
, "SecPolicyName");
75 SEC_CONST_DECL (kSecPolicyClient
, "SecPolicyClient");
76 SEC_CONST_DECL (kSecPolicyRevocationFlags
, "SecPolicyRevocationFlags");
77 SEC_CONST_DECL (kSecPolicyTeamIdentifier
, "SecPolicyTeamIdentifier");
79 SEC_CONST_DECL (kSecPolicyKU_DigitalSignature
, "CE_KU_DigitalSignature");
80 SEC_CONST_DECL (kSecPolicyKU_NonRepudiation
, "CE_KU_NonRepudiation");
81 SEC_CONST_DECL (kSecPolicyKU_KeyEncipherment
, "CE_KU_KeyEncipherment");
82 SEC_CONST_DECL (kSecPolicyKU_DataEncipherment
, "CE_KU_DataEncipherment");
83 SEC_CONST_DECL (kSecPolicyKU_KeyAgreement
, "CE_KU_KeyAgreement");
84 SEC_CONST_DECL (kSecPolicyKU_KeyCertSign
, "CE_KU_KeyCertSign");
85 SEC_CONST_DECL (kSecPolicyKU_CRLSign
, "CE_KU_CRLSign");
86 SEC_CONST_DECL (kSecPolicyKU_EncipherOnly
, "CE_KU_EncipherOnly");
87 SEC_CONST_DECL (kSecPolicyKU_DecipherOnly
, "CE_KU_DecipherOnly");
91 SecPolicyRef
SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid
*oidPtr
);
92 extern "C" { CFArrayRef
SecPolicyCopyEscrowRootCertificates(void); }
98 SecPolicyGetTypeID(void)
101 return gTypes().Policy
.typeID
;
102 END_SECAPI1(_kCFRuntimeNotATypeID
)
107 // Sec API bridge functions
110 SecPolicyGetOID(SecPolicyRef policyRef
, CSSM_OID
* oid
)
113 Required(oid
) = Policy::required(policyRef
)->oid();
118 SecPolicyGetValue(SecPolicyRef policyRef
, CSSM_DATA
* value
)
121 Required(value
) = Policy::required(policyRef
)->value();
126 SecPolicyCopyProperties(SecPolicyRef policyRef
)
128 /* can't use SECAPI macros, since this function does not return OSStatus */
129 CFDictionaryRef result
= NULL
;
131 result
= Policy::required(policyRef
)->properties();
143 SecPolicySetValue(SecPolicyRef policyRef
, const CSSM_DATA
*value
)
147 const CssmData
newValue(value
->Data
, value
->Length
);
148 Policy::required(policyRef
)->setValue(newValue
);
153 SecPolicySetProperties(SecPolicyRef policyRef
, CFDictionaryRef properties
)
156 Policy::required(policyRef
)->setProperties(properties
);
161 SecPolicyGetTPHandle(SecPolicyRef policyRef
, CSSM_TP_HANDLE
* tpHandle
)
164 Required(tpHandle
) = Policy::required(policyRef
)->tp()->handle();
169 SecPolicyCopyAll(CSSM_CERT_TYPE certificateType
, CFArrayRef
* policies
)
173 CFMutableArrayRef currPolicies
= NULL
;
174 currPolicies
= CFArrayCreateMutable(NULL
, 0, NULL
);
177 SecPointer
<PolicyCursor
> cursor(new PolicyCursor(NULL
, NULL
));
178 SecPointer
<Policy
> policy
;
179 while ( cursor
->next(policy
) ) /* copies the next policy */
181 CFArrayAppendValue(currPolicies
, policy
->handle()); /* 'SecPolicyRef' appended */
182 CFRelease(policy
->handle()); /* refcount bumped up when appended to array */
184 *policies
= CFArrayCreateCopy(NULL
, currPolicies
);
185 CFRelease(currPolicies
);
186 CFRelease(cursor
->handle());
192 SecPolicyCopy(CSSM_CERT_TYPE certificateType
, const CSSM_OID
*policyOID
, SecPolicyRef
* policy
)
197 SecPolicySearchRef srchRef
= NULL
;
200 ortn
= SecPolicySearchCreate(certificateType
, policyOID
, NULL
, &srchRef
);
204 ortn
= SecPolicySearchCopyNext(srchRef
, policy
);
211 SecPolicyCreateBasicX509(void)
213 // return a SecPolicyRef object for the X.509 Basic policy
214 SecPolicyRef policy
= nil
;
215 SecPolicySearchRef policySearch
= nil
;
216 OSStatus status
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, &CSSMOID_APPLE_X509_BASIC
, NULL
, &policySearch
);
218 status
= SecPolicySearchCopyNext(policySearch
, &policy
);
221 CFRelease(policySearch
);
228 SecPolicyCreateSSL(Boolean server
, CFStringRef hostname
)
230 // return a SecPolicyRef object for the SSL policy, given hostname and client options
231 SecPolicyRef policy
= nil
;
232 SecPolicySearchRef policySearch
= nil
;
233 OSStatus status
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, &CSSMOID_APPLE_TP_SSL
, NULL
, &policySearch
);
235 status
= SecPolicySearchCopyNext(policySearch
, &policy
);
237 if (!status
&& policy
) {
238 // set options for client-side or server-side policy evaluation
240 const char *hostnamestr
= NULL
;
242 hostnamestr
= CFStringGetCStringPtr(hostname
, kCFStringEncodingUTF8
);
243 if (hostnamestr
== NULL
) {
244 CFIndex maxLen
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(hostname
), kCFStringEncodingUTF8
) + 1;
245 strbuf
= (char *)malloc(maxLen
);
246 if (CFStringGetCString(hostname
, strbuf
, maxLen
, kCFStringEncodingUTF8
)) {
247 hostnamestr
= strbuf
;
251 uint32 hostnamelen
= (hostnamestr
) ? (uint32
)strlen(hostnamestr
) : 0;
252 uint32 flags
= (!server
) ? CSSM_APPLE_TP_SSL_CLIENT
: 0;
253 CSSM_APPLE_TP_SSL_OPTIONS opts
= {CSSM_APPLE_TP_SSL_OPTS_VERSION
, hostnamelen
, hostnamestr
, flags
};
254 CSSM_DATA data
= {sizeof(opts
), (uint8
*)&opts
};
255 SecPolicySetValue(policy
, &data
);
262 CFRelease(policySearch
);
268 SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid
*oidPtr
)
270 SecPolicyRef policy
= NULL
;
272 SecPointer
<Policy
> policyObj
;
273 PolicyCursor::policy(oidPtr
, policyObj
);
274 policy
= policyObj
->handle();
283 SecPolicyCreateWithOID(CFTypeRef policyOID
)
285 // for now, we only accept the policy constants that are defined in SecPolicy.h
286 CFStringRef oidStr
= (CFStringRef
)policyOID
;
287 CSSM_OID
*oidPtr
= NULL
;
288 SecPolicyRef policy
= NULL
;
292 struct oidmap_entry_t
{
293 const CFTypeRef oidstr
;
294 const SecAsn1Oid
*oidptr
;
296 const oidmap_entry_t oidmap
[] = {
297 { kSecPolicyAppleX509Basic
, &CSSMOID_APPLE_X509_BASIC
},
298 { kSecPolicyAppleSSL
, &CSSMOID_APPLE_TP_SSL
},
299 { kSecPolicyAppleSMIME
, &CSSMOID_APPLE_TP_SMIME
},
300 { kSecPolicyAppleEAP
, &CSSMOID_APPLE_TP_EAP
},
301 { kSecPolicyAppleIPsec
, &CSSMOID_APPLE_TP_IP_SEC
},
302 { kSecPolicyAppleiChat
, &CSSMOID_APPLE_TP_ICHAT
},
303 { kSecPolicyApplePKINITClient
, &CSSMOID_APPLE_TP_PKINIT_CLIENT
},
304 { kSecPolicyApplePKINITServer
, &CSSMOID_APPLE_TP_PKINIT_SERVER
},
305 { kSecPolicyAppleCodeSigning
, &CSSMOID_APPLE_TP_CODE_SIGNING
},
306 { kSecPolicyMacAppStoreReceipt
, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT
},
307 { kSecPolicyAppleIDValidation
, &CSSMOID_APPLE_TP_APPLEID_SHARING
},
308 { kSecPolicyAppleTimeStamping
, &CSSMOID_APPLE_TP_TIMESTAMPING
},
309 { kSecPolicyAppleRevocation
, &CSSMOID_APPLE_TP_REVOCATION
},
310 { kSecPolicyApplePassbookSigning
, &CSSMOID_APPLE_TP_PASSBOOK_SIGNING
},
311 { kSecPolicyAppleMobileStore
, &CSSMOID_APPLE_TP_MOBILE_STORE
},
312 { kSecPolicyAppleEscrowService
, &CSSMOID_APPLE_TP_ESCROW_SERVICE
},
313 { kSecPolicyAppleProfileSigner
, &CSSMOID_APPLE_TP_PROFILE_SIGNING
},
314 { kSecPolicyAppleQAProfileSigner
, &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING
},
315 { kSecPolicyAppleTestMobileStore
, &CSSMOID_APPLE_TP_TEST_MOBILE_STORE
},
316 { kSecPolicyApplePCSEscrowService
, &CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE
},
318 unsigned int i
, oidmaplen
= sizeof(oidmap
) / sizeof(oidmap_entry_t
);
319 for (i
=0; i
<oidmaplen
; i
++) {
320 CFStringRef str
= (CFStringRef
) oidmap
[i
].oidstr
;
321 if (CFStringCompare(str
, oidStr
, 0) == kCFCompareEqualTo
) {
322 oidPtr
= (CSSM_OID
*)oidmap
[i
].oidptr
;
326 if (CFEqual(oidStr
, kSecPolicyAppleServerAuthentication
)) {
327 return SecPolicyCreateAppleSSLService(NULL
);
330 SecPolicySearchRef policySearch
= NULL
;
331 OSStatus status
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, oidPtr
, NULL
, &policySearch
);
332 if (!status
&& policySearch
) {
333 status
= SecPolicySearchCopyNext(policySearch
, &policy
);
334 CFRelease(policySearch
);
336 if (!policy
&& CFEqual(policyOID
, kSecPolicyAppleRevocation
)) {
337 policy
= SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod
);
340 policy
= SecPolicyCreateWithSecAsn1Oid((SecAsn1Oid
*)oidPtr
);
348 SecPolicyCreateWithProperties(CFTypeRef policyIdentifier
, CFDictionaryRef properties
)
350 SecPolicyRef policy
= SecPolicyCreateWithOID(policyIdentifier
);
351 SecPolicySetProperties(policy
, properties
);
358 SecPolicyCreateRevocation(CFOptionFlags revocationFlags
)
360 // return a SecPolicyRef object for the unified revocation policy
361 SecAsn1Oid
*oidPtr
= (SecAsn1Oid
*)&CSSMOID_APPLE_TP_REVOCATION
;
362 SecPolicyRef policy
= SecPolicyCreateWithSecAsn1Oid(oidPtr
);
364 CSSM_DATA policyData
= { (CSSM_SIZE
)sizeof(CFOptionFlags
), (uint8
*)&revocationFlags
};
365 SecPolicySetValue(policy
, &policyData
);
370 /* new in 10.9 ***FIXME*** TO BE REMOVED */
371 CFArrayRef
SecPolicyCopyEscrowRootCertificates(void)
373 return SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot
);
376 SecPolicyRef
SecPolicyCreateAppleIDSService(CFStringRef hostname
)
378 return SecPolicyCreateSSL(true, hostname
);
381 SecPolicyRef
SecPolicyCreateApplePushService(CFStringRef hostname
)
383 return SecPolicyCreateSSL(true, hostname
);
386 SecPolicyRef
SecPolicyCreateAppleMMCSService(CFStringRef hostname
)
388 return SecPolicyCreateSSL(true, hostname
);
391 SecPolicyRef
SecPolicyCreateAppleSSLService(CFStringRef hostname
)
393 // SSL server, pinned to an Apple intermediate
394 SecPolicyRef policy
= SecPolicyCreateSSL(true, hostname
);
396 // change options for policy evaluation
398 const char *hostnamestr
= NULL
;
400 hostnamestr
= CFStringGetCStringPtr(hostname
, kCFStringEncodingUTF8
);
401 if (hostnamestr
== NULL
) {
402 CFIndex maxLen
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(hostname
), kCFStringEncodingUTF8
) + 1;
403 strbuf
= (char *)malloc(maxLen
);
404 if (CFStringGetCString(hostname
, strbuf
, maxLen
, kCFStringEncodingUTF8
)) {
405 hostnamestr
= strbuf
;
409 uint32 hostnamelen
= (hostnamestr
) ? (uint32
)strlen(hostnamestr
) : 0;
410 uint32 flags
= 0x00000002; // 2nd-lowest bit set to require Apple intermediate pin
411 CSSM_APPLE_TP_SSL_OPTIONS opts
= {CSSM_APPLE_TP_SSL_OPTS_VERSION
, hostnamelen
, hostnamestr
, flags
};
412 CSSM_DATA data
= {sizeof(opts
), (uint8
*)&opts
};
413 SecPolicySetValue(policy
, &data
);
417 #include <security_utilities/cfutilities.h>
419 // Takes the "context" policies to extract the revocation and apply it to timeStamp.
421 SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef policyOrArray
)
423 /* can't use SECAPI macros, since this function does not return OSStatus */
424 CFArrayRef resultPolicyArray
=NULL
;
426 // Set default policy
427 CFRef
<CFArrayRef
> policyArray
= cfArrayize(policyOrArray
);
428 CFRef
<SecPolicyRef
> defaultPolicy
= SecPolicyCreateWithOID(kSecPolicyAppleTimeStamping
);
429 CFRef
<CFMutableArrayRef
> appleTimeStampingPolicies
= makeCFMutableArray(1,defaultPolicy
.get());
431 // Parse the policy and add revocation related ones
432 CFIndex numPolicies
= CFArrayGetCount(policyArray
);
433 for(CFIndex dex
=0; dex
<numPolicies
; dex
++) {
434 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(policyArray
, dex
);
435 SecPointer
<Policy
> pol
= Policy::required(SecPolicyRef(secPol
));
436 const CssmOid
&oid
= pol
->oid();
437 if ((oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION
))
438 || (oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
))
439 || (oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
)))
441 CFArrayAppendValue(appleTimeStampingPolicies
, secPol
);
444 // Transfer of ownership
445 resultPolicyArray
=appleTimeStampingPolicies
.yield();
448 CFReleaseNull(resultPolicyArray
);
450 return resultPolicyArray
;