2 * Copyright (c) 2002-2010,2012 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 "SecTrustSettings.h"
31 #include "SecCertificatePriv.h"
32 #include <security_utilities/cfutilities.h>
33 #include <security_utilities/cfmunge.h>
34 #include <CoreFoundation/CoreFoundation.h>
36 // forward declarations
37 CFArrayRef
SecTrustCopyDetails(SecTrustRef trust
);
38 static CFDictionaryRef
SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust
, CFIndex ix
);
39 static void SecTrustCheckException(const void *key
, const void *value
, void *context
);
41 typedef struct SecTrustCheckExceptionContext
{
42 CFDictionaryRef exception
;
43 bool exceptionNotFound
;
44 } SecTrustCheckExceptionContext
;
46 // public trust result constants
47 CFTypeRef kSecTrustEvaluationDate
= CFSTR("TrustEvaluationDate");
48 CFTypeRef kSecTrustExtendedValidation
= CFSTR("TrustExtendedValidation");
49 CFTypeRef kSecTrustOrganizationName
= CFSTR("Organization");
50 CFTypeRef kSecTrustResultValue
= CFSTR("TrustResultValue");
51 CFTypeRef kSecTrustRevocationChecked
= CFSTR("TrustRevocationChecked");
52 CFTypeRef kSecTrustRevocationValidUntilDate
= CFSTR("TrustExpirationDate");
53 CFTypeRef kSecTrustResultDetails
= CFSTR("TrustResultDetails");
58 CFTypeID
SecTrustGetTypeID(void)
62 return gTypes().Trust
.typeID
;
64 END_SECAPI1(_kCFRuntimeNotATypeID
)
69 // Sec* API bridge functions
71 OSStatus
SecTrustCreateWithCertificates(
72 CFTypeRef certificates
,
74 SecTrustRef
*trustRef
)
78 *trustRef
= (new Trust(certificates
, policies
))->handle();
83 SecTrustSetPolicies(SecTrustRef trustRef
, CFTypeRef policies
)
86 Trust::required(trustRef
)->policies(policies
);
91 SecTrustSetOptions(SecTrustRef trustRef
, SecTrustOptionFlags options
)
94 CSSM_APPLE_TP_ACTION_DATA actionData
= {
95 CSSM_APPLE_TP_ACTION_VERSION
,
96 (CSSM_APPLE_TP_ACTION_FLAGS
)options
98 Trust
*trust
= Trust::required(trustRef
);
99 CFDataRef actionDataRef
= CFDataCreate(NULL
,
100 (const UInt8
*)&actionData
,
101 (CFIndex
)sizeof(CSSM_APPLE_TP_ACTION_DATA
));
102 trust
->action(CSSM_TP_ACTION_DEFAULT
);
103 trust
->actionData(actionDataRef
);
104 if (actionDataRef
) CFRelease(actionDataRef
);
108 OSStatus
SecTrustSetParameters(
109 SecTrustRef trustRef
,
110 CSSM_TP_ACTION action
,
111 CFDataRef actionData
)
114 Trust
*trust
= Trust::required(trustRef
);
115 trust
->action(action
);
116 trust
->actionData(actionData
);
121 OSStatus
SecTrustSetAnchorCertificates(SecTrustRef trust
, CFArrayRef anchorCertificates
)
124 Trust::required(trust
)->anchors(anchorCertificates
);
128 OSStatus
SecTrustSetAnchorCertificatesOnly(SecTrustRef trust
, Boolean anchorCertificatesOnly
)
131 Trust::AnchorPolicy policy
= (anchorCertificatesOnly
) ? Trust::useAnchorsOnly
: Trust::useAnchorsAndBuiltIns
;
132 Trust::required(trust
)->anchorPolicy(policy
);
136 OSStatus
SecTrustSetKeychains(SecTrustRef trust
, CFTypeRef keychainOrArray
)
139 StorageManager::KeychainList keychains
;
140 // avoid unnecessary global initializations if an empty array is passed in
141 if (!( (keychainOrArray
!= NULL
) &&
142 (CFGetTypeID(keychainOrArray
) == CFArrayGetTypeID()) &&
143 (CFArrayGetCount((CFArrayRef
)keychainOrArray
) == 0) )) {
144 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
146 Trust::required(trust
)->searchLibs(keychains
);
151 OSStatus
SecTrustSetVerifyDate(SecTrustRef trust
, CFDateRef verifyDate
)
154 Trust::required(trust
)->time(verifyDate
);
159 CFAbsoluteTime
SecTrustGetVerifyTime(SecTrustRef trust
)
161 CFAbsoluteTime verifyTime
= 0;
162 OSStatus __secapiresult
= errSecSuccess
;
164 CFRef
<CFDateRef
> verifyDate
= Trust::required(trust
)->time();
165 verifyTime
= CFDateGetAbsoluteTime(verifyDate
);
167 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
168 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
169 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
170 catch (...) { __secapiresult
=errSecInternalComponent
; }
176 OSStatus
SecTrustEvaluate(SecTrustRef trust
, SecTrustResultType
*resultP
)
178 SecTrustResultType trustResult
= kSecTrustResultInvalid
;
179 CFArrayRef exceptions
= NULL
;
180 OSStatus __secapiresult
= errSecSuccess
;
182 Trust
*trustObj
= Trust::required(trust
);
183 trustObj
->evaluate();
184 trustResult
= trustObj
->result();
185 exceptions
= trustObj
->exceptions();
187 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
188 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
189 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
190 catch (...) { __secapiresult
=errSecInternalComponent
; }
192 if (__secapiresult
) {
193 return __secapiresult
;
196 /* post-process trust result based on exceptions */
197 if (trustResult
== kSecTrustResultUnspecified
) {
198 /* If leaf is in exceptions -> proceed, otherwise unspecified. */
199 if (SecTrustGetExceptionForCertificateAtIndex(trust
, 0))
200 trustResult
= kSecTrustResultProceed
;
202 else if (trustResult
== kSecTrustResultRecoverableTrustFailure
&& exceptions
) {
203 /* If we have exceptions get details and match to exceptions. */
204 CFArrayRef details
= SecTrustCopyDetails(trust
);
206 CFIndex pathLength
= CFArrayGetCount(details
);
207 struct SecTrustCheckExceptionContext context
= {};
209 for (ix
= 0; ix
< pathLength
; ++ix
) {
210 CFDictionaryRef detail
= (CFDictionaryRef
)CFArrayGetValueAtIndex(details
, ix
);
211 // if ((ix == 0) && CFDictionaryContainsKey(detail, kSecPolicyCheckBlackListedLeaf))
212 // trustResult = kSecTrustResultFatalTrustFailure;
213 context
.exception
= SecTrustGetExceptionForCertificateAtIndex(trust
, ix
);
214 CFDictionaryApplyFunction(detail
, SecTrustCheckException
, &context
);
215 if (context
.exceptionNotFound
) {
219 if (!context
.exceptionNotFound
)
220 trustResult
= kSecTrustResultProceed
;
225 secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult
);
227 *resultP
= trustResult
;
229 return __secapiresult
;
232 OSStatus
SecTrustEvaluateAsync(SecTrustRef trust
,
233 dispatch_queue_t queue
, SecTrustCallback result
)
236 dispatch_async(queue
, ^{
238 Trust
*trustObj
= Trust::required(trust
);
239 trustObj
->evaluate();
240 SecTrustResultType trustResult
= trustObj
->result();
241 result(trust
, trustResult
);
244 result(trust
, kSecTrustResultInvalid
);
251 // Construct the "official" result evidence and return it
253 OSStatus
SecTrustGetResult(
254 SecTrustRef trustRef
,
255 SecTrustResultType
*result
,
256 CFArrayRef
*certChain
, CSSM_TP_APPLE_EVIDENCE_INFO
**statusChain
)
259 Trust
*trust
= Trust::required(trustRef
);
261 *result
= trust
->result();
262 if (certChain
&& statusChain
)
263 trust
->buildEvidence(*certChain
, TPEvidenceInfo::overlayVar(*statusChain
));
268 // Retrieve result of trust evaluation only
270 OSStatus
SecTrustGetTrustResult(SecTrustRef trustRef
,
271 SecTrustResultType
*result
)
274 Trust
*trust
= Trust::required(trustRef
);
275 if (result
) *result
= trust
->result();
280 // Retrieve extended validation trust results
282 OSStatus
SecTrustCopyExtendedResult(SecTrustRef trust
, CFDictionaryRef
*result
)
285 Trust
*trustObj
= Trust::required(trust
);
288 trustObj
->extendedResult(*result
);
293 // Retrieve CSSM-level information for those who want to dig down
295 OSStatus
SecTrustGetCssmResult(SecTrustRef trust
, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR
*result
)
298 Required(result
) = Trust::required(trust
)->cssmResult();
303 // Retrieve CSSM_LEVEL TP return code
305 OSStatus
SecTrustGetCssmResultCode(SecTrustRef trustRef
, OSStatus
*result
)
308 Trust
*trust
= Trust::required(trustRef
);
309 if (trust
->result() == kSecTrustResultInvalid
)
312 Required(result
) = trust
->cssmResultCode();
316 OSStatus
SecTrustGetTPHandle(SecTrustRef trust
, CSSM_TP_HANDLE
*handle
)
319 Required(handle
) = Trust::required(trust
)->getTPHandle();
323 OSStatus
SecTrustCopyPolicies(SecTrustRef trust
, CFArrayRef
*policies
)
326 CFArrayRef currentPolicies
= Trust::required(trust
)->policies();
327 if (currentPolicies
!= NULL
)
329 CFRetain(currentPolicies
);
332 Required(policies
) = currentPolicies
;
336 OSStatus
SecTrustSetNetworkFetchAllowed(SecTrustRef trust
, Boolean allowFetch
)
339 Trust
*trustObj
= Trust::required(trust
);
340 Trust::NetworkPolicy netPolicy
= (allowFetch
) ?
341 Trust::useNetworkEnabled
: Trust::useNetworkDisabled
;
342 trustObj
->networkPolicy(netPolicy
);
346 OSStatus
SecTrustGetNetworkFetchAllowed(SecTrustRef trust
, Boolean
*allowFetch
)
349 Boolean allowed
= false;
350 Trust
*trustObj
= Trust::required(trust
);
351 Trust::NetworkPolicy netPolicy
= trustObj
->networkPolicy();
352 if (netPolicy
== Trust::useNetworkDefault
) {
353 // network fetch is enabled by default for SSL only
354 allowed
= trustObj
->policySpecified(trustObj
->policies(), CSSMOID_APPLE_TP_SSL
);
356 // caller has explicitly set the network policy
357 allowed
= (netPolicy
== Trust::useNetworkEnabled
);
359 Required(allowFetch
) = allowed
;
363 OSStatus
SecTrustSetOCSPResponse(SecTrustRef trust
, CFTypeRef responseData
)
366 Trust::required(trust
)->responses(responseData
);
370 OSStatus
SecTrustCopyCustomAnchorCertificates(SecTrustRef trust
, CFArrayRef
*anchorCertificates
)
373 CFArrayRef customAnchors
= Trust::required(trust
)->anchors();
374 Required(anchorCertificates
) = (customAnchors
) ?
375 (const CFArrayRef
)CFRetain(customAnchors
) : (const CFArrayRef
)NULL
;
380 // Get the user's default anchor certificate set
382 OSStatus
SecTrustCopyAnchorCertificates(CFArrayRef
*anchorCertificates
)
386 return SecTrustSettingsCopyUnrestrictedRoots(
387 true, true, true, /* all domains */
394 SecKeyRef
SecTrustCopyPublicKey(SecTrustRef trust
)
396 SecKeyRef pubKey
= NULL
;
397 CFArrayRef certChain
= NULL
;
398 CFArrayRef evidenceChain
= NULL
;
399 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
400 OSStatus __secapiresult
= errSecSuccess
;
402 Trust
*trustObj
= Trust::required(trust
);
403 if (trustObj
->result() == kSecTrustResultInvalid
)
404 MacOSError::throwMe(errSecTrustNotAvailable
);
405 if (trustObj
->evidence() == nil
)
406 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
407 evidenceChain
= trustObj
->evidence();
409 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
410 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
411 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
412 catch (...) { __secapiresult
=errSecInternalComponent
; }
415 CFRelease(certChain
);
418 if (CFArrayGetCount(evidenceChain
) > 0) {
419 SecCertificateRef cert
= (SecCertificateRef
) CFArrayGetValueAtIndex(evidenceChain
, 0);
420 __secapiresult
= SecCertificateCopyPublicKey(cert
, &pubKey
);
422 // do not release evidenceChain, as it is owned by the trust object.
428 CFIndex
SecTrustGetCertificateCount(SecTrustRef trust
)
430 CFIndex chainLen
= 0;
431 CFArrayRef certChain
= NULL
;
432 CFArrayRef evidenceChain
= NULL
;
433 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
434 OSStatus __secapiresult
= errSecSuccess
;
436 Trust
*trustObj
= Trust::required(trust
);
437 if (trustObj
->result() == kSecTrustResultInvalid
) {
438 trustObj
->evaluate();
439 if (trustObj
->result() == kSecTrustResultInvalid
)
440 MacOSError::throwMe(errSecTrustNotAvailable
);
442 if (trustObj
->evidence() == nil
)
443 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
444 evidenceChain
= trustObj
->evidence();
446 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
447 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
448 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
449 catch (...) { __secapiresult
=errSecInternalComponent
; }
452 CFRelease(certChain
);
455 chainLen
= CFArrayGetCount(evidenceChain
); // don't release, trust object owns it.
461 SecCertificateRef
SecTrustGetCertificateAtIndex(SecTrustRef trust
, CFIndex ix
)
463 SecCertificateRef certificate
= NULL
;
464 CFArrayRef certChain
= NULL
;
465 CFArrayRef evidenceChain
= NULL
;
466 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
467 OSStatus __secapiresult
= errSecSuccess
;
469 Trust
*trustObj
= Trust::required(trust
);
470 if (trustObj
->result() == kSecTrustResultInvalid
) {
471 trustObj
->evaluate();
472 if (trustObj
->result() == kSecTrustResultInvalid
)
473 MacOSError::throwMe(errSecTrustNotAvailable
);
475 if (trustObj
->evidence() == nil
)
476 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
477 evidenceChain
= trustObj
->evidence();
479 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
480 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
481 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
482 catch (...) { __secapiresult
=errSecInternalComponent
; }
485 CFRelease(certChain
);
488 if (ix
< CFArrayGetCount(evidenceChain
)) {
489 certificate
= (SecCertificateRef
) CFArrayGetValueAtIndex(evidenceChain
, ix
);
490 // note: we do not retain this certificate. The assumption here is
491 // that the certificate is retained by the trust object, so it is
492 // valid unil the trust is released (or until re-evaluated.)
493 // also note: we do not release the evidenceChain, as it is owned
494 // by the trust object.
501 static CFStringRef kSecCertificateDetailSHA1Digest
= CFSTR("SHA1Digest");
502 static CFStringRef kSecCertificateDetailStatusCodes
= CFSTR("StatusCodes");
505 _AppendStatusCode(CFMutableArrayRef array
, OSStatus statusCode
)
509 SInt32 num
= statusCode
;
510 CFNumberRef numRef
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &num
);
513 CFArrayAppendValue(array
, numRef
);
517 CFArrayRef
SecTrustCopyDetails(SecTrustRef trust
)
519 // This function returns an array of dictionaries, one per certificate,
520 // holding status info for each certificate in the evaluated chain.
522 CFIndex count
, chainLen
= 0;
523 CFArrayRef certChain
= NULL
;
524 CFMutableArrayRef details
= NULL
;
525 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
526 OSStatus __secapiresult
= errSecSuccess
;
528 Trust
*trustObj
= Trust::required(trust
);
529 if (trustObj
->result() == kSecTrustResultInvalid
) {
530 trustObj
->evaluate();
531 if (trustObj
->result() == kSecTrustResultInvalid
)
532 MacOSError::throwMe(errSecTrustNotAvailable
);
534 trustObj
->buildEvidence(certChain
, TPEvidenceInfo::overlayVar(statusChain
));
536 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
537 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
538 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
539 catch (...) { __secapiresult
=errSecInternalComponent
; }
542 chainLen
= CFArrayGetCount(certChain
);
543 CFRelease(certChain
);
546 details
= CFArrayCreateMutable(NULL
, chainLen
, &kCFTypeArrayCallBacks
);
547 for (count
= 0; count
< chainLen
; count
++) {
548 CFMutableDictionaryRef certDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
549 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
550 CFMutableArrayRef statusCodes
= CFArrayCreateMutable(kCFAllocatorDefault
,
551 0, &kCFTypeArrayCallBacks
);
552 CSSM_TP_APPLE_EVIDENCE_INFO
*evInfo
= &statusChain
[count
];
553 CSSM_TP_APPLE_CERT_STATUS statBits
= evInfo
->StatusBits
;
555 // translate status bits
556 if (statBits
& CSSM_CERT_STATUS_EXPIRED
)
557 _AppendStatusCode(statusCodes
, errSecCertificateExpired
);
558 if (statBits
& CSSM_CERT_STATUS_NOT_VALID_YET
)
559 _AppendStatusCode(statusCodes
, errSecCertificateNotValidYet
);
560 if (statBits
& CSSM_CERT_STATUS_TRUST_SETTINGS_DENY
)
561 _AppendStatusCode(statusCodes
, errSecTrustSettingDeny
);
563 // translate status codes
565 for (i
= 0; i
< evInfo
->NumStatusCodes
; i
++) {
566 CSSM_RETURN scode
= evInfo
->StatusCodes
[i
];
567 _AppendStatusCode(statusCodes
, (OSStatus
)scode
);
570 CFDictionarySetValue(certDict
, kSecCertificateDetailStatusCodes
, statusCodes
);
571 CFRelease(statusCodes
);
572 CFArrayAppendValue(details
, certDict
);
579 static CFDictionaryRef
SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust
, CFIndex ix
)
581 CFArrayRef exceptions
= NULL
;
582 OSStatus __secapiresult
= errSecSuccess
;
584 exceptions
= Trust::required(trust
)->exceptions();
586 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
587 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
588 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
589 catch (...) { __secapiresult
=errSecInternalComponent
; }
591 if (!exceptions
|| ix
>= CFArrayGetCount(exceptions
))
593 CFDictionaryRef exception
= (CFDictionaryRef
)CFArrayGetValueAtIndex(exceptions
, ix
);
594 if (CFGetTypeID(exception
) != CFDictionaryGetTypeID())
597 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, ix
);
601 /* If the exception contains the current certificate's sha1Digest in the
602 kSecCertificateDetailSHA1Digest key then we use it otherwise we ignore it. */
603 CFDataRef sha1Digest
= SecCertificateGetSHA1Digest(certificate
);
604 CFTypeRef digestValue
= CFDictionaryGetValue(exception
, kSecCertificateDetailSHA1Digest
);
605 if (!digestValue
|| !CFEqual(sha1Digest
, digestValue
))
611 static void SecTrustCheckException(const void *key
, const void *value
, void *context
)
613 struct SecTrustCheckExceptionContext
*cec
= (struct SecTrustCheckExceptionContext
*)context
;
614 if (cec
->exception
) {
615 CFTypeRef exceptionValue
= CFDictionaryGetValue(cec
->exception
, key
);
616 if (!exceptionValue
|| !CFEqual(value
, exceptionValue
)) {
617 cec
->exceptionNotFound
= true;
620 cec
->exceptionNotFound
= true;
625 CFDataRef
SecTrustCopyExceptions(SecTrustRef trust
)
627 CFArrayRef details
= SecTrustCopyDetails(trust
);
628 CFIndex pathLength
= details
? CFArrayGetCount(details
) : 0;
629 CFMutableArrayRef exceptions
= CFArrayCreateMutable(kCFAllocatorDefault
,
630 pathLength
, &kCFTypeArrayCallBacks
);
632 for (ix
= 0; ix
< pathLength
; ++ix
) {
633 CFDictionaryRef detail
= (CFDictionaryRef
)CFArrayGetValueAtIndex(details
, ix
);
634 CFIndex detailCount
= CFDictionaryGetCount(detail
);
635 CFMutableDictionaryRef exception
;
636 if (ix
== 0 || detailCount
> 0) {
637 exception
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
,
638 detailCount
+ 1, detail
);
639 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, ix
);
640 CFDataRef digest
= SecCertificateGetSHA1Digest(certificate
);
642 CFDictionaryAddValue(exception
, kSecCertificateDetailSHA1Digest
, digest
);
645 /* Add empty exception dictionaries for non leaf certs which have no exceptions
648 exception
= (CFMutableDictionaryRef
)CFDictionaryCreate(kCFAllocatorDefault
,
650 &kCFTypeDictionaryKeyCallBacks
,
651 &kCFTypeDictionaryValueCallBacks
);
653 CFArrayAppendValue(exceptions
, exception
);
654 CFReleaseNull(exception
);
656 CFReleaseSafe(details
);
658 /* Remove any trailing empty dictionaries to save even more space (we skip the leaf
659 since it will never be empty). */
660 for (ix
= pathLength
; ix
-- > 1;) {
661 CFDictionaryRef exception
= (CFDictionaryRef
)CFArrayGetValueAtIndex(exceptions
, ix
);
662 if (CFDictionaryGetCount(exception
) == 0) {
663 CFArrayRemoveValueAtIndex(exceptions
, ix
);
669 CFDataRef encodedExceptions
= CFPropertyListCreateData(kCFAllocatorDefault
,
670 exceptions
, kCFPropertyListBinaryFormat_v1_0
, 0, NULL
);
671 CFRelease(exceptions
);
673 return encodedExceptions
;
677 bool SecTrustSetExceptions(SecTrustRef trust
, CFDataRef encodedExceptions
)
679 CFArrayRef exceptions
;
680 exceptions
= (CFArrayRef
)CFPropertyListCreateWithData(kCFAllocatorDefault
,
681 encodedExceptions
, kCFPropertyListImmutable
, NULL
, NULL
);
682 if (exceptions
&& CFGetTypeID(exceptions
) != CFArrayGetTypeID()) {
683 CFRelease(exceptions
);
687 OSStatus __secapiresult
= errSecSuccess
;
689 Trust::required(trust
)->exceptions(exceptions
);
691 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
692 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
693 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
694 catch (...) { __secapiresult
=errSecInternalComponent
; }
696 /* If there is a valid exception entry for our current leaf we're golden. */
697 if (SecTrustGetExceptionForCertificateAtIndex(trust
, 0))
700 /* The passed in exceptions didn't match our current leaf, so we discard it. */
702 Trust::required(trust
)->exceptions(NULL
);
703 __secapiresult
= errSecSuccess
;
705 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
706 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
707 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
708 catch (...) { __secapiresult
=errSecInternalComponent
; }
715 SecTrustCopyResult(SecTrustRef trust
)
717 CFDictionaryRef result
= NULL
;
719 result
= Trust::required(trust
)->results();
720 // merge details into result
721 CFArrayRef details
= SecTrustCopyDetails(trust
);
723 CFDictionarySetValue((CFMutableDictionaryRef
)result
,
724 kSecTrustResultDetails
, details
);
739 SecTrustCopyProperties(SecTrustRef trust
)
741 /* can't use SECAPI macros, since this function does not return OSStatus */
742 CFArrayRef result
= NULL
;
744 result
= Trust::required(trust
)->properties();
756 /* deprecated in 10.5 */
757 OSStatus
SecTrustGetCSSMAnchorCertificates(const CSSM_DATA
**cssmAnchors
,
758 uint32
*cssmAnchorCount
)
762 Trust::gStore().getCssmRootCertificates(certs
);
763 Required(cssmAnchors
) = certs
.blobCerts();
764 Required(cssmAnchorCount
) = certs
.count();
770 // Get and set user trust settings. Deprecated in 10.5.
771 // User Trust getter, deprecated, works as it always has.
773 OSStatus
SecTrustGetUserTrust(SecCertificateRef certificate
,
774 SecPolicyRef policy
, SecTrustUserSetting
*trustSetting
)
777 StorageManager::KeychainList searchList
;
778 globals().storageManager
.getSearchList(searchList
);
779 Required(trustSetting
) = Trust::gStore().find(
780 Certificate::required(certificate
),
781 Policy::required(policy
),
787 // The public setter, also deprecated; it maps to the appropriate
788 // Trust Settings call if possible, else throws errSecUnimplemented.
790 OSStatus
SecTrustSetUserTrust(SecCertificateRef certificate
,
791 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
793 SecTrustSettingsResult tsResult
= kSecTrustSettingsResultInvalid
;
797 Policy::required(policy
);
798 switch(trustSetting
) {
799 case kSecTrustResultProceed
:
800 /* different SecTrustSettingsResult depending in root-ness */
801 ortn
= SecCertificateIsSelfSigned(certificate
, &isRoot
);
806 tsResult
= kSecTrustSettingsResultTrustRoot
;
809 tsResult
= kSecTrustSettingsResultTrustAsRoot
;
812 case kSecTrustResultDeny
:
813 tsResult
= kSecTrustSettingsResultDeny
;
816 return errSecUnimplemented
;
819 /* make a usage constraints dictionary */
820 CFRef
<CFMutableDictionaryRef
> usageDict(CFDictionaryCreateMutable(NULL
,
821 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
));
822 CFDictionaryAddValue(usageDict
, kSecTrustSettingsPolicy
, policy
);
823 if(tsResult
!= kSecTrustSettingsResultTrustRoot
) {
824 /* skip if we're specifying the default */
825 SInt32 result
= tsResult
;
826 CFNumberRef cfNum
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &result
);
827 CFDictionarySetValue(usageDict
, kSecTrustSettingsResult
, cfNum
);
830 return SecTrustSettingsSetTrustSettings(certificate
, kSecTrustSettingsDomainUser
,
835 // This one is the now-private version of what SecTrustSetUserTrust() used to
836 // be. The public API can no longer manipulate User Trust settings, only
839 OSStatus
SecTrustSetUserTrustLegacy(SecCertificateRef certificate
,
840 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
843 switch (trustSetting
) {
844 case kSecTrustResultProceed
:
845 case kSecTrustResultConfirm
:
846 case kSecTrustResultDeny
:
847 case kSecTrustResultUnspecified
:
850 MacOSError::throwMe(errSecInvalidTrustSetting
);
852 Trust::gStore().assign(
853 Certificate::required(certificate
),
854 Policy::required(policy
),
859 /* SecGetAppleTPHandle - @@@NOT EXPORTED YET; copied from SecurityInterface,
860 but could be useful in the future.
864 SecGetAppleTPHandle()
867 return TP(gGuidAppleX509TP)->handle();