2 * Copyright (c) 2002-2017 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 <libDER/oids.h>
25 #include <Security/oidscert.h>
27 #include <Security/SecTrust.h>
28 #include <Security/SecTrustPriv.h>
30 #include <Security/SecBase.h>
31 #include "SecBridge.h"
32 #include <Security/SecInternal.h>
33 #include <Security/SecTrustSettings.h>
34 #include <Security/SecTrustSettingsPriv.h>
35 #include <Security/SecTrustStatusCodes.h>
36 #include <Security/SecCertificatePriv.h>
37 #include <Security/SecPolicyPriv.h>
38 #include <security_utilities/cfutilities.h>
39 #include <security_utilities/cfmunge.h>
40 #include <CoreFoundation/CoreFoundation.h>
43 // forward declarations
44 CFArrayRef
SecTrustCopyInputCertificates(SecTrustRef trust
);
45 CFArrayRef
SecTrustCopyInputAnchors(SecTrustRef trust
);
46 CFArrayRef
SecTrustCopyConstructedChain(SecTrustRef trust
);
47 static CSSM_TP_APPLE_EVIDENCE_INFO
* SecTrustGetEvidenceInfo(SecTrustRef trust
);
49 typedef struct SecTrustCheckExceptionContext
{
50 CFDictionaryRef exception
;
51 bool exceptionNotFound
;
52 } SecTrustCheckExceptionContext
;
55 // Sec* API bridge functions
57 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
58 OSStatus
SecTrustSetParameters(
60 CSSM_TP_ACTION action
,
63 /* bridge to support API functionality for legacy callers */
65 CSSM_APPLE_TP_ACTION_FLAGS actionFlags
= 0;
67 CSSM_APPLE_TP_ACTION_DATA
*actionDataPtr
= (CSSM_APPLE_TP_ACTION_DATA
*) CFDataGetBytePtr(actionData
);
69 actionFlags
= actionDataPtr
->ActionFlags
;
72 // note that SecTrustOptionFlags == CSSM_APPLE_TP_ACTION_FLAGS;
73 // both are sizeof(uint32) and the flag values have identical meanings
74 status
= SecTrustSetOptions(trustRef
, (SecTrustOptionFlags
)actionFlags
);
76 #if SECTRUST_DEPRECATION_WARNINGS
77 syslog(LOG_ERR
, "WARNING: SecTrustSetParameters was deprecated in 10.7. Use SecTrustSetOptions instead.");
83 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
84 OSStatus
SecTrustSetKeychains(SecTrustRef trust
, CFTypeRef keychainOrArray
)
86 /* this function is currently unsupported in unified SecTrust */
87 // TODO: pull all certs out of the specified keychains for the evaluation?
88 #if SECTRUST_DEPRECATION_WARNINGS
89 syslog(LOG_ERR
, "WARNING: SecTrustSetKeychains does nothing in 10.11. Use SecTrustSetAnchorCertificates{Only} to provide anchors.");
95 // Construct the "official" result evidence and return it
97 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
98 OSStatus
SecTrustGetResult(
100 SecTrustResultType
*result
,
101 CFArrayRef
*certChain
, CSSM_TP_APPLE_EVIDENCE_INFO
**statusChain
)
103 /* bridge to support old functionality */
104 #if SECTRUST_DEPRECATION_WARNINGS
105 syslog(LOG_ERR
, "WARNING: SecTrustGetResult has been deprecated since 10.7. Please use SecTrustGetTrustResult instead.");
107 SecTrustResultType trustResult
;
108 OSStatus status
= SecTrustGetTrustResult(trustRef
, &trustResult
);
109 if (status
!= errSecSuccess
) {
113 *result
= trustResult
;
116 *certChain
= SecTrustCopyConstructedChain(trustRef
);
119 *statusChain
= SecTrustGetEvidenceInfo(trustRef
);
125 // Retrieve extended validation trust results
127 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
128 OSStatus
SecTrustCopyExtendedResult(SecTrustRef trust
, CFDictionaryRef
*result
)
130 /* bridge to support old functionality */
131 #if SECTRUST_DEPRECATION_WARNINGS
132 syslog(LOG_ERR
, "WARNING: SecTrustCopyExtendedResult will be deprecated in an upcoming release. Please use SecTrustCopyResult instead.");
134 CFDictionaryRef resultDict
= SecTrustCopyResult(trust
);
136 CFReleaseNull(resultDict
);
139 *result
= resultDict
;
140 return errSecSuccess
;
144 // Retrieve CSSM-level information for those who want to dig down
146 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
147 OSStatus
SecTrustGetCssmResult(SecTrustRef trust
, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR
*result
)
149 /* this function is unsupported in unified SecTrust */
150 #if SECTRUST_DEPRECATION_WARNINGS
151 syslog(LOG_ERR
, "WARNING: SecTrustGetCssmResult has been deprecated since 10.7, and has no functional equivalent in 10.11. Please use SecTrustCopyResult instead.");
156 return errSecServiceNotAvailable
;
159 static uint8_t convertCssmResultToPriority(CSSM_RETURN resultCode
) {
160 switch (resultCode
) {
161 /* explicitly not trusted */
162 case CSSMERR_TP_CERT_REVOKED
:
163 case CSSMERR_APPLETP_TRUST_SETTING_DENY
:
165 /* failure to comply with X.509 */
166 case CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS
:
167 case CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT
:
168 case CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT
:
169 case CSSMERR_APPLETP_INVALID_AUTHORITY_ID
:
170 case CSSMERR_TP_INVALID_CERTIFICATE
:
171 case CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN
:
173 case CSSMERR_TP_CERT_EXPIRED
:
175 /* doesn't chain to trusted root */
176 case CSSMERR_TP_NOT_TRUSTED
:
177 case CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH
:
179 /* all others are policy-specific failures */
186 // Retrieve CSSM_LEVEL TP return code
188 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
189 OSStatus
SecTrustGetCssmResultCode(SecTrustRef trustRef
, OSStatus
*result
)
191 /* bridge to support old functionality */
192 #if SECTRUST_DEPRECATION_WARNINGS
193 syslog(LOG_ERR
, "WARNING: SecTrustGetCssmResultCode has been deprecated since 10.7, and will be removed in a future release. Please use SecTrustCopyProperties instead.");
195 if (!trustRef
|| !result
) {
199 SecTrustResultType trustResult
= kSecTrustResultInvalid
;
200 (void) SecTrustGetTrustResult(trustRef
, &trustResult
);
201 if (trustResult
== kSecTrustResultProceed
|| trustResult
== kSecTrustResultUnspecified
) {
202 if (result
) { *result
= 0; }
203 return errSecSuccess
;
206 OSStatus cssmResultCode
= errSecSuccess
;
207 uint8_t resultCodePriority
= 0xFF;
208 CFIndex ix
, count
= SecTrustGetCertificateCount(trustRef
);
209 for (ix
= 0; ix
< count
; ix
++) {
210 CFIndex numStatusCodes
;
211 CSSM_RETURN
*statusCodes
= NULL
;
212 statusCodes
= (CSSM_RETURN
*)SecTrustCopyStatusCodes(trustRef
, ix
, &numStatusCodes
);
213 if (statusCodes
&& numStatusCodes
> 0) {
214 unsigned int statusIX
;
215 for (statusIX
= 0; statusIX
< numStatusCodes
; statusIX
++) {
216 CSSM_RETURN currStatus
= statusCodes
[statusIX
];
217 uint8_t currPriority
= convertCssmResultToPriority(currStatus
);
218 if (resultCodePriority
> currPriority
) {
219 cssmResultCode
= currStatus
;
220 resultCodePriority
= currPriority
;
224 if (statusCodes
) { free(statusCodes
); }
225 if (resultCodePriority
== 1) { break; }
229 *result
= cssmResultCode
;
231 return errSecSuccess
;
234 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
235 OSStatus
SecTrustGetTPHandle(SecTrustRef trust
, CSSM_TP_HANDLE
*handle
)
237 /* this function is unsupported in unified SecTrust */
238 #if SECTRUST_DEPRECATION_WARNINGS
239 syslog(LOG_ERR
, "WARNING: SecTrustGetTPHandle has been deprecated since 10.7, and cannot return CSSM objects in 10.11. Please stop using it.");
244 return errSecServiceNotAvailable
;
248 // Get the user's default anchor certificate set
251 OSStatus
SecTrustCopyAnchorCertificates(CFArrayRef
*anchorCertificates
)
255 OSStatus status
= SecTrustSettingsCopyUnrestrictedRoots(
256 true, true, true, /* all domains */
258 if (status
!= errSecSuccess
) {
261 CFIndex count
= outArray
? CFArrayGetCount(outArray
) : 0;
263 return errSecNoTrustSettings
;
266 /* Go through outArray and do a SecTrustEvaluate */
268 SecPolicyRef policy
= SecPolicyCreateBasicX509();
269 SecTrustRef trust
= NULL
;
270 CFMutableArrayRef trustedCertArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
271 for (i
= 0; i
< count
; i
++) {
272 SecTrustResultType result
;
273 SecCertificateRef certificate
= (SecCertificateRef
) CFArrayGetValueAtIndex(outArray
, i
);
274 status
= SecTrustCreateWithCertificates(certificate
, policy
, &trust
);
275 if (status
!= errSecSuccess
) {
276 CFReleaseSafe(trustedCertArray
);
279 status
= SecTrustEvaluate(trust
, &result
);
280 if (status
!= errSecSuccess
) {
281 CFReleaseSafe(trustedCertArray
);
284 if (result
!= kSecTrustResultFatalTrustFailure
) {
285 CFArrayAppendValue(trustedCertArray
, certificate
);
287 CFReleaseNull(trust
);
289 if (CFArrayGetCount(trustedCertArray
) == 0) {
290 status
= errSecNoTrustSettings
;
291 CFReleaseSafe(trustedCertArray
);
294 *anchorCertificates
= trustedCertArray
;
296 CFReleaseSafe(outArray
);
297 CFReleaseSafe(policy
);
298 CFReleaseSafe(trust
);
304 * We have an iOS-style SecTrustRef, but we need to return a CDSA-based SecKeyRef.
306 * If you need a SecKeyRef based of the iOS based SecKey, check certificate chain
307 * length, get certificate with SecTrustGetCertificateAtIndex(0), use
308 * SecCertificateCopyKey() to get a iOS based key.
310 SecKeyRef
SecTrustCopyPublicKey(SecTrustRef trust
)
312 SecKeyRef pubKey
= NULL
;
313 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, 0);
314 #pragma clang diagnostic push
315 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
316 (void) SecCertificateCopyPublicKey(certificate
, &pubKey
);
317 #pragma clang diagnostic pop
321 // cannot link against the new iOS SecTrust from this implementation,
322 // so there are no possible accessors for the fields of this struct
323 typedef struct __TSecTrust
{
325 CFArrayRef _certificates
;
328 CFArrayRef _responses
;
330 CFArrayRef _trustedLogs
;
331 CFDateRef _verifyDate
;
333 SecKeyRef _publicKey
;
335 CFDictionaryRef _info
;
336 CFArrayRef _exceptions
;
337 SecTrustResultType _trustResult
;
339 bool _keychainsAllowed
;
340 void* _legacy_info_array
;
341 void* _legacy_status_array
;
342 dispatch_queue_t _trustQueue
;
345 CFArrayRef
SecTrustCopyInputCertificates(SecTrustRef trust
)
347 if (!trust
) { return NULL
; };
348 TSecTrust
*secTrust
= (TSecTrust
*)trust
;
349 if (secTrust
->_certificates
) {
350 CFRetain(secTrust
->_certificates
);
352 return secTrust
->_certificates
;
355 CFArrayRef
SecTrustCopyInputAnchors(SecTrustRef trust
)
357 if (!trust
) { return NULL
; };
358 TSecTrust
*secTrust
= (TSecTrust
*)trust
;
359 if (secTrust
->_anchors
) {
360 CFRetain(secTrust
->_anchors
);
362 return secTrust
->_anchors
;
365 // Return the constructed certificate chain for this trust reference,
366 // making output certificates pointer-equivalent to any provided input
367 // certificates (where possible) for legacy behavioral compatibility.
368 // Caller must release this array.
370 CFArrayRef
SecTrustCopyConstructedChain(SecTrustRef trust
)
372 CFMutableArrayRef certChain
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
373 CFIndex idx
, count
= SecTrustGetCertificateCount(trust
);
374 for (idx
=0; idx
< count
; idx
++) {
375 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, idx
);
377 CFArrayAppendValue(certChain
, certificate
);
381 // Some callers make the assumption that the certificates in
382 // this chain are pointer-equivalent to ones they passed to the
383 // SecTrustCreateWithCertificates function. We'll maintain that
384 // behavior here for compatibility.
386 CFArrayRef inputCertArray
= SecTrustCopyInputCertificates(trust
);
387 CFArrayRef inputAnchorArray
= SecTrustCopyInputAnchors(trust
);
388 CFIndex inputCertIdx
, inputCertCount
= (inputCertArray
) ? CFArrayGetCount(inputCertArray
) : 0;
389 CFIndex inputAnchorIdx
, inputAnchorCount
= (inputAnchorArray
) ? CFArrayGetCount(inputAnchorArray
) : 0;
390 for (idx
=0; idx
< count
; idx
++) {
391 SecCertificateRef tmpCert
= (SecCertificateRef
) CFArrayGetValueAtIndex(certChain
, idx
);
393 SecCertificateRef matchCert
= NULL
;
394 for (inputCertIdx
=0; inputCertIdx
< inputCertCount
&& !matchCert
; inputCertIdx
++) {
395 SecCertificateRef inputCert
= (SecCertificateRef
) CFArrayGetValueAtIndex(inputCertArray
, inputCertIdx
);
396 if (inputCert
&& CFEqual(inputCert
, tmpCert
)) {
397 matchCert
= inputCert
;
400 for (inputAnchorIdx
=0; inputAnchorIdx
< inputAnchorCount
&& !matchCert
; inputAnchorIdx
++) {
401 SecCertificateRef inputAnchor
= (SecCertificateRef
) CFArrayGetValueAtIndex(inputAnchorArray
, inputAnchorIdx
);
402 if (inputAnchor
&& CFEqual(inputAnchor
, tmpCert
)) {
403 matchCert
= inputAnchor
;
407 CFArraySetValueAtIndex(certChain
, idx
, matchCert
);
411 if (inputCertArray
) {
412 CFRelease(inputCertArray
);
414 if (inputAnchorArray
) {
415 CFRelease(inputAnchorArray
);
421 // Here is where backward compatibility gets ugly. CSSM_TP_APPLE_EVIDENCE_INFO does not exist
422 // in the unified SecTrust world. Unfortunately, some clients are still calling legacy APIs
423 // (e.g. SecTrustGetResult) and grubbing through the info for StatusBits and StatusCodes.
424 // SecTrustGetEvidenceInfo builds the legacy evidence info structure as needed, and returns
425 // a pointer to it. The evidence data is allocated here and set in the _legacy_* fields
426 // of the TSecTrust; the trust object subsequently owns it. The returned pointer is expected
427 // to be valid for the lifetime of the SecTrustRef, or until the trust parameters are changed,
428 // which would force re-evaluation.
430 static CSSM_TP_APPLE_EVIDENCE_INFO
*
431 SecTrustGetEvidenceInfo(SecTrustRef trust
)
433 TSecTrust
*secTrust
= (TSecTrust
*)trust
;
437 if (secTrust
->_trustResult
!= kSecTrustResultInvalid
&&
438 secTrust
->_legacy_info_array
) {
439 // we've already got valid evidence info, return it now.
440 return (CSSM_TP_APPLE_EVIDENCE_INFO
*)secTrust
->_legacy_info_array
;
443 // Getting the count implicitly evaluates the chain if necessary.
444 CFIndex idx
, count
= SecTrustGetCertificateCount(trust
);
445 CFArrayRef inputCertArray
= SecTrustCopyInputCertificates(trust
);
446 CFArrayRef inputAnchorArray
= SecTrustCopyInputAnchors(trust
);
447 CFIndex inputCertIdx
, inputCertCount
= (inputCertArray
) ? CFArrayGetCount(inputCertArray
) : 0;
448 CFIndex inputAnchorIdx
, inputAnchorCount
= (inputAnchorArray
) ? CFArrayGetCount(inputAnchorArray
) : 0;
450 CSSM_TP_APPLE_EVIDENCE_INFO
*infoArray
= (CSSM_TP_APPLE_EVIDENCE_INFO
*)calloc(count
, sizeof(CSSM_TP_APPLE_EVIDENCE_INFO
));
451 CSSM_RETURN
*statusArray
= NULL
;
452 CFIndex numStatusCodes
= 0;
454 // Set status codes for each certificate in the constructed chain
455 for (idx
=0; idx
< count
; idx
++) {
456 SecCertificateRef cert
= SecTrustGetCertificateAtIndex(trust
, idx
);
460 CSSM_TP_APPLE_EVIDENCE_INFO
*evInfo
= &infoArray
[idx
];
462 /* first the booleans (StatusBits flags) */
463 CFAbsoluteTime now
= CFAbsoluteTimeGetCurrent();
464 if (secTrust
->_verifyDate
) {
465 now
= CFDateGetAbsoluteTime(secTrust
->_verifyDate
);
467 CFAbsoluteTime na
= SecCertificateNotValidAfter(cert
);
469 evInfo
->StatusBits
|= CSSM_CERT_STATUS_EXPIRED
;
471 CFAbsoluteTime nb
= SecCertificateNotValidBefore(cert
);
473 evInfo
->StatusBits
|= CSSM_CERT_STATUS_NOT_VALID_YET
;
475 for (inputAnchorIdx
=0; inputAnchorIdx
< inputAnchorCount
; inputAnchorIdx
++) {
476 SecCertificateRef inputAnchor
= (SecCertificateRef
) CFArrayGetValueAtIndex(inputAnchorArray
, inputAnchorIdx
);
477 if (inputAnchor
&& CFEqual(inputAnchor
, cert
)) {
478 evInfo
->StatusBits
|= CSSM_CERT_STATUS_IS_IN_ANCHORS
;
482 for (inputCertIdx
=0; inputCertIdx
< inputCertCount
; inputCertIdx
++) {
483 SecCertificateRef inputCert
= (SecCertificateRef
) CFArrayGetValueAtIndex(inputCertArray
, inputCertIdx
);
484 if (inputCert
&& CFEqual(inputCert
, cert
)) {
485 evInfo
->StatusBits
|= CSSM_CERT_STATUS_IS_IN_INPUT_CERTS
;
490 /* See if there are trust settings for this certificate. */
491 CFStringRef hashStr
= SecTrustSettingsCertHashStrFromCert(cert
);
492 bool foundMatch
= false;
493 bool foundAny
= false;
494 CSSM_RETURN
*errors
= NULL
;
495 uint32 errorCount
= 0;
497 SecTrustSettingsDomain foundDomain
= kSecTrustSettingsDomainUser
;
498 SecTrustSettingsResult foundResult
= kSecTrustSettingsResultInvalid
;
499 bool isSelfSigned
= false;
500 if ((count
- 1) == idx
) {
501 // Only the last cert in the chain needs to be considered
503 status
= SecCertificateIsSelfSigned(cert
, &selfSigned
);
504 isSelfSigned
= (status
) ? false : ((selfSigned
) ? true : false);
506 evInfo
->StatusBits
|= CSSM_CERT_STATUS_IS_ROOT
;
509 // STU: rdar://25554967
510 // %%% need to get policyOID, policyString, and keyUsage here!
512 status
= SecTrustSettingsEvaluateCert(
513 hashStr
, /* certHashStr */
514 NULL
, /* policyOID (optional) */
515 NULL
, /* policyString (optional) */
516 0, /* policyStringLen */
518 isSelfSigned
, /* isRootCert */
519 &foundDomain
, /* foundDomain */
520 &errors
, /* allowedErrors -- MUST FREE */
521 &errorCount
, /* numAllowedErrors */
522 &foundResult
, /* resultType */
523 &foundMatch
, /* foundMatchingEntry */
524 &foundAny
); /* foundAnyEntry */
526 if (status
== errSecSuccess
) {
528 switch (foundResult
) {
529 case kSecTrustSettingsResultTrustRoot
:
530 case kSecTrustSettingsResultTrustAsRoot
:
531 /* these two can be disambiguated by IS_ROOT */
532 evInfo
->StatusBits
|= CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST
;
534 case kSecTrustSettingsResultDeny
:
535 evInfo
->StatusBits
|= CSSM_CERT_STATUS_TRUST_SETTINGS_DENY
;
537 case kSecTrustSettingsResultUnspecified
:
538 case kSecTrustSettingsResultInvalid
:
552 CSSM_RETURN
*statusCodes
= (CSSM_RETURN
*)SecTrustCopyStatusCodes(trust
, idx
, &numCodes
);
554 // Realloc space for these status codes at end of our status codes block.
555 // Two important things to note:
556 // 1. the actual length is numCodes+1 because SecTrustCopyStatusCodes
557 // allocates one more element at the end for the CrlReason value.
558 // 2. realloc may cause the pointer to move, which means we will
559 // need to fix up the StatusCodes fields after we're done with this loop.
560 CFIndex totalStatusCodes
= numStatusCodes
+ numCodes
+ 1;
561 statusArray
= (CSSM_RETURN
*)realloc(statusArray
, totalStatusCodes
* sizeof(CSSM_RETURN
));
562 evInfo
->StatusCodes
= &statusArray
[numStatusCodes
];
563 evInfo
->NumStatusCodes
= (uint32
)numCodes
;
564 // Copy the new codes (plus one) into place
565 for (unsigned int cpix
= 0; cpix
<= numCodes
; cpix
++) {
566 evInfo
->StatusCodes
[cpix
] = statusCodes
[cpix
];
568 numStatusCodes
= totalStatusCodes
;
572 if(evInfo
->StatusBits
& (CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST
|
573 CSSM_CERT_STATUS_TRUST_SETTINGS_DENY
|
574 CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR
)) {
575 /* Something noteworthy happened involving TrustSettings */
576 uint32 whichDomain
= 0;
577 switch(foundDomain
) {
578 case kSecTrustSettingsDomainUser
:
579 whichDomain
= CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER
;
581 case kSecTrustSettingsDomainAdmin
:
582 whichDomain
= CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN
;
584 case kSecTrustSettingsDomainSystem
:
585 whichDomain
= CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM
;
588 evInfo
->StatusBits
|= whichDomain
;
591 /* index into raw cert group or AnchorCerts depending on IS_IN_ANCHORS */
592 //evInfo->Index = certInfo->index();
593 /* nonzero if cert came from a DLDB */
594 //evInfo->DlDbHandle = certInfo->dlDbHandle();
595 //evInfo->UniqueRecord = certInfo->uniqueRecord();
598 // Now that all the status codes have been allocated in a contiguous block,
599 // refresh the StatusCodes pointer in each array element.
601 for (idx
=0; idx
< count
; idx
++) {
602 CSSM_TP_APPLE_EVIDENCE_INFO
*evInfo
= &infoArray
[idx
];
603 evInfo
->StatusCodes
= &statusArray
[numStatusCodes
];
604 numStatusCodes
+= evInfo
->NumStatusCodes
+ 1;
607 secTrust
->_legacy_info_array
= infoArray
;
608 secTrust
->_legacy_status_array
= statusArray
;
610 if (inputCertArray
) {
611 CFRelease(inputCertArray
);
613 if (inputAnchorArray
) {
614 CFRelease(inputAnchorArray
);
617 return (CSSM_TP_APPLE_EVIDENCE_INFO
*)secTrust
->_legacy_info_array
;
620 CFArrayRef
SecTrustCopyProperties(SecTrustRef trust
) {
621 /* OS X creates a completely different structure with one dictionary for each certificate */
622 CFIndex ix
, count
= SecTrustGetCertificateCount(trust
);
624 CFMutableArrayRef properties
= CFArrayCreateMutable(kCFAllocatorDefault
, count
,
625 &kCFTypeArrayCallBacks
);
627 for (ix
= 0; ix
< count
; ix
++) {
628 CFMutableDictionaryRef certDict
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
,
629 &kCFTypeDictionaryValueCallBacks
);
630 /* Populate the certificate title */
631 SecCertificateRef cert
= SecTrustGetCertificateAtIndex(trust
, ix
);
633 CFStringRef subjectSummary
= SecCertificateCopySubjectSummary(cert
);
634 if (subjectSummary
) {
635 CFDictionaryAddValue(certDict
, kSecPropertyTypeTitle
, subjectSummary
);
636 CFRelease(subjectSummary
);
640 /* Populate a revocation reason if the cert was revoked */
641 CFIndex numStatusCodes
;
642 CSSM_RETURN
*statusCodes
= NULL
;
643 statusCodes
= (CSSM_RETURN
*)SecTrustCopyStatusCodes(trust
, ix
, &numStatusCodes
);
645 SInt32 reason
= statusCodes
[numStatusCodes
]; // stored at end of status codes array
647 CFNumberRef cfreason
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &reason
);
649 CFDictionarySetValue(certDict
, kSecTrustRevocationReason
, cfreason
);
656 /* Populate the error in the leaf dictionary */
658 OSStatus error
= errSecSuccess
;
659 (void)SecTrustGetCssmResultCode(trust
, &error
);
660 CFStringRef errorStr
= SecCopyErrorMessageString(error
, NULL
);
662 CFDictionarySetValue(certDict
, kSecPropertyTypeError
, errorStr
);
667 CFArrayAppendValue(properties
, certDict
);
674 /* deprecated in 10.5 */
675 OSStatus
SecTrustGetCSSMAnchorCertificates(const CSSM_DATA
**cssmAnchors
,
676 uint32
*cssmAnchorCount
)
678 /* this function is unsupported in unified SecTrust */
679 #if SECTRUST_DEPRECATION_WARNINGS
680 syslog(LOG_ERR
, "WARNING: SecTrustGetCSSMAnchorCertificates has been deprecated since 10.5, and cannot return CSSM objects in 10.11. Please stop using it.");
685 if (cssmAnchorCount
) {
686 *cssmAnchorCount
= 0;
688 return errSecServiceNotAvailable
;
693 // Get and set user trust settings. Deprecated in 10.5.
694 // User Trust getter, deprecated, works as it always has.
696 OSStatus
SecTrustGetUserTrust(SecCertificateRef certificate
,
697 SecPolicyRef policy
, SecTrustUserSetting
*trustSetting
)
699 /* this function is unsupported in unified SecTrust */
700 #if SECTRUST_DEPRECATION_WARNINGS
701 syslog(LOG_ERR
, "WARNING: SecTrustGetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
703 return errSecServiceNotAvailable
;
707 // The public setter, also deprecated; it maps to the appropriate
708 // Trust Settings call if possible, else throws errSecUnimplemented.
710 OSStatus
SecTrustSetUserTrust(SecCertificateRef certificate
,
711 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
713 /* this function is unsupported in unified SecTrust */
714 #if SECTRUST_DEPRECATION_WARNINGS
715 syslog(LOG_ERR
, "WARNING: SecTrustSetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
717 return errSecServiceNotAvailable
;
721 // This one is the now-private version of what SecTrustSetUserTrust() used to
722 // be. The public API can no longer manipulate User Trust settings, only
725 OSStatus
SecTrustSetUserTrustLegacy(SecCertificateRef certificate
,
726 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
728 /* this function is unsupported in unified SecTrust */
729 #if SECTRUST_DEPRECATION_WARNINGS
730 syslog(LOG_ERR
, "WARNING: SecTrustSetUserTrustLegacy does nothing in 10.11. Please stop using it.");
732 return errSecServiceNotAvailable
;