2 * Copyright (c) 2002-2015 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 #include "SecTrustPriv.h"
27 #include <security_keychain/SecTrustSettingsPriv.h>
29 #include "SecBridge.h"
30 #include "SecInternal.h"
31 #include "SecInternalP.h"
32 #include "SecTrustSettings.h"
33 #include "SecCertificatePriv.h"
34 #include "SecCertificateP.h"
35 #include "SecCertificatePrivP.h"
36 #include "SecPolicyPriv.h"
37 #include <security_utilities/cfutilities.h>
38 #include <security_utilities/cfmunge.h>
39 #include <CoreFoundation/CoreFoundation.h>
42 // forward declarations
44 CFArrayRef
SecTrustCopyDetails(SecTrustRef trust
);
45 static CFDictionaryRef
SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust
, CFIndex ix
);
46 static void SecTrustCheckException(const void *key
, const void *value
, void *context
);
49 typedef struct SecTrustCheckExceptionContext
{
50 CFDictionaryRef exception
;
51 bool exceptionNotFound
;
52 } SecTrustCheckExceptionContext
;
54 // public trust result constants
55 const CFStringRef kSecTrustEvaluationDate
= CFSTR("TrustEvaluationDate");
56 const CFStringRef kSecTrustExtendedValidation
= CFSTR("TrustExtendedValidation");
57 const CFStringRef kSecTrustOrganizationName
= CFSTR("Organization");
58 const CFStringRef kSecTrustResultValue
= CFSTR("TrustResultValue");
59 const CFStringRef kSecTrustRevocationChecked
= CFSTR("TrustRevocationChecked");
60 const CFStringRef kSecTrustRevocationReason
= CFSTR("TrustRevocationReason");
61 const CFStringRef kSecTrustRevocationValidUntilDate
= CFSTR("TrustExpirationDate");
62 const CFStringRef kSecTrustResultDetails
= CFSTR("TrustResultDetails");
68 CFTypeID
SecTrustGetTypeID(void)
72 return gTypes().Trust
.typeID
;
74 END_SECAPI1(_kCFRuntimeNotATypeID
)
79 // Sec* API bridge functions
82 OSStatus
SecTrustCreateWithCertificates(
83 CFTypeRef certificates
,
85 SecTrustRef
*trustRef
)
89 *trustRef
= (new Trust(certificates
, policies
))->handle();
96 SecTrustSetPolicies(SecTrustRef trustRef
, CFTypeRef policies
)
99 Trust::required(trustRef
)->policies(policies
);
104 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
106 SecTrustSetOptions(SecTrustRef trustRef
, SecTrustOptionFlags options
)
110 CSSM_APPLE_TP_ACTION_DATA actionData
= {
111 CSSM_APPLE_TP_ACTION_VERSION
,
112 (CSSM_APPLE_TP_ACTION_FLAGS
)options
114 Trust
*trust
= Trust::required(trustRef
);
115 CFDataRef actionDataRef
= CFDataCreate(NULL
,
116 (const UInt8
*)&actionData
,
117 (CFIndex
)sizeof(CSSM_APPLE_TP_ACTION_DATA
));
118 trust
->action(CSSM_TP_ACTION_DEFAULT
);
119 trust
->actionData(actionDataRef
);
120 if (actionDataRef
) CFRelease(actionDataRef
);
123 /* bridge to support API functionality for legacy callers */
124 OSStatus status
= errSecSuccess
;
126 #warning STU: <rdar://21328005>
127 //%%% need to ensure that the exception covers only the requested options
129 CFArrayRef details
= SecTrustGetDetails(trustRef
); // NOTE: performs the evaluation if not done already
130 CFIndex pathLength
= details
? CFArrayGetCount(details
) : 0;
132 for (ix
= 0; ix
< pathLength
; ++ix
) {
133 CFDictionaryRef detail
= (CFDictionaryRef
)CFArrayGetValueAtIndex(details
, ix
);
134 CFIndex detailCount
= CFDictionaryGetCount(detail
);
135 if (detailCount
> 0) {
136 // see if we can ignore this error
137 syslog(LOG_ERR
, "SecTrustSetOptions: examining detail dictionary items at ix %ld", (long)ix
);
141 syslog(LOG_ERR
, "SecTrustSetOptions: creating trust exception");
143 CFDataRef exceptions
= SecTrustCopyExceptions(trustRef
);
145 SecTrustSetExceptions(trustRef
, exceptions
);
146 CFRelease(exceptions
);
150 #if SECTRUST_DEPRECATION_WARNINGS
151 bool displayModifyMsg
= false;
152 bool displayNetworkMsg
= false;
153 bool displayPolicyMsg
= false;
154 const char *baseMsg
= "WARNING: SecTrustSetOptions called with";
155 const char *modifyMsg
= "Use SecTrustSetExceptions and SecTrustCopyExceptions to modify default trust results.";
156 const char *networkMsg
= "Use SecTrustSetNetworkFetchAllowed to specify whether missing certificates can be fetched from the network.";
157 const char *policyMsg
= "Use SecPolicyCreateRevocation to specify revocation policy requirements.";
159 if (options
& kSecTrustOptionAllowExpired
) {
160 syslog(LOG_ERR
, "%s %s.", baseMsg
, "kSecTrustOptionAllowExpired");
161 displayModifyMsg
= true;
163 if (options
& kSecTrustOptionAllowExpiredRoot
) {
164 syslog(LOG_ERR
, "%s %s.", baseMsg
, "kSecTrustOptionAllowExpiredRoot");
165 displayModifyMsg
= true;
167 if (options
& kSecTrustOptionFetchIssuerFromNet
) {
168 syslog(LOG_ERR
, "%s %s.", baseMsg
, "kSecTrustOptionFetchIssuerFromNet");
169 displayNetworkMsg
= true;
171 if (options
& kSecTrustOptionRequireRevPerCert
) {
172 syslog(LOG_ERR
, "%s %s.", baseMsg
, "kSecTrustOptionRequireRevPerCert");
173 displayPolicyMsg
= true;
175 if (displayModifyMsg
|| displayNetworkMsg
|| displayPolicyMsg
) {
176 syslog(LOG_ERR
, "%s %s %s",
177 (displayModifyMsg
) ? modifyMsg
: "",
178 (displayNetworkMsg
) ? networkMsg
: "",
179 (displayPolicyMsg
) ? policyMsg
: "");
188 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
189 OSStatus
SecTrustSetParameters(
190 SecTrustRef trustRef
,
191 CSSM_TP_ACTION action
,
192 CFDataRef actionData
)
196 Trust
*trust
= Trust::required(trustRef
);
197 trust
->action(action
);
198 trust
->actionData(actionData
);
201 /* bridge to support API functionality for legacy callers */
203 CSSM_APPLE_TP_ACTION_FLAGS actionFlags
= 0;
205 CSSM_APPLE_TP_ACTION_DATA
*actionDataPtr
= (CSSM_APPLE_TP_ACTION_DATA
*) CFDataGetBytePtr(actionData
);
207 actionFlags
= actionDataPtr
->ActionFlags
;
210 // note that SecTrustOptionFlags == CSSM_APPLE_TP_ACTION_FLAGS;
211 // both are sizeof(uint32) and the flag values have identical meanings
212 status
= SecTrustSetOptions(trustRef
, (SecTrustOptionFlags
)actionFlags
);
214 #if SECTRUST_DEPRECATION_WARNINGS
215 syslog(LOG_ERR
, "WARNING: SecTrustSetParameters was deprecated in 10.7. Use SecTrustSetOptions instead.");
224 OSStatus
SecTrustSetAnchorCertificates(SecTrustRef trust
, CFArrayRef anchorCertificates
)
227 Trust::required(trust
)->anchors(anchorCertificates
);
233 OSStatus
SecTrustSetAnchorCertificatesOnly(SecTrustRef trust
, Boolean anchorCertificatesOnly
)
236 Trust::AnchorPolicy policy
= (anchorCertificatesOnly
) ? Trust::useAnchorsOnly
: Trust::useAnchorsAndBuiltIns
;
237 Trust::required(trust
)->anchorPolicy(policy
);
242 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
243 OSStatus
SecTrustSetKeychains(SecTrustRef trust
, CFTypeRef keychainOrArray
)
247 StorageManager::KeychainList keychains
;
248 // avoid unnecessary global initializations if an empty array is passed in
249 if (!( (keychainOrArray
!= NULL
) &&
250 (CFGetTypeID(keychainOrArray
) == CFArrayGetTypeID()) &&
251 (CFArrayGetCount((CFArrayRef
)keychainOrArray
) == 0) )) {
252 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
254 Trust::required(trust
)->searchLibs(keychains
);
257 /* this function is currently unsupported in unified SecTrust */
258 // TODO: pull all certs out of the specified keychains for the evaluation?
259 #if SECTRUST_DEPRECATION_WARNINGS
260 syslog(LOG_ERR
, "WARNING: SecTrustSetKeychains does nothing in 10.11. Use SecTrustSetAnchorCertificates{Only} to provide anchors.");
262 return errSecSuccess
;
267 OSStatus
SecTrustSetVerifyDate(SecTrustRef trust
, CFDateRef verifyDate
)
270 Trust::required(trust
)->time(verifyDate
);
276 CFAbsoluteTime
SecTrustGetVerifyTime(SecTrustRef trust
)
278 CFAbsoluteTime verifyTime
= 0;
279 OSStatus __secapiresult
= errSecSuccess
;
281 CFRef
<CFDateRef
> verifyDate
= Trust::required(trust
)->time();
282 verifyTime
= CFDateGetAbsoluteTime(verifyDate
);
284 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
285 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
286 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
287 catch (...) { __secapiresult
=errSecInternalComponent
; }
295 OSStatus
SecTrustEvaluate(SecTrustRef trust
, SecTrustResultType
*resultP
)
297 SecTrustResultType trustResult
= kSecTrustResultInvalid
;
298 CFArrayRef exceptions
= NULL
;
299 OSStatus __secapiresult
= errSecSuccess
;
301 Trust
*trustObj
= Trust::required(trust
);
302 trustObj
->evaluate();
303 trustResult
= trustObj
->result();
304 exceptions
= trustObj
->exceptions();
306 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
307 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
308 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
309 catch (...) { __secapiresult
=errSecInternalComponent
; }
311 if (__secapiresult
) {
312 return __secapiresult
;
315 /* post-process trust result based on exceptions */
316 if (trustResult
== kSecTrustResultUnspecified
) {
317 /* If leaf is in exceptions -> proceed, otherwise unspecified. */
318 if (SecTrustGetExceptionForCertificateAtIndex(trust
, 0))
319 trustResult
= kSecTrustResultProceed
;
321 else if (trustResult
== kSecTrustResultRecoverableTrustFailure
&& exceptions
) {
322 /* If we have exceptions get details and match to exceptions. */
323 CFArrayRef details
= SecTrustCopyDetails(trust
);
325 CFIndex pathLength
= CFArrayGetCount(details
);
326 struct SecTrustCheckExceptionContext context
= {};
328 for (ix
= 0; ix
< pathLength
; ++ix
) {
329 CFDictionaryRef detail
= (CFDictionaryRef
)CFArrayGetValueAtIndex(details
, ix
);
330 // if ((ix == 0) && CFDictionaryContainsKey(detail, kSecPolicyCheckBlackListedLeaf))
331 // trustResult = kSecTrustResultFatalTrustFailure;
332 context
.exception
= SecTrustGetExceptionForCertificateAtIndex(trust
, ix
);
333 CFDictionaryApplyFunction(detail
, SecTrustCheckException
, &context
);
334 if (context
.exceptionNotFound
) {
338 if (!context
.exceptionNotFound
)
339 trustResult
= kSecTrustResultProceed
;
344 secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult
);
346 *resultP
= trustResult
;
348 return __secapiresult
;
353 OSStatus
SecTrustEvaluateAsync(SecTrustRef trust
,
354 dispatch_queue_t queue
, SecTrustCallback result
)
357 dispatch_async(queue
, ^{
359 Trust
*trustObj
= Trust::required(trust
);
360 trustObj
->evaluate();
361 SecTrustResultType trustResult
= trustObj
->result();
362 result(trust
, trustResult
);
365 result(trust
, kSecTrustResultInvalid
);
373 // Construct the "official" result evidence and return it
375 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
376 OSStatus
SecTrustGetResult(
377 SecTrustRef trustRef
,
378 SecTrustResultType
*result
,
379 CFArrayRef
*certChain
, CSSM_TP_APPLE_EVIDENCE_INFO
**statusChain
)
383 Trust
*trust
= Trust::required(trustRef
);
385 *result
= trust
->result();
386 if (certChain
&& statusChain
)
387 trust
->buildEvidence(*certChain
, TPEvidenceInfo::overlayVar(*statusChain
));
390 /* bridge to support old functionality */
391 #if SECTRUST_DEPRECATION_WARNINGS
392 syslog(LOG_ERR
, "WARNING: SecTrustGetResult has been deprecated since 10.7, and may not return a statusChain in 10.11. Please use SecTrustGetTrustResult instead.");
394 SecTrustResultType trustResult
;
395 OSStatus status
= SecTrustGetTrustResult(trustRef
, &trustResult
);
397 *result
= trustResult
;
399 if (certChain
&& !statusChain
) {
400 /* This is the easy case; caller only wants cert chain and not status chain. */
401 CFMutableArrayRef certArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
402 CFIndex idx
, count
= SecTrustGetCertificateCount(trustRef
);
403 for (idx
=0; idx
< count
; idx
++) {
404 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trustRef
, idx
);
406 CFArrayAppendValue(certArray
, certificate
);
409 *certChain
= certArray
;
411 else if (certChain
&& statusChain
) {
413 * Here is where backward compatibility gets ugly. CSSM_TP_APPLE_EVIDENCE_INFO* is tied to a
414 * Trust object and does not exist in the new unified world. Unfortunately, some clients are
415 * still calling this legacy API and grubbing through the info for StatusBits and StatusCodes.
416 * If they want this info, then we have to do a legacy evaluation to get it. The info struct
417 * goes away once the old-style object does, so we must keep the old-style object alive after
418 * returning from the function.
420 * TODO: keep a dictionary and figure out how to expire entries when no longer needed.,
421 * or build the evidence info ourselves: rdar://21005914
423 static CFMutableArrayRef sTrustArray
= NULL
;
425 // make array of Certificate instances from unified SecCertificateRefs
426 CFMutableArrayRef certArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
427 CFIndex idx
, count
= SecTrustGetCertificateCount(trustRef
);
428 for (idx
=0; idx
< count
; idx
++) {
429 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trustRef
, idx
);
431 SecCertificateRef itemImplRef
= SecCertificateCreateItemImplInstance(certificate
);
433 CFArrayAppendValue(certArray
, itemImplRef
);
434 CFRelease(itemImplRef
);
438 // make array of Policy instances from unified SecPolicyRefs
439 CFMutableArrayRef policyArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
440 CFArrayRef policies
= NULL
;
441 status
= SecTrustCopyPolicies(trustRef
, &policies
);
442 count
= (!status
&& policies
) ? CFArrayGetCount(policies
) : 0;
443 for (idx
=0; idx
< count
; idx
++) {
444 SecPolicyRef policy
= (SecPolicyRef
) CFArrayGetValueAtIndex(policies
, idx
);
446 SecPolicyRef itemImplRef
= SecPolicyCreateItemImplInstance(policy
);
448 CFArrayAppendValue(policyArray
, itemImplRef
);
449 CFRelease(itemImplRef
);
453 // now make a Trust instance and evaluate it
455 Trust
*trustObj
= new Trust(certArray
, policyArray
);
456 SecTrustRef trust
= trustObj
->handle();
458 MacOSError::throwMe(errSecTrustNotAvailable
);
461 sTrustArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
463 MacOSError::throwMe(errSecAllocate
);
466 // fetch the built cert chain and status chain
467 CFArrayRef itemImplCertArray
= NULL
;
468 trustObj
->evaluate();
469 trustObj
->buildEvidence(itemImplCertArray
, TPEvidenceInfo::overlayVar(*statusChain
));
471 // convert each Certificate in the built chain to a unified SecCertificateRef
472 CFMutableArrayRef outCertChain
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
473 CFIndex idx
, count
= (itemImplCertArray
) ? CFArrayGetCount(itemImplCertArray
) : 0;
474 for (idx
=0; idx
< count
; idx
++) {
475 SecCertificateRef inCert
= (SecCertificateRef
) CFArrayGetValueAtIndex(itemImplCertArray
, idx
);
476 SecCertificateRef outCert
= SecCertificateCreateFromItemImplInstance(inCert
);
478 CFArrayAppendValue(outCertChain
, outCert
);
482 *certChain
= outCertChain
;
483 if (itemImplCertArray
) {
484 CFRelease(itemImplCertArray
);
486 CFArrayAppendValue(sTrustArray
, trust
);
487 status
= errSecSuccess
;
489 catch (const MacOSError
&err
) { status
=err
.osStatus(); }
490 catch (const CommonError
&err
) { status
=SecKeychainErrFromOSStatus(err
.osStatus()); }
491 catch (const std::bad_alloc
&) { status
=errSecAllocate
; }
492 catch (...) { status
=errSecInternalComponent
; }
495 CFRelease(policyArray
);
497 CFRelease(certArray
);
504 // Retrieve result of trust evaluation only
507 OSStatus
SecTrustGetTrustResult(SecTrustRef trustRef
,
508 SecTrustResultType
*result
)
511 Trust
*trust
= Trust::required(trustRef
);
512 if (result
) *result
= trust
->result();
518 // Retrieve extended validation trust results
520 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
521 OSStatus
SecTrustCopyExtendedResult(SecTrustRef trust
, CFDictionaryRef
*result
)
525 Trust
*trustObj
= Trust::required(trust
);
528 trustObj
->extendedResult(*result
);
531 /* bridge to support old functionality */
532 #if SECTRUST_DEPRECATION_WARNINGS
533 syslog(LOG_ERR
, "WARNING: SecTrustCopyExtendedResult will be deprecated in an upcoming release. Please use SecTrustCopyResult instead.");
535 CFDictionaryRef resultDict
= SecTrustCopyResult(trust
);
539 *result
= resultDict
;
540 return errSecSuccess
;
545 // Retrieve CSSM-level information for those who want to dig down
547 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
548 OSStatus
SecTrustGetCssmResult(SecTrustRef trust
, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR
*result
)
552 Required(result
) = Trust::required(trust
)->cssmResult();
555 /* this function is unsupported in unified SecTrust */
556 #if SECTRUST_DEPRECATION_WARNINGS
557 syslog(LOG_ERR
, "WARNING: SecTrustGetCssmResult has been deprecated since 10.7, and has no functional equivalent in 10.11. Please use SecTrustCopyResult instead.");
562 return errSecServiceNotAvailable
;
567 static void applyPropertyToCssmResultCode(const void *_key
, const void *_value
, void *context
) {
568 CFStringRef key
= (CFStringRef
)_key
;
569 CFStringRef value
= (CFStringRef
)_value
;
570 OSStatus
*result
= (OSStatus
*)context
;
571 if (CFGetTypeID(_value
) != CFStringGetTypeID()) {
574 if (!CFEqual(CFSTR("value"), key
)) {
577 if (CFEqual(CFSTR("Invalid certificate chain linkage."), value
)) {
578 *result
= CSSMERR_APPLETP_INVALID_ID_LINKAGE
;
579 } else if (CFEqual(CFSTR("One or more unsupported critical extensions found."), value
)) {
580 *result
= CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN
;
581 } else if (CFEqual(CFSTR("Root certificate is not trusted."), value
)) {
582 *result
= CSSMERR_TP_NOT_TRUSTED
;
583 } else if (CFEqual(CFSTR("Hostname mismatch."), value
)) {
584 *result
= CSSMERR_APPLETP_HOSTNAME_MISMATCH
;
585 } else if (CFEqual(CFSTR("One or more certificates have expired or are not valid yet."), value
)) {
586 *result
= CSSMERR_TP_CERT_EXPIRED
;
587 } else if (CFEqual(CFSTR("Policy requirements not met."), value
)) {
588 *result
= CSSMERR_TP_VERIFY_ACTION_FAILED
;
594 // Retrieve CSSM_LEVEL TP return code
596 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
597 OSStatus
SecTrustGetCssmResultCode(SecTrustRef trustRef
, OSStatus
*result
)
601 Trust
*trust
= Trust::required(trustRef
);
602 if (trust
->result() == kSecTrustResultInvalid
)
605 Required(result
) = trust
->cssmResultCode();
608 /* bridge to support old functionality */
609 #if SECTRUST_DEPRECATION_WARNINGS
610 syslog(LOG_ERR
, "WARNING: SecTrustGetCssmResultCode has been deprecated since 10.7, and will be removed in a future release. Please use SecTrustCopyProperties instead.");
612 if (!trustRef
|| !result
) {
615 CFArrayRef properties
= SecTrustCopyProperties(trustRef
);
618 return errSecSuccess
;
620 OSStatus cssmResultCode
= 0;
621 CFIndex ix
, count
= CFArrayGetCount(properties
);
622 for (ix
= 0; ix
< count
; ++ix
) {
623 CFDictionaryRef property
= (CFDictionaryRef
)
624 CFArrayGetValueAtIndex(properties
, ix
);
625 CFDictionaryApplyFunction(property
, applyPropertyToCssmResultCode
, &cssmResultCode
);
628 *result
= cssmResultCode
;
631 CFRelease(properties
);
633 return errSecSuccess
;
637 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
638 OSStatus
SecTrustGetTPHandle(SecTrustRef trust
, CSSM_TP_HANDLE
*handle
)
642 Required(handle
) = Trust::required(trust
)->getTPHandle();
645 /* this function is unsupported in unified SecTrust */
646 #if SECTRUST_DEPRECATION_WARNINGS
647 syslog(LOG_ERR
, "WARNING: SecTrustGetTPHandle has been deprecated since 10.7, and cannot return CSSM objects in 10.11. Please stop using it.");
652 return errSecServiceNotAvailable
;
657 OSStatus
SecTrustCopyPolicies(SecTrustRef trust
, CFArrayRef
*policies
)
660 CFArrayRef currentPolicies
= Trust::required(trust
)->policies();
661 if (currentPolicies
!= NULL
)
663 CFRetain(currentPolicies
);
666 Required(policies
) = currentPolicies
;
672 OSStatus
SecTrustSetNetworkFetchAllowed(SecTrustRef trust
, Boolean allowFetch
)
675 Trust
*trustObj
= Trust::required(trust
);
676 Trust::NetworkPolicy netPolicy
= (allowFetch
) ?
677 Trust::useNetworkEnabled
: Trust::useNetworkDisabled
;
678 trustObj
->networkPolicy(netPolicy
);
684 OSStatus
SecTrustGetNetworkFetchAllowed(SecTrustRef trust
, Boolean
*allowFetch
)
687 Boolean allowed
= false;
688 Trust
*trustObj
= Trust::required(trust
);
689 Trust::NetworkPolicy netPolicy
= trustObj
->networkPolicy();
690 if (netPolicy
== Trust::useNetworkDefault
) {
691 // network fetch is enabled by default for SSL only
692 allowed
= trustObj
->policySpecified(trustObj
->policies(), CSSMOID_APPLE_TP_SSL
);
694 // caller has explicitly set the network policy
695 allowed
= (netPolicy
== Trust::useNetworkEnabled
);
697 Required(allowFetch
) = allowed
;
703 OSStatus
SecTrustSetOCSPResponse(SecTrustRef trust
, CFTypeRef responseData
)
706 Trust::required(trust
)->responses(responseData
);
712 OSStatus
SecTrustCopyCustomAnchorCertificates(SecTrustRef trust
, CFArrayRef
*anchorCertificates
)
715 CFArrayRef customAnchors
= Trust::required(trust
)->anchors();
716 Required(anchorCertificates
) = (customAnchors
) ?
717 (const CFArrayRef
)CFRetain(customAnchors
) : (const CFArrayRef
)NULL
;
723 // Get the user's default anchor certificate set
726 OSStatus
SecTrustCopyAnchorCertificates(CFArrayRef
*anchorCertificates
)
730 return SecTrustSettingsCopyUnrestrictedRoots(
731 true, true, true, /* all domains */
738 /* We have an iOS-style SecTrustRef, but we need to return a CDSA-based SecKeyRef.
740 SecKeyRef
SecTrustCopyPublicKey(SecTrustRef trust
)
742 SecKeyRef pubKey
= NULL
;
743 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, 0);
744 (void) SecCertificateCopyPublicKey(certificate
, &pubKey
);
749 SecKeyRef
SecTrustCopyPublicKey(SecTrustRef trust
)
751 SecKeyRef pubKey
= NULL
;
752 CFArrayRef certChain
= NULL
;
753 CFArrayRef evidenceChain
= NULL
;
754 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
755 OSStatus __secapiresult
= errSecSuccess
;
757 Trust
*trustObj
= Trust::required(trust
);
758 if (trustObj
->result() == kSecTrustResultInvalid
) {
759 // Trust hasn't been evaluated; attempt to retrieve public key from leaf.
760 SecCertificateRef cert
= SecTrustGetCertificateAtIndex(trust
, 0);
761 __secapiresult
= SecCertificateCopyPublicKey(cert
, &pubKey
);
765 // Otherwise, we must evaluate first.
766 trustObj
->evaluate();
767 if (trustObj
->result() == kSecTrustResultInvalid
) {
768 MacOSError::throwMe(errSecTrustNotAvailable
);
771 if (trustObj
->evidence() == nil
) {
772 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
774 evidenceChain
= trustObj
->evidence();
776 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
777 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
778 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
779 catch (...) { __secapiresult
=errSecInternalComponent
; }
782 CFRelease(certChain
);
785 if (CFArrayGetCount(evidenceChain
) > 0) {
786 SecCertificateRef cert
= (SecCertificateRef
) CFArrayGetValueAtIndex(evidenceChain
, 0);
787 __secapiresult
= SecCertificateCopyPublicKey(cert
, &pubKey
);
789 // do not release evidenceChain, as it is owned by the trust object.
797 CFIndex
SecTrustGetCertificateCount(SecTrustRef trust
)
799 CFIndex chainLen
= 0;
800 CFArrayRef certChain
= NULL
;
801 CFArrayRef evidenceChain
= NULL
;
802 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
803 OSStatus __secapiresult
= errSecSuccess
;
805 Trust
*trustObj
= Trust::required(trust
);
806 if (trustObj
->result() == kSecTrustResultInvalid
) {
807 trustObj
->evaluate();
808 if (trustObj
->result() == kSecTrustResultInvalid
)
809 MacOSError::throwMe(errSecTrustNotAvailable
);
811 if (trustObj
->evidence() == nil
)
812 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
813 evidenceChain
= trustObj
->evidence();
815 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
816 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
817 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
818 catch (...) { __secapiresult
=errSecInternalComponent
; }
821 CFRelease(certChain
);
824 chainLen
= CFArrayGetCount(evidenceChain
); // don't release, trust object owns it.
832 SecCertificateRef
SecTrustGetCertificateAtIndex(SecTrustRef trust
, CFIndex ix
)
834 SecCertificateRef certificate
= NULL
;
835 CFArrayRef certChain
= NULL
;
836 CFArrayRef evidenceChain
= NULL
;
837 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
838 OSStatus __secapiresult
= errSecSuccess
;
840 Trust
*trustObj
= Trust::required(trust
);
841 if (trustObj
->result() == kSecTrustResultInvalid
) {
842 // If caller is asking for the leaf, we can return it without
843 // having to evaluate the entire chain. Note that we don't retain
844 // the cert as it's owned by the trust and this is a 'Get' API.
846 CFArrayRef certs
= trustObj
->certificates();
847 if (certs
&& (CFArrayGetCount(certs
) > 0)) {
848 certificate
= (SecCertificateRef
) CFArrayGetValueAtIndex(certs
, 0);
854 // Otherwise, we must evaluate first.
855 trustObj
->evaluate();
856 if (trustObj
->result() == kSecTrustResultInvalid
) {
857 MacOSError::throwMe(errSecTrustNotAvailable
);
860 if (trustObj
->evidence() == nil
) {
861 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
863 evidenceChain
= trustObj
->evidence();
865 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
866 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
867 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
868 catch (...) { __secapiresult
=errSecInternalComponent
; }
871 CFRelease(certChain
);
874 if (ix
< CFArrayGetCount(evidenceChain
)) {
875 certificate
= (SecCertificateRef
) CFArrayGetValueAtIndex(evidenceChain
, ix
);
876 // note: we do not retain this certificate. The assumption here is
877 // that the certificate is retained by the trust object, so it is
878 // valid unil the trust is released (or until re-evaluated.)
879 // also note: we do not release the evidenceChain, as it is owned
880 // by the trust object.
889 static CFStringRef kSecCertificateDetailSHA1Digest
= CFSTR("SHA1Digest");
890 static CFStringRef kSecCertificateDetailStatusCodes
= CFSTR("StatusCodes");
893 _AppendStatusCode(CFMutableArrayRef array
, OSStatus statusCode
)
897 SInt32 num
= statusCode
;
898 CFNumberRef numRef
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &num
);
901 CFArrayAppendValue(array
, numRef
);
907 CFArrayRef
SecTrustCopyDetails(SecTrustRef trust
)
909 // This function returns an array of dictionaries, one per certificate,
910 // holding status info for each certificate in the evaluated chain.
912 CFIndex count
, chainLen
= 0;
913 CFArrayRef certChain
= NULL
;
914 CFMutableArrayRef details
= NULL
;
915 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
916 OSStatus __secapiresult
= errSecSuccess
;
918 Trust
*trustObj
= Trust::required(trust
);
919 if (trustObj
->result() == kSecTrustResultInvalid
) {
920 trustObj
->evaluate();
921 if (trustObj
->result() == kSecTrustResultInvalid
)
922 MacOSError::throwMe(errSecTrustNotAvailable
);
924 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
926 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
927 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
928 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
929 catch (...) { __secapiresult
=errSecInternalComponent
; }
932 chainLen
= CFArrayGetCount(certChain
);
933 CFRelease(certChain
);
936 details
= CFArrayCreateMutable(NULL
, chainLen
, &kCFTypeArrayCallBacks
);
937 for (count
= 0; count
< chainLen
; count
++) {
938 CFMutableDictionaryRef certDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
939 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
940 CFMutableArrayRef statusCodes
= CFArrayCreateMutable(kCFAllocatorDefault
,
941 0, &kCFTypeArrayCallBacks
);
942 CSSM_TP_APPLE_EVIDENCE_INFO
*evInfo
= &statusChain
[count
];
943 CSSM_TP_APPLE_CERT_STATUS statBits
= evInfo
->StatusBits
;
945 // translate status bits
946 if (statBits
& CSSM_CERT_STATUS_EXPIRED
)
947 _AppendStatusCode(statusCodes
, errSecCertificateExpired
);
948 if (statBits
& CSSM_CERT_STATUS_NOT_VALID_YET
)
949 _AppendStatusCode(statusCodes
, errSecCertificateNotValidYet
);
950 if (statBits
& CSSM_CERT_STATUS_TRUST_SETTINGS_DENY
)
951 _AppendStatusCode(statusCodes
, errSecTrustSettingDeny
);
953 // translate status codes
955 for (i
= 0; i
< evInfo
->NumStatusCodes
; i
++) {
956 CSSM_RETURN scode
= evInfo
->StatusCodes
[i
];
957 _AppendStatusCode(statusCodes
, (OSStatus
)scode
);
960 CFDictionarySetValue(certDict
, kSecCertificateDetailStatusCodes
, statusCodes
);
961 CFRelease(statusCodes
);
962 CFArrayAppendValue(details
, certDict
);
971 static CFDictionaryRef
SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust
, CFIndex ix
)
973 CFArrayRef exceptions
= NULL
;
974 OSStatus __secapiresult
= errSecSuccess
;
976 exceptions
= Trust::required(trust
)->exceptions();
978 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
979 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
980 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
981 catch (...) { __secapiresult
=errSecInternalComponent
; }
983 if (!exceptions
|| ix
>= CFArrayGetCount(exceptions
))
985 CFDictionaryRef exception
= (CFDictionaryRef
)CFArrayGetValueAtIndex(exceptions
, ix
);
986 if (CFGetTypeID(exception
) != CFDictionaryGetTypeID())
989 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, ix
);
993 /* If the exception contains the current certificate's sha1Digest in the
994 kSecCertificateDetailSHA1Digest key then we use it otherwise we ignore it. */
995 CFDataRef sha1Digest
= SecCertificateGetSHA1Digest(certificate
);
996 CFTypeRef digestValue
= CFDictionaryGetValue(exception
, kSecCertificateDetailSHA1Digest
);
997 if (!digestValue
|| !CFEqual(sha1Digest
, digestValue
))
1005 static void SecTrustCheckException(const void *key
, const void *value
, void *context
)
1007 struct SecTrustCheckExceptionContext
*cec
= (struct SecTrustCheckExceptionContext
*)context
;
1008 if (cec
->exception
) {
1009 CFTypeRef exceptionValue
= CFDictionaryGetValue(cec
->exception
, key
);
1010 if (!exceptionValue
|| !CFEqual(value
, exceptionValue
)) {
1011 cec
->exceptionNotFound
= true;
1014 cec
->exceptionNotFound
= true;
1021 CFDataRef
SecTrustCopyExceptions(SecTrustRef trust
)
1023 CFArrayRef details
= SecTrustCopyDetails(trust
);
1024 CFIndex pathLength
= details
? CFArrayGetCount(details
) : 0;
1025 CFMutableArrayRef exceptions
= CFArrayCreateMutable(kCFAllocatorDefault
,
1026 pathLength
, &kCFTypeArrayCallBacks
);
1028 for (ix
= 0; ix
< pathLength
; ++ix
) {
1029 CFDictionaryRef detail
= (CFDictionaryRef
)CFArrayGetValueAtIndex(details
, ix
);
1030 CFIndex detailCount
= CFDictionaryGetCount(detail
);
1031 CFMutableDictionaryRef exception
;
1032 if (ix
== 0 || detailCount
> 0) {
1033 exception
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
,
1034 detailCount
+ 1, detail
);
1035 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, ix
);
1036 CFDataRef digest
= SecCertificateGetSHA1Digest(certificate
);
1038 CFDictionaryAddValue(exception
, kSecCertificateDetailSHA1Digest
, digest
);
1041 /* Add empty exception dictionaries for non leaf certs which have no exceptions
1044 exception
= (CFMutableDictionaryRef
)CFDictionaryCreate(kCFAllocatorDefault
,
1046 &kCFTypeDictionaryKeyCallBacks
,
1047 &kCFTypeDictionaryValueCallBacks
);
1049 CFArrayAppendValue(exceptions
, exception
);
1050 CFReleaseNull(exception
);
1052 CFReleaseSafe(details
);
1054 /* Remove any trailing empty dictionaries to save even more space (we skip the leaf
1055 since it will never be empty). */
1056 for (ix
= pathLength
; ix
-- > 1;) {
1057 CFDictionaryRef exception
= (CFDictionaryRef
)CFArrayGetValueAtIndex(exceptions
, ix
);
1058 if (CFDictionaryGetCount(exception
) == 0) {
1059 CFArrayRemoveValueAtIndex(exceptions
, ix
);
1065 CFDataRef encodedExceptions
= CFPropertyListCreateData(kCFAllocatorDefault
,
1066 exceptions
, kCFPropertyListBinaryFormat_v1_0
, 0, NULL
);
1067 CFRelease(exceptions
);
1069 return encodedExceptions
;
1075 bool SecTrustSetExceptions(SecTrustRef trust
, CFDataRef encodedExceptions
)
1077 CFArrayRef exceptions
;
1078 exceptions
= (CFArrayRef
)CFPropertyListCreateWithData(kCFAllocatorDefault
,
1079 encodedExceptions
, kCFPropertyListImmutable
, NULL
, NULL
);
1080 if (exceptions
&& CFGetTypeID(exceptions
) != CFArrayGetTypeID()) {
1081 CFRelease(exceptions
);
1085 OSStatus __secapiresult
= errSecSuccess
;
1087 Trust::required(trust
)->exceptions(exceptions
);
1089 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1090 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1091 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1092 catch (...) { __secapiresult
=errSecInternalComponent
; }
1094 /* If there is a valid exception entry for our current leaf we're golden. */
1095 if (SecTrustGetExceptionForCertificateAtIndex(trust
, 0))
1098 /* The passed in exceptions didn't match our current leaf, so we discard it. */
1100 Trust::required(trust
)->exceptions(NULL
);
1101 __secapiresult
= errSecSuccess
;
1103 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1104 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1105 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1106 catch (...) { __secapiresult
=errSecInternalComponent
; }
1115 SecTrustCopyResult(SecTrustRef trust
)
1117 CFDictionaryRef result
= NULL
;
1119 result
= Trust::required(trust
)->results();
1120 // merge details into result
1121 CFArrayRef details
= SecTrustCopyDetails(trust
);
1123 CFDictionarySetValue((CFMutableDictionaryRef
)result
,
1124 kSecTrustResultDetails
, details
);
1141 SecTrustCopyProperties(SecTrustRef trust
)
1143 /* can't use SECAPI macros, since this function does not return OSStatus */
1144 CFArrayRef result
= NULL
;
1146 result
= Trust::required(trust
)->properties();
1158 /* deprecated in 10.5 */
1159 OSStatus
SecTrustGetCSSMAnchorCertificates(const CSSM_DATA
**cssmAnchors
,
1160 uint32
*cssmAnchorCount
)
1165 Trust::gStore().getCssmRootCertificates(certs
);
1166 Required(cssmAnchors
) = certs
.blobCerts();
1167 Required(cssmAnchorCount
) = certs
.count();
1170 /* this function is unsupported in unified SecTrust */
1171 #if SECTRUST_DEPRECATION_WARNINGS
1172 syslog(LOG_ERR
, "WARNING: SecTrustGetCSSMAnchorCertificates has been deprecated since 10.5, and cannot return CSSM objects in 10.11. Please stop using it.");
1175 *cssmAnchors
= NULL
;
1177 if (cssmAnchorCount
) {
1178 *cssmAnchorCount
= 0;
1180 return errSecServiceNotAvailable
;
1186 // Get and set user trust settings. Deprecated in 10.5.
1187 // User Trust getter, deprecated, works as it always has.
1189 OSStatus
SecTrustGetUserTrust(SecCertificateRef certificate
,
1190 SecPolicyRef policy
, SecTrustUserSetting
*trustSetting
)
1194 StorageManager::KeychainList searchList
;
1195 globals().storageManager
.getSearchList(searchList
);
1196 Required(trustSetting
) = Trust::gStore().find(
1197 Certificate::required(certificate
),
1198 Policy::required(policy
),
1202 /* this function is unsupported in unified SecTrust */
1203 #if SECTRUST_DEPRECATION_WARNINGS
1204 syslog(LOG_ERR
, "WARNING: SecTrustGetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
1206 return errSecServiceNotAvailable
;
1211 // The public setter, also deprecated; it maps to the appropriate
1212 // Trust Settings call if possible, else throws errSecUnimplemented.
1214 OSStatus
SecTrustSetUserTrust(SecCertificateRef certificate
,
1215 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
1218 SecTrustSettingsResult tsResult
= kSecTrustSettingsResultInvalid
;
1222 Policy::required(policy
);
1223 switch(trustSetting
) {
1224 case kSecTrustResultProceed
:
1225 /* different SecTrustSettingsResult depending in root-ness */
1226 ortn
= SecCertificateIsSelfSigned(certificate
, &isRoot
);
1231 tsResult
= kSecTrustSettingsResultTrustRoot
;
1234 tsResult
= kSecTrustSettingsResultTrustAsRoot
;
1237 case kSecTrustResultDeny
:
1238 tsResult
= kSecTrustSettingsResultDeny
;
1241 return errSecUnimplemented
;
1244 /* make a usage constraints dictionary */
1245 CFRef
<CFMutableDictionaryRef
> usageDict(CFDictionaryCreateMutable(NULL
,
1246 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
));
1247 CFDictionaryAddValue(usageDict
, kSecTrustSettingsPolicy
, policy
);
1248 if(tsResult
!= kSecTrustSettingsResultTrustRoot
) {
1249 /* skip if we're specifying the default */
1250 SInt32 result
= tsResult
;
1251 CFNumberRef cfNum
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &result
);
1252 CFDictionarySetValue(usageDict
, kSecTrustSettingsResult
, cfNum
);
1255 return SecTrustSettingsSetTrustSettings(certificate
, kSecTrustSettingsDomainUser
,
1258 /* this function is unsupported in unified SecTrust */
1259 #if SECTRUST_DEPRECATION_WARNINGS
1260 syslog(LOG_ERR
, "WARNING: SecTrustSetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
1262 return errSecServiceNotAvailable
;
1267 // This one is the now-private version of what SecTrustSetUserTrust() used to
1268 // be. The public API can no longer manipulate User Trust settings, only
1271 OSStatus
SecTrustSetUserTrustLegacy(SecCertificateRef certificate
,
1272 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
1276 switch (trustSetting
) {
1277 case kSecTrustResultProceed
:
1278 case kSecTrustResultConfirm
:
1279 case kSecTrustResultDeny
:
1280 case kSecTrustResultUnspecified
:
1283 MacOSError::throwMe(errSecInvalidTrustSetting
);
1285 Trust::gStore().assign(
1286 Certificate::required(certificate
),
1287 Policy::required(policy
),
1291 /* this function is unsupported in unified SecTrust */
1292 #if SECTRUST_DEPRECATION_WARNINGS
1293 syslog(LOG_ERR
, "WARNING: SecTrustSetUserTrustLegacy does nothing in 10.11. Please stop using it.");
1295 return errSecServiceNotAvailable
;