2 * Copyright (c) 2002-2010,2012-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 #include "SecTrustPriv.h"
27 #include <security_keychain/SecTrustSettingsPriv.h>
28 #include "SecBridge.h"
29 #include "SecInternal.h"
30 #include "SecInternalP.h"
31 #include "SecTrustSettings.h"
32 #include "SecCertificatePriv.h"
33 #include "SecCertificateP.h"
34 #include "SecCertificatePrivP.h"
35 #include <security_utilities/cfutilities.h>
36 #include <security_utilities/cfmunge.h>
37 #include <CoreFoundation/CoreFoundation.h>
39 // forward declarations
40 CFArrayRef
SecTrustCopyDetails(SecTrustRef trust
);
41 static CFDictionaryRef
SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust
, CFIndex ix
);
42 static void SecTrustCheckException(const void *key
, const void *value
, void *context
);
44 typedef struct SecTrustCheckExceptionContext
{
45 CFDictionaryRef exception
;
46 bool exceptionNotFound
;
47 } SecTrustCheckExceptionContext
;
49 // public trust result constants
50 CFTypeRef kSecTrustEvaluationDate
= CFSTR("TrustEvaluationDate");
51 CFTypeRef kSecTrustExtendedValidation
= CFSTR("TrustExtendedValidation");
52 CFTypeRef kSecTrustOrganizationName
= CFSTR("Organization");
53 CFTypeRef kSecTrustResultValue
= CFSTR("TrustResultValue");
54 CFTypeRef kSecTrustRevocationChecked
= CFSTR("TrustRevocationChecked");
55 CFTypeRef kSecTrustRevocationValidUntilDate
= CFSTR("TrustExpirationDate");
56 CFTypeRef kSecTrustResultDetails
= CFSTR("TrustResultDetails");
61 CFTypeID
SecTrustGetTypeID(void)
65 return gTypes().Trust
.typeID
;
67 END_SECAPI1(_kCFRuntimeNotATypeID
)
72 // Sec* API bridge functions
74 OSStatus
SecTrustCreateWithCertificates(
75 CFTypeRef certificates
,
77 SecTrustRef
*trustRef
)
81 *trustRef
= (new Trust(certificates
, policies
))->handle();
86 SecTrustSetPolicies(SecTrustRef trustRef
, CFTypeRef policies
)
89 Trust::required(trustRef
)->policies(policies
);
94 SecTrustSetOptions(SecTrustRef trustRef
, SecTrustOptionFlags options
)
97 CSSM_APPLE_TP_ACTION_DATA actionData
= {
98 CSSM_APPLE_TP_ACTION_VERSION
,
99 (CSSM_APPLE_TP_ACTION_FLAGS
)options
101 Trust
*trust
= Trust::required(trustRef
);
102 CFDataRef actionDataRef
= CFDataCreate(NULL
,
103 (const UInt8
*)&actionData
,
104 (CFIndex
)sizeof(CSSM_APPLE_TP_ACTION_DATA
));
105 trust
->action(CSSM_TP_ACTION_DEFAULT
);
106 trust
->actionData(actionDataRef
);
107 if (actionDataRef
) CFRelease(actionDataRef
);
111 OSStatus
SecTrustSetParameters(
112 SecTrustRef trustRef
,
113 CSSM_TP_ACTION action
,
114 CFDataRef actionData
)
117 Trust
*trust
= Trust::required(trustRef
);
118 trust
->action(action
);
119 trust
->actionData(actionData
);
124 OSStatus
SecTrustSetAnchorCertificates(SecTrustRef trust
, CFArrayRef anchorCertificates
)
127 Trust::required(trust
)->anchors(anchorCertificates
);
131 OSStatus
SecTrustSetAnchorCertificatesOnly(SecTrustRef trust
, Boolean anchorCertificatesOnly
)
134 Trust::AnchorPolicy policy
= (anchorCertificatesOnly
) ? Trust::useAnchorsOnly
: Trust::useAnchorsAndBuiltIns
;
135 Trust::required(trust
)->anchorPolicy(policy
);
139 OSStatus
SecTrustSetKeychains(SecTrustRef trust
, CFTypeRef keychainOrArray
)
142 StorageManager::KeychainList keychains
;
143 // avoid unnecessary global initializations if an empty array is passed in
144 if (!( (keychainOrArray
!= NULL
) &&
145 (CFGetTypeID(keychainOrArray
) == CFArrayGetTypeID()) &&
146 (CFArrayGetCount((CFArrayRef
)keychainOrArray
) == 0) )) {
147 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
149 Trust::required(trust
)->searchLibs(keychains
);
154 OSStatus
SecTrustSetVerifyDate(SecTrustRef trust
, CFDateRef verifyDate
)
157 Trust::required(trust
)->time(verifyDate
);
162 CFAbsoluteTime
SecTrustGetVerifyTime(SecTrustRef trust
)
164 CFAbsoluteTime verifyTime
= 0;
165 OSStatus __secapiresult
= errSecSuccess
;
167 CFRef
<CFDateRef
> verifyDate
= Trust::required(trust
)->time();
168 verifyTime
= CFDateGetAbsoluteTime(verifyDate
);
170 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
171 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
172 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
173 catch (...) { __secapiresult
=errSecInternalComponent
; }
178 OSStatus
SecTrustEvaluate(SecTrustRef trust
, SecTrustResultType
*resultP
)
180 SecTrustResultType trustResult
= kSecTrustResultInvalid
;
181 CFArrayRef exceptions
= NULL
;
182 OSStatus __secapiresult
= errSecSuccess
;
184 Trust
*trustObj
= Trust::required(trust
);
185 trustObj
->evaluate();
186 trustResult
= trustObj
->result();
187 exceptions
= trustObj
->exceptions();
189 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
190 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
191 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
192 catch (...) { __secapiresult
=errSecInternalComponent
; }
194 if (__secapiresult
) {
195 return __secapiresult
;
198 /* post-process trust result based on exceptions */
199 if (trustResult
== kSecTrustResultUnspecified
) {
200 /* If leaf is in exceptions -> proceed, otherwise unspecified. */
201 if (SecTrustGetExceptionForCertificateAtIndex(trust
, 0))
202 trustResult
= kSecTrustResultProceed
;
204 else if (trustResult
== kSecTrustResultRecoverableTrustFailure
&& exceptions
) {
205 /* If we have exceptions get details and match to exceptions. */
206 CFArrayRef details
= SecTrustCopyDetails(trust
);
208 CFIndex pathLength
= CFArrayGetCount(details
);
209 struct SecTrustCheckExceptionContext context
= {};
211 for (ix
= 0; ix
< pathLength
; ++ix
) {
212 CFDictionaryRef detail
= (CFDictionaryRef
)CFArrayGetValueAtIndex(details
, ix
);
213 // if ((ix == 0) && CFDictionaryContainsKey(detail, kSecPolicyCheckBlackListedLeaf))
214 // trustResult = kSecTrustResultFatalTrustFailure;
215 context
.exception
= SecTrustGetExceptionForCertificateAtIndex(trust
, ix
);
216 CFDictionaryApplyFunction(detail
, SecTrustCheckException
, &context
);
217 if (context
.exceptionNotFound
) {
221 if (!context
.exceptionNotFound
)
222 trustResult
= kSecTrustResultProceed
;
227 secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult
);
229 *resultP
= trustResult
;
231 return __secapiresult
;
234 OSStatus
SecTrustEvaluateAsync(SecTrustRef trust
,
235 dispatch_queue_t queue
, SecTrustCallback result
)
238 dispatch_async(queue
, ^{
240 Trust
*trustObj
= Trust::required(trust
);
241 trustObj
->evaluate();
242 SecTrustResultType trustResult
= trustObj
->result();
243 result(trust
, trustResult
);
246 result(trust
, kSecTrustResultInvalid
);
253 // Construct the "official" result evidence and return it
255 OSStatus
SecTrustGetResult(
256 SecTrustRef trustRef
,
257 SecTrustResultType
*result
,
258 CFArrayRef
*certChain
, CSSM_TP_APPLE_EVIDENCE_INFO
**statusChain
)
261 Trust
*trust
= Trust::required(trustRef
);
263 *result
= trust
->result();
264 if (certChain
&& statusChain
)
265 trust
->buildEvidence(*certChain
, TPEvidenceInfo::overlayVar(*statusChain
));
270 // Retrieve result of trust evaluation only
272 OSStatus
SecTrustGetTrustResult(SecTrustRef trustRef
,
273 SecTrustResultType
*result
)
276 Trust
*trust
= Trust::required(trustRef
);
277 if (result
) *result
= trust
->result();
282 // Retrieve extended validation trust results
284 OSStatus
SecTrustCopyExtendedResult(SecTrustRef trust
, CFDictionaryRef
*result
)
287 Trust
*trustObj
= Trust::required(trust
);
290 trustObj
->extendedResult(*result
);
295 // Retrieve CSSM-level information for those who want to dig down
297 OSStatus
SecTrustGetCssmResult(SecTrustRef trust
, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR
*result
)
300 Required(result
) = Trust::required(trust
)->cssmResult();
305 // Retrieve CSSM_LEVEL TP return code
307 OSStatus
SecTrustGetCssmResultCode(SecTrustRef trustRef
, OSStatus
*result
)
310 Trust
*trust
= Trust::required(trustRef
);
311 if (trust
->result() == kSecTrustResultInvalid
)
314 Required(result
) = trust
->cssmResultCode();
318 OSStatus
SecTrustGetTPHandle(SecTrustRef trust
, CSSM_TP_HANDLE
*handle
)
321 Required(handle
) = Trust::required(trust
)->getTPHandle();
325 OSStatus
SecTrustCopyPolicies(SecTrustRef trust
, CFArrayRef
*policies
)
328 CFArrayRef currentPolicies
= Trust::required(trust
)->policies();
329 if (currentPolicies
!= NULL
)
331 CFRetain(currentPolicies
);
334 Required(policies
) = currentPolicies
;
338 OSStatus
SecTrustSetNetworkFetchAllowed(SecTrustRef trust
, Boolean allowFetch
)
341 Trust
*trustObj
= Trust::required(trust
);
342 Trust::NetworkPolicy netPolicy
= (allowFetch
) ?
343 Trust::useNetworkEnabled
: Trust::useNetworkDisabled
;
344 trustObj
->networkPolicy(netPolicy
);
348 OSStatus
SecTrustGetNetworkFetchAllowed(SecTrustRef trust
, Boolean
*allowFetch
)
351 Boolean allowed
= false;
352 Trust
*trustObj
= Trust::required(trust
);
353 Trust::NetworkPolicy netPolicy
= trustObj
->networkPolicy();
354 if (netPolicy
== Trust::useNetworkDefault
) {
355 // network fetch is enabled by default for SSL only
356 allowed
= trustObj
->policySpecified(trustObj
->policies(), CSSMOID_APPLE_TP_SSL
);
358 // caller has explicitly set the network policy
359 allowed
= (netPolicy
== Trust::useNetworkEnabled
);
361 Required(allowFetch
) = allowed
;
365 OSStatus
SecTrustSetOCSPResponse(SecTrustRef trust
, CFTypeRef responseData
)
368 Trust::required(trust
)->responses(responseData
);
372 OSStatus
SecTrustCopyCustomAnchorCertificates(SecTrustRef trust
, CFArrayRef
*anchorCertificates
)
375 CFArrayRef customAnchors
= Trust::required(trust
)->anchors();
376 Required(anchorCertificates
) = (customAnchors
) ?
377 (const CFArrayRef
)CFRetain(customAnchors
) : (const CFArrayRef
)NULL
;
382 // Get the user's default anchor certificate set
384 OSStatus
SecTrustCopyAnchorCertificates(CFArrayRef
*anchorCertificates
)
388 return SecTrustSettingsCopyUnrestrictedRoots(
389 true, true, true, /* all domains */
396 SecKeyRef
SecTrustCopyPublicKey(SecTrustRef trust
)
398 SecKeyRef pubKey
= NULL
;
399 CFArrayRef certChain
= NULL
;
400 CFArrayRef evidenceChain
= NULL
;
401 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
402 OSStatus __secapiresult
= errSecSuccess
;
404 Trust
*trustObj
= Trust::required(trust
);
405 if (trustObj
->result() == kSecTrustResultInvalid
)
406 MacOSError::throwMe(errSecTrustNotAvailable
);
407 if (trustObj
->evidence() == nil
)
408 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
409 evidenceChain
= trustObj
->evidence();
411 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
412 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
413 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
414 catch (...) { __secapiresult
=errSecInternalComponent
; }
417 CFRelease(certChain
);
420 if (CFArrayGetCount(evidenceChain
) > 0) {
421 SecCertificateRef cert
= (SecCertificateRef
) CFArrayGetValueAtIndex(evidenceChain
, 0);
422 __secapiresult
= SecCertificateCopyPublicKey(cert
, &pubKey
);
424 // do not release evidenceChain, as it is owned by the trust object.
430 CFIndex
SecTrustGetCertificateCount(SecTrustRef trust
)
432 CFIndex chainLen
= 0;
433 CFArrayRef certChain
= NULL
;
434 CFArrayRef evidenceChain
= NULL
;
435 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
436 OSStatus __secapiresult
= errSecSuccess
;
438 Trust
*trustObj
= Trust::required(trust
);
439 if (trustObj
->result() == kSecTrustResultInvalid
) {
440 trustObj
->evaluate();
441 if (trustObj
->result() == kSecTrustResultInvalid
)
442 MacOSError::throwMe(errSecTrustNotAvailable
);
444 if (trustObj
->evidence() == nil
)
445 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
446 evidenceChain
= trustObj
->evidence();
448 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
449 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
450 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
451 catch (...) { __secapiresult
=errSecInternalComponent
; }
454 CFRelease(certChain
);
457 chainLen
= CFArrayGetCount(evidenceChain
); // don't release, trust object owns it.
463 SecCertificateRef
SecTrustGetCertificateAtIndex(SecTrustRef trust
, CFIndex ix
)
465 SecCertificateRef certificate
= NULL
;
466 CFArrayRef certChain
= NULL
;
467 CFArrayRef evidenceChain
= NULL
;
468 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
469 OSStatus __secapiresult
= errSecSuccess
;
471 Trust
*trustObj
= Trust::required(trust
);
472 if (trustObj
->result() == kSecTrustResultInvalid
) {
473 trustObj
->evaluate();
474 if (trustObj
->result() == kSecTrustResultInvalid
)
475 MacOSError::throwMe(errSecTrustNotAvailable
);
477 if (trustObj
->evidence() == nil
)
478 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
479 evidenceChain
= trustObj
->evidence();
481 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
482 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
483 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
484 catch (...) { __secapiresult
=errSecInternalComponent
; }
487 CFRelease(certChain
);
490 if (ix
< CFArrayGetCount(evidenceChain
)) {
491 certificate
= (SecCertificateRef
) CFArrayGetValueAtIndex(evidenceChain
, ix
);
492 // note: we do not retain this certificate. The assumption here is
493 // that the certificate is retained by the trust object, so it is
494 // valid unil the trust is released (or until re-evaluated.)
495 // also note: we do not release the evidenceChain, as it is owned
496 // by the trust object.
503 static CFStringRef kSecCertificateDetailSHA1Digest
= CFSTR("SHA1Digest");
504 static CFStringRef kSecCertificateDetailStatusCodes
= CFSTR("StatusCodes");
507 _AppendStatusCode(CFMutableArrayRef array
, OSStatus statusCode
)
511 SInt32 num
= statusCode
;
512 CFNumberRef numRef
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &num
);
515 CFArrayAppendValue(array
, numRef
);
519 CFArrayRef
SecTrustCopyDetails(SecTrustRef trust
)
521 // This function returns an array of dictionaries, one per certificate,
522 // holding status info for each certificate in the evaluated chain.
524 CFIndex count
, chainLen
= 0;
525 CFArrayRef certChain
= NULL
;
526 CFMutableArrayRef details
= NULL
;
527 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
528 OSStatus __secapiresult
= errSecSuccess
;
530 Trust
*trustObj
= Trust::required(trust
);
531 if (trustObj
->result() == kSecTrustResultInvalid
) {
532 trustObj
->evaluate();
533 if (trustObj
->result() == kSecTrustResultInvalid
)
534 MacOSError::throwMe(errSecTrustNotAvailable
);
536 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
538 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
539 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
540 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
541 catch (...) { __secapiresult
=errSecInternalComponent
; }
544 chainLen
= CFArrayGetCount(certChain
);
545 CFRelease(certChain
);
548 details
= CFArrayCreateMutable(NULL
, chainLen
, &kCFTypeArrayCallBacks
);
549 for (count
= 0; count
< chainLen
; count
++) {
550 CFMutableDictionaryRef certDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
551 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
552 CFMutableArrayRef statusCodes
= CFArrayCreateMutable(kCFAllocatorDefault
,
553 0, &kCFTypeArrayCallBacks
);
554 CSSM_TP_APPLE_EVIDENCE_INFO
*evInfo
= &statusChain
[count
];
555 CSSM_TP_APPLE_CERT_STATUS statBits
= evInfo
->StatusBits
;
557 // translate status bits
558 if (statBits
& CSSM_CERT_STATUS_EXPIRED
)
559 _AppendStatusCode(statusCodes
, errSecCertificateExpired
);
560 if (statBits
& CSSM_CERT_STATUS_NOT_VALID_YET
)
561 _AppendStatusCode(statusCodes
, errSecCertificateNotValidYet
);
562 if (statBits
& CSSM_CERT_STATUS_TRUST_SETTINGS_DENY
)
563 _AppendStatusCode(statusCodes
, errSecTrustSettingDeny
);
565 // translate status codes
567 for (i
= 0; i
< evInfo
->NumStatusCodes
; i
++) {
568 CSSM_RETURN scode
= evInfo
->StatusCodes
[i
];
569 _AppendStatusCode(statusCodes
, (OSStatus
)scode
);
572 CFDictionarySetValue(certDict
, kSecCertificateDetailStatusCodes
, statusCodes
);
573 CFRelease(statusCodes
);
574 CFArrayAppendValue(details
, certDict
);
581 static CFDictionaryRef
SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust
, CFIndex ix
)
583 CFArrayRef exceptions
= NULL
;
584 OSStatus __secapiresult
= errSecSuccess
;
586 exceptions
= Trust::required(trust
)->exceptions();
588 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
589 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
590 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
591 catch (...) { __secapiresult
=errSecInternalComponent
; }
593 if (!exceptions
|| ix
>= CFArrayGetCount(exceptions
))
595 CFDictionaryRef exception
= (CFDictionaryRef
)CFArrayGetValueAtIndex(exceptions
, ix
);
596 if (CFGetTypeID(exception
) != CFDictionaryGetTypeID())
599 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, ix
);
603 /* If the exception contains the current certificate's sha1Digest in the
604 kSecCertificateDetailSHA1Digest key then we use it otherwise we ignore it. */
605 CFDataRef sha1Digest
= SecCertificateGetSHA1Digest(certificate
);
606 CFTypeRef digestValue
= CFDictionaryGetValue(exception
, kSecCertificateDetailSHA1Digest
);
607 if (!digestValue
|| !CFEqual(sha1Digest
, digestValue
))
613 static void SecTrustCheckException(const void *key
, const void *value
, void *context
)
615 struct SecTrustCheckExceptionContext
*cec
= (struct SecTrustCheckExceptionContext
*)context
;
616 if (cec
->exception
) {
617 CFTypeRef exceptionValue
= CFDictionaryGetValue(cec
->exception
, key
);
618 if (!exceptionValue
|| !CFEqual(value
, exceptionValue
)) {
619 cec
->exceptionNotFound
= true;
622 cec
->exceptionNotFound
= true;
627 CFDataRef
SecTrustCopyExceptions(SecTrustRef trust
)
629 CFArrayRef details
= SecTrustCopyDetails(trust
);
630 CFIndex pathLength
= details
? CFArrayGetCount(details
) : 0;
631 CFMutableArrayRef exceptions
= CFArrayCreateMutable(kCFAllocatorDefault
,
632 pathLength
, &kCFTypeArrayCallBacks
);
634 for (ix
= 0; ix
< pathLength
; ++ix
) {
635 CFDictionaryRef detail
= (CFDictionaryRef
)CFArrayGetValueAtIndex(details
, ix
);
636 CFIndex detailCount
= CFDictionaryGetCount(detail
);
637 CFMutableDictionaryRef exception
;
638 if (ix
== 0 || detailCount
> 0) {
639 exception
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
,
640 detailCount
+ 1, detail
);
641 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, ix
);
642 CFDataRef digest
= SecCertificateGetSHA1Digest(certificate
);
644 CFDictionaryAddValue(exception
, kSecCertificateDetailSHA1Digest
, digest
);
647 /* Add empty exception dictionaries for non leaf certs which have no exceptions
650 exception
= (CFMutableDictionaryRef
)CFDictionaryCreate(kCFAllocatorDefault
,
652 &kCFTypeDictionaryKeyCallBacks
,
653 &kCFTypeDictionaryValueCallBacks
);
655 CFArrayAppendValue(exceptions
, exception
);
656 CFReleaseNull(exception
);
658 CFReleaseSafe(details
);
660 /* Remove any trailing empty dictionaries to save even more space (we skip the leaf
661 since it will never be empty). */
662 for (ix
= pathLength
; ix
-- > 1;) {
663 CFDictionaryRef exception
= (CFDictionaryRef
)CFArrayGetValueAtIndex(exceptions
, ix
);
664 if (CFDictionaryGetCount(exception
) == 0) {
665 CFArrayRemoveValueAtIndex(exceptions
, ix
);
671 CFDataRef encodedExceptions
= CFPropertyListCreateData(kCFAllocatorDefault
,
672 exceptions
, kCFPropertyListBinaryFormat_v1_0
, 0, NULL
);
673 CFRelease(exceptions
);
675 return encodedExceptions
;
679 bool SecTrustSetExceptions(SecTrustRef trust
, CFDataRef encodedExceptions
)
681 CFArrayRef exceptions
;
682 exceptions
= (CFArrayRef
)CFPropertyListCreateWithData(kCFAllocatorDefault
,
683 encodedExceptions
, kCFPropertyListImmutable
, NULL
, NULL
);
684 if (exceptions
&& CFGetTypeID(exceptions
) != CFArrayGetTypeID()) {
685 CFRelease(exceptions
);
689 OSStatus __secapiresult
= errSecSuccess
;
691 Trust::required(trust
)->exceptions(exceptions
);
693 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
694 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
695 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
696 catch (...) { __secapiresult
=errSecInternalComponent
; }
698 /* If there is a valid exception entry for our current leaf we're golden. */
699 if (SecTrustGetExceptionForCertificateAtIndex(trust
, 0))
702 /* The passed in exceptions didn't match our current leaf, so we discard it. */
704 Trust::required(trust
)->exceptions(NULL
);
705 __secapiresult
= errSecSuccess
;
707 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
708 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
709 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
710 catch (...) { __secapiresult
=errSecInternalComponent
; }
717 SecTrustCopyResult(SecTrustRef trust
)
719 CFDictionaryRef result
= NULL
;
721 result
= Trust::required(trust
)->results();
722 // merge details into result
723 CFArrayRef details
= SecTrustCopyDetails(trust
);
725 CFDictionarySetValue((CFMutableDictionaryRef
)result
,
726 kSecTrustResultDetails
, details
);
741 SecTrustCopyProperties(SecTrustRef trust
)
743 /* can't use SECAPI macros, since this function does not return OSStatus */
744 CFArrayRef result
= NULL
;
746 result
= Trust::required(trust
)->properties();
758 /* deprecated in 10.5 */
759 OSStatus
SecTrustGetCSSMAnchorCertificates(const CSSM_DATA
**cssmAnchors
,
760 uint32
*cssmAnchorCount
)
764 Trust::gStore().getCssmRootCertificates(certs
);
765 Required(cssmAnchors
) = certs
.blobCerts();
766 Required(cssmAnchorCount
) = certs
.count();
772 // Get and set user trust settings. Deprecated in 10.5.
773 // User Trust getter, deprecated, works as it always has.
775 OSStatus
SecTrustGetUserTrust(SecCertificateRef certificate
,
776 SecPolicyRef policy
, SecTrustUserSetting
*trustSetting
)
779 StorageManager::KeychainList searchList
;
780 globals().storageManager
.getSearchList(searchList
);
781 Required(trustSetting
) = Trust::gStore().find(
782 Certificate::required(certificate
),
783 Policy::required(policy
),
789 // The public setter, also deprecated; it maps to the appropriate
790 // Trust Settings call if possible, else throws errSecUnimplemented.
792 OSStatus
SecTrustSetUserTrust(SecCertificateRef certificate
,
793 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
795 SecTrustSettingsResult tsResult
= kSecTrustSettingsResultInvalid
;
799 Policy::required(policy
);
800 switch(trustSetting
) {
801 case kSecTrustResultProceed
:
802 /* different SecTrustSettingsResult depending in root-ness */
803 ortn
= SecCertificateIsSelfSigned(certificate
, &isRoot
);
808 tsResult
= kSecTrustSettingsResultTrustRoot
;
811 tsResult
= kSecTrustSettingsResultTrustAsRoot
;
814 case kSecTrustResultDeny
:
815 tsResult
= kSecTrustSettingsResultDeny
;
818 return errSecUnimplemented
;
821 /* make a usage constraints dictionary */
822 CFRef
<CFMutableDictionaryRef
> usageDict(CFDictionaryCreateMutable(NULL
,
823 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
));
824 CFDictionaryAddValue(usageDict
, kSecTrustSettingsPolicy
, policy
);
825 if(tsResult
!= kSecTrustSettingsResultTrustRoot
) {
826 /* skip if we're specifying the default */
827 SInt32 result
= tsResult
;
828 CFNumberRef cfNum
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &result
);
829 CFDictionarySetValue(usageDict
, kSecTrustSettingsResult
, cfNum
);
832 return SecTrustSettingsSetTrustSettings(certificate
, kSecTrustSettingsDomainUser
,
837 // This one is the now-private version of what SecTrustSetUserTrust() used to
838 // be. The public API can no longer manipulate User Trust settings, only
841 OSStatus
SecTrustSetUserTrustLegacy(SecCertificateRef certificate
,
842 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
845 switch (trustSetting
) {
846 case kSecTrustResultProceed
:
847 case kSecTrustResultConfirm
:
848 case kSecTrustResultDeny
:
849 case kSecTrustResultUnspecified
:
852 MacOSError::throwMe(errSecInvalidTrustSetting
);
854 Trust::gStore().assign(
855 Certificate::required(certificate
),
856 Policy::required(policy
),
861 /* SecGetAppleTPHandle - @@@NOT EXPORTED YET; copied from SecurityInterface,
862 but could be useful in the future.
866 SecGetAppleTPHandle()
869 return TP(gGuidAppleX509TP)->handle();