2 * Copyright (c) 2002-2016 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"
28 #include "SecBridge.h"
29 #include "SecInternal.h"
30 #include "SecTrustSettings.h"
31 #include "SecTrustSettingsPriv.h"
32 #include "SecCertificatePriv.h"
33 #include "SecCertificateP.h"
34 #include "SecCertificatePrivP.h"
35 #include "SecPolicyPriv.h"
36 #include <security_utilities/cfutilities.h>
37 #include <security_utilities/cfmunge.h>
38 #include <CoreFoundation/CoreFoundation.h>
41 // forward declarations
42 CFArrayRef
SecTrustCopyInputCertificates(SecTrustRef trust
);
43 CFArrayRef
SecTrustCopyInputAnchors(SecTrustRef trust
);
44 CFArrayRef
SecTrustCopyConstructedChain(SecTrustRef trust
);
45 static CSSM_TP_APPLE_EVIDENCE_INFO
* SecTrustGetEvidenceInfo(SecTrustRef trust
);
47 typedef struct SecTrustCheckExceptionContext
{
48 CFDictionaryRef exception
;
49 bool exceptionNotFound
;
50 } SecTrustCheckExceptionContext
;
52 // public trust result constants
53 const CFStringRef kSecTrustEvaluationDate
= CFSTR("TrustEvaluationDate");
54 const CFStringRef kSecTrustExtendedValidation
= CFSTR("TrustExtendedValidation");
55 const CFStringRef kSecTrustOrganizationName
= CFSTR("Organization");
56 const CFStringRef kSecTrustResultValue
= CFSTR("TrustResultValue");
57 const CFStringRef kSecTrustRevocationChecked
= CFSTR("TrustRevocationChecked");
58 const CFStringRef kSecTrustRevocationReason
= CFSTR("TrustRevocationReason");
59 const CFStringRef kSecTrustRevocationValidUntilDate
= CFSTR("TrustExpirationDate");
60 const CFStringRef kSecTrustResultDetails
= CFSTR("TrustResultDetails");
62 // Policy check string to CSSM_RETURN mapping
64 struct resultmap_entry_s
{
65 const CFStringRef checkstr
;
66 const CSSM_RETURN resultcode
;
68 typedef struct resultmap_entry_s resultmap_entry_t
;
70 const resultmap_entry_t cssmresultmap
[] = {
71 { CFSTR("SSLHostname"), CSSMERR_APPLETP_HOSTNAME_MISMATCH
},
72 { CFSTR("email"), CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND
},
73 { CFSTR("IssuerCommonName"), CSSMERR_APPLETP_IDENTIFIER_MISSING
},
74 { CFSTR("SubjectCommonName"), CSSMERR_APPLETP_IDENTIFIER_MISSING
},
75 { CFSTR("SubjectCommonNamePrefix"), CSSMERR_APPLETP_IDENTIFIER_MISSING
},
76 { CFSTR("SubjectCommonNameTEST"), CSSMERR_APPLETP_IDENTIFIER_MISSING
},
77 { CFSTR("SubjectOrganization"), CSSMERR_APPLETP_IDENTIFIER_MISSING
},
78 { CFSTR("SubjectOrganizationalUnit"), CSSMERR_APPLETP_IDENTIFIER_MISSING
},
79 { CFSTR("EAPTrustedServerNames"), CSSMERR_APPLETP_HOSTNAME_MISMATCH
},
80 { CFSTR("CertificatePolicy"), CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION
},
81 { CFSTR("KeyUsage"), CSSMERR_APPLETP_INVALID_KEY_USAGE
},
82 { CFSTR("ExtendedKeyUsage"), CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE
},
83 { CFSTR("BasicConstraints"), CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS
},
84 { CFSTR("QualifiedCertStatements"), CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT
},
85 { CFSTR("IntermediateSPKISHA256"), CSSMERR_APPLETP_IDENTIFIER_MISSING
},
86 { CFSTR("IntermediateEKU"), CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE
},
87 { CFSTR("AnchorSHA1"), CSSMERR_TP_NOT_TRUSTED
},
88 { CFSTR("AnchorSHA256"), CSSMERR_TP_NOT_TRUSTED
},
89 { CFSTR("AnchorTrusted"), CSSMERR_TP_NOT_TRUSTED
},
90 { CFSTR("AnchorApple"), CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH
},
91 { CFSTR("NonEmptySubject"), CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT
},
92 { CFSTR("IdLinkage"), CSSMERR_APPLETP_INVALID_AUTHORITY_ID
},
93 { CFSTR("WeakIntermediates"), CSSMERR_TP_INVALID_CERTIFICATE
},
94 { CFSTR("WeakLeaf"), CSSMERR_TP_INVALID_CERTIFICATE
},
95 { CFSTR("WeakRoot"), CSSMERR_TP_INVALID_CERTIFICATE
},
96 { CFSTR("KeySize"), CSSMERR_CSP_UNSUPPORTED_KEY_SIZE
},
97 { CFSTR("SignatureHashAlgorithms"), CSSMERR_CSP_ALGID_MISMATCH
},
98 { CFSTR("SystemTrustedWeakHash"), CSSMERR_CSP_INVALID_DIGEST_ALGORITHM
},
99 { CFSTR("CriticalExtensions"), CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN
},
100 { CFSTR("ChainLength"), CSSMERR_APPLETP_PATH_LEN_CONSTRAINT
},
101 { CFSTR("BasicCertificateProcessing"), CSSMERR_TP_INVALID_CERTIFICATE
},
102 { CFSTR("ExtendedValidation"), CSSMERR_TP_NOT_TRUSTED
},
103 { CFSTR("Revocation"), CSSMERR_TP_CERT_REVOKED
},
104 { CFSTR("RevocationResponseRequired"), CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK
},
105 { CFSTR("CertificateTransparency"), CSSMERR_TP_NOT_TRUSTED
},
106 { CFSTR("BlackListedLeaf"), CSSMERR_TP_CERT_REVOKED
},
107 { CFSTR("GrayListedLeaf"), CSSMERR_TP_NOT_TRUSTED
},
108 { CFSTR("GrayListedKey"), CSSMERR_TP_NOT_TRUSTED
},
109 { CFSTR("BlackListedKey"), CSSMERR_TP_CERT_REVOKED
},
110 { CFSTR("CheckLeafMarkerOid"), CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION
},
111 { CFSTR("CheckLeafMarkerOidNoValueCheck"), CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION
},
112 { CFSTR("CheckIntermediateMarkerOid"), CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION
},
113 { CFSTR("UsageConstraints"), CSSMERR_APPLETP_TRUST_SETTING_DENY
},
114 { CFSTR("NotValidBefore"), CSSMERR_TP_CERT_NOT_VALID_YET
},
115 { CFSTR("ValidIntermediates"), CSSMERR_TP_CERT_EXPIRED
},
116 { CFSTR("ValidLeaf"), CSSMERR_TP_CERT_EXPIRED
},
117 { CFSTR("ValidRoot"), CSSMERR_TP_CERT_EXPIRED
},
118 // { CFSTR("AnchorAppleTestRoots"), },
119 // { CFSTR("AnchorAppleTestRootsOnProduction"), },
120 // { CFSTR("NoNetworkAccess"), },
125 // Sec* API bridge functions
128 SecTrustOptionFlags flags
;
130 SecTrustRef trustRef
;
131 CFMutableDictionaryRef filteredException
;
132 CFDictionaryRef oldException
;
133 } SecExceptionFilterContext
;
135 // inline function from SecCFWrappers.h
136 static inline char *CFStringToCString(CFStringRef inStr
)
139 return (char *)strdup("");
140 CFRetain(inStr
); // compensate for release on exit
142 // need to extract into buffer
143 CFIndex length
= CFStringGetLength(inStr
); // in 16-bit character units
144 size_t len
= CFStringGetMaximumSizeForEncoding(length
, kCFStringEncodingUTF8
);
145 char *buffer
= (char *)malloc(len
); // pessimistic
146 if (!CFStringGetCString(inStr
, buffer
, len
, kCFStringEncodingUTF8
))
154 filter_exception(const void *key
, const void *value
, void *context
)
156 SecExceptionFilterContext
*ctx
= (SecExceptionFilterContext
*)context
;
157 if (!ctx
) { return; }
159 SecTrustOptionFlags options
= ctx
->flags
;
160 CFMutableDictionaryRef filteredException
= ctx
->filteredException
;
161 CFStringRef keystr
= (CFStringRef
)key
;
163 if (ctx
->oldException
&& CFDictionaryContainsKey(ctx
->oldException
, key
)) {
164 // Keep existing exception in filtered dictionary, regardless of options
165 CFDictionaryAddValue(filteredException
, key
, CFDictionaryGetValue(ctx
->oldException
, key
));
169 bool allowed
= false;
171 if (CFEqual(keystr
, CFSTR("SHA1Digest"))) {
172 allowed
= true; // this key is informational and always permitted
174 else if (CFEqual(keystr
, CFSTR("NotValidBefore"))) {
175 allowed
= ((options
& kSecTrustOptionAllowExpired
) != 0);
177 else if (CFEqual(keystr
, CFSTR("ValidLeaf"))) {
178 allowed
= ((options
& kSecTrustOptionAllowExpired
) != 0);
180 else if (CFEqual(keystr
, CFSTR("ValidIntermediates"))) {
181 allowed
= ((options
& kSecTrustOptionAllowExpired
) != 0);
183 else if (CFEqual(keystr
, CFSTR("ValidRoot"))) {
184 if (((options
& kSecTrustOptionAllowExpired
) != 0) ||
185 ((options
& kSecTrustOptionAllowExpiredRoot
) != 0)) {
189 else if (CFEqual(keystr
, CFSTR("AnchorTrusted"))) {
190 bool implicitAnchors
= ((options
& kSecTrustOptionImplicitAnchors
) != 0);
191 // Implicit anchors option only filters exceptions for self-signed certs
192 if (implicitAnchors
&& ctx
->trustRef
&&
193 (ctx
->certIX
< SecTrustGetCertificateCount(ctx
->trustRef
))) {
194 Boolean isSelfSigned
= false;
195 SecCertificateRef cert
= SecTrustGetCertificateAtIndex(ctx
->trustRef
, ctx
->certIX
);
196 if (cert
&& (errSecSuccess
== SecCertificateIsSelfSigned(cert
, &isSelfSigned
)) &&
202 else if (CFEqual(keystr
, CFSTR("KeyUsage")) ||
203 CFEqual(keystr
, CFSTR("ExtendedKeyUsage")) ||
204 CFEqual(keystr
, CFSTR("BasicConstraints")) ||
205 CFEqual(keystr
, CFSTR("NonEmptySubject")) ||
206 CFEqual(keystr
, CFSTR("IdLinkage"))) {
207 // Cannot override these exceptions
211 // Unhandled exceptions should not be overridden,
212 // but we want to know which ones we're missing
213 char *cstr
= CFStringToCString(keystr
);
214 syslog(LOG_ERR
, "Unfiltered exception: %s", (cstr
) ? cstr
: "<NULL>");
215 if (cstr
) { free(cstr
); }
220 CFDictionaryAddValue(filteredException
, key
, value
);
224 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
226 SecTrustSetOptions(SecTrustRef trustRef
, SecTrustOptionFlags options
)
228 /* bridge to support API functionality for legacy callers */
229 OSStatus status
= errSecSuccess
;
230 CFDataRef encodedExceptions
= SecTrustCopyExceptions(trustRef
);
231 CFArrayRef exceptions
= NULL
,
232 oldExceptions
= SecTrustGetTrustExceptionsArray(trustRef
);
234 if (encodedExceptions
) {
235 exceptions
= (CFArrayRef
)CFPropertyListCreateWithData(kCFAllocatorDefault
,
236 encodedExceptions
, kCFPropertyListImmutable
, NULL
, NULL
);
237 CFRelease(encodedExceptions
);
238 encodedExceptions
= NULL
;
241 if (exceptions
&& CFGetTypeID(exceptions
) != CFArrayGetTypeID()) {
242 CFRelease(exceptions
);
246 if (oldExceptions
&& exceptions
&&
247 CFArrayGetCount(oldExceptions
) > CFArrayGetCount(exceptions
)) {
248 oldExceptions
= NULL
;
251 /* verify both exceptions are for the same leaf */
252 if (oldExceptions
&& exceptions
&& CFArrayGetCount(oldExceptions
) > 0) {
253 CFDictionaryRef oldLeafExceptions
= (CFDictionaryRef
)CFArrayGetValueAtIndex(oldExceptions
, 0);
254 CFDictionaryRef leafExceptions
= (CFDictionaryRef
)CFArrayGetValueAtIndex(exceptions
, 0);
255 CFDataRef oldDigest
= (CFDataRef
)CFDictionaryGetValue(oldLeafExceptions
, CFSTR("SHA1Digest"));
256 CFDataRef digest
= (CFDataRef
)CFDictionaryGetValue(leafExceptions
, CFSTR("SHA1Digest"));
257 if (!oldDigest
|| !digest
|| !CFEqual(oldDigest
, digest
)) {
258 oldExceptions
= NULL
;
262 /* add only those exceptions which are allowed by the supplied options */
264 CFMutableArrayRef filteredExceptions
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
265 CFIndex i
, exceptionCount
= (filteredExceptions
) ? CFArrayGetCount(exceptions
) : 0;
267 for (i
= 0; i
< exceptionCount
; ++i
) {
268 CFDictionaryRef exception
= (CFDictionaryRef
)CFArrayGetValueAtIndex(exceptions
, i
);
269 CFDictionaryRef oldException
= NULL
;
270 if (oldExceptions
&& i
< CFArrayGetCount(oldExceptions
)) {
271 oldException
= (CFDictionaryRef
)CFArrayGetValueAtIndex(oldExceptions
, i
);
273 CFMutableDictionaryRef filteredException
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
,
274 &kCFTypeDictionaryValueCallBacks
);
275 if (exception
&& filteredException
) {
276 SecExceptionFilterContext filterContext
= { options
, i
, trustRef
, filteredException
, oldException
};
277 CFDictionaryApplyFunction(exception
, filter_exception
, &filterContext
);
278 CFArrayAppendValue(filteredExceptions
, filteredException
);
279 CFRelease(filteredException
);
283 if (filteredExceptions
) {
284 CFIndex filteredCount
= CFArrayGetCount(filteredExceptions
);
285 /* remove empty trailing entries to match iOS behavior */
286 for (i
= filteredCount
; i
-- > 1;) {
287 CFDictionaryRef exception
= (CFDictionaryRef
)CFArrayGetValueAtIndex(filteredExceptions
, i
);
288 if (CFDictionaryGetCount(exception
) == 0) {
289 CFArrayRemoveValueAtIndex(filteredExceptions
, i
);
294 encodedExceptions
= CFPropertyListCreateData(kCFAllocatorDefault
,
295 filteredExceptions
, kCFPropertyListBinaryFormat_v1_0
, 0, NULL
);
296 CFRelease(filteredExceptions
);
298 SecTrustSetExceptions(trustRef
, encodedExceptions
);
299 CFRelease(encodedExceptions
);
301 CFRelease(exceptions
);
304 #if SECTRUST_DEPRECATION_WARNINGS
305 bool displayModifyMsg
= false;
306 bool displayNetworkMsg
= false;
307 bool displayPolicyMsg
= false;
308 const char *baseMsg
= "WARNING: SecTrustSetOptions called with";
309 const char *modifyMsg
= "Use SecTrustSetExceptions and SecTrustCopyExceptions to modify default trust results.";
310 const char *networkMsg
= "Use SecTrustSetNetworkFetchAllowed to specify whether missing certificates can be fetched from the network.";
311 const char *policyMsg
= "Use SecPolicyCreateRevocation to specify revocation policy requirements.";
313 if (options
& kSecTrustOptionAllowExpired
) {
314 syslog(LOG_ERR
, "%s %s.", baseMsg
, "kSecTrustOptionAllowExpired");
315 displayModifyMsg
= true;
317 if (options
& kSecTrustOptionAllowExpiredRoot
) {
318 syslog(LOG_ERR
, "%s %s.", baseMsg
, "kSecTrustOptionAllowExpiredRoot");
319 displayModifyMsg
= true;
321 if (options
& kSecTrustOptionFetchIssuerFromNet
) {
322 syslog(LOG_ERR
, "%s %s.", baseMsg
, "kSecTrustOptionFetchIssuerFromNet");
323 displayNetworkMsg
= true;
325 if (options
& kSecTrustOptionRequireRevPerCert
) {
326 syslog(LOG_ERR
, "%s %s.", baseMsg
, "kSecTrustOptionRequireRevPerCert");
327 displayPolicyMsg
= true;
329 if (displayModifyMsg
|| displayNetworkMsg
|| displayPolicyMsg
) {
330 syslog(LOG_ERR
, "%s %s %s",
331 (displayModifyMsg
) ? modifyMsg
: "",
332 (displayNetworkMsg
) ? networkMsg
: "",
333 (displayPolicyMsg
) ? policyMsg
: "");
340 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
341 OSStatus
SecTrustSetParameters(
342 SecTrustRef trustRef
,
343 CSSM_TP_ACTION action
,
344 CFDataRef actionData
)
346 /* bridge to support API functionality for legacy callers */
348 CSSM_APPLE_TP_ACTION_FLAGS actionFlags
= 0;
350 CSSM_APPLE_TP_ACTION_DATA
*actionDataPtr
= (CSSM_APPLE_TP_ACTION_DATA
*) CFDataGetBytePtr(actionData
);
352 actionFlags
= actionDataPtr
->ActionFlags
;
355 // note that SecTrustOptionFlags == CSSM_APPLE_TP_ACTION_FLAGS;
356 // both are sizeof(uint32) and the flag values have identical meanings
357 status
= SecTrustSetOptions(trustRef
, (SecTrustOptionFlags
)actionFlags
);
359 #if SECTRUST_DEPRECATION_WARNINGS
360 syslog(LOG_ERR
, "WARNING: SecTrustSetParameters was deprecated in 10.7. Use SecTrustSetOptions instead.");
366 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
367 OSStatus
SecTrustSetKeychains(SecTrustRef trust
, CFTypeRef keychainOrArray
)
369 /* this function is currently unsupported in unified SecTrust */
370 // TODO: pull all certs out of the specified keychains for the evaluation?
371 #if SECTRUST_DEPRECATION_WARNINGS
372 syslog(LOG_ERR
, "WARNING: SecTrustSetKeychains does nothing in 10.11. Use SecTrustSetAnchorCertificates{Only} to provide anchors.");
374 return errSecSuccess
;
378 // Construct the "official" result evidence and return it
380 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
381 OSStatus
SecTrustGetResult(
382 SecTrustRef trustRef
,
383 SecTrustResultType
*result
,
384 CFArrayRef
*certChain
, CSSM_TP_APPLE_EVIDENCE_INFO
**statusChain
)
386 /* bridge to support old functionality */
387 #if SECTRUST_DEPRECATION_WARNINGS
388 syslog(LOG_ERR
, "WARNING: SecTrustGetResult has been deprecated since 10.7. Please use SecTrustGetTrustResult instead.");
390 SecTrustResultType trustResult
;
391 OSStatus status
= SecTrustGetTrustResult(trustRef
, &trustResult
);
392 if (status
!= errSecSuccess
) {
396 *result
= trustResult
;
399 *certChain
= SecTrustCopyConstructedChain(trustRef
);
402 *statusChain
= SecTrustGetEvidenceInfo(trustRef
);
408 // Retrieve extended validation trust results
410 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
411 OSStatus
SecTrustCopyExtendedResult(SecTrustRef trust
, CFDictionaryRef
*result
)
413 /* bridge to support old functionality */
414 #if SECTRUST_DEPRECATION_WARNINGS
415 syslog(LOG_ERR
, "WARNING: SecTrustCopyExtendedResult will be deprecated in an upcoming release. Please use SecTrustCopyResult instead.");
417 CFDictionaryRef resultDict
= SecTrustCopyResult(trust
);
419 CFReleaseNull(resultDict
);
422 *result
= resultDict
;
423 return errSecSuccess
;
427 // Retrieve CSSM-level information for those who want to dig down
429 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
430 OSStatus
SecTrustGetCssmResult(SecTrustRef trust
, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR
*result
)
432 /* this function is unsupported in unified SecTrust */
433 #if SECTRUST_DEPRECATION_WARNINGS
434 syslog(LOG_ERR
, "WARNING: SecTrustGetCssmResult has been deprecated since 10.7, and has no functional equivalent in 10.11. Please use SecTrustCopyResult instead.");
439 return errSecServiceNotAvailable
;
443 // Returns a malloced array of CSSM_RETURN values, with the length in numStatusCodes,
444 // for the certificate specified by chain index in the given SecTrustRef.
446 // To match legacy behavior, the array actually allocates one element more than the
447 // value of numStatusCodes; if the certificate is revoked, the additional element
448 // at the end contains the CrlReason value.
450 // Caller must free the returned pointer.
452 static CSSM_RETURN
*copyCssmStatusCodes(SecTrustRef trust
,
453 unsigned int index
, unsigned int *numStatusCodes
)
455 if (!trust
|| !numStatusCodes
) {
459 CFArrayRef details
= SecTrustCopyFilteredDetails(trust
);
460 CFIndex chainLength
= (details
) ? CFArrayGetCount(details
) : 0;
461 if (!(index
< chainLength
)) {
462 CFReleaseSafe(details
);
465 CFDictionaryRef detail
= (CFDictionaryRef
)CFArrayGetValueAtIndex(details
, index
);
466 CFIndex ix
, detailCount
= CFDictionaryGetCount(detail
);
467 *numStatusCodes
= (unsigned int)detailCount
;
469 // Allocate one more entry than we need; this is used to store a CrlReason
470 // at the end of the array.
471 CSSM_RETURN
*statusCodes
= (CSSM_RETURN
*)malloc((detailCount
+1) * sizeof(CSSM_RETURN
));
472 statusCodes
[*numStatusCodes
] = 0;
474 const unsigned int resultmaplen
= sizeof(cssmresultmap
) / sizeof(resultmap_entry_t
);
475 const void *keys
[detailCount
];
476 CFDictionaryGetKeysAndValues(detail
, &keys
[0], NULL
);
477 for (ix
= 0; ix
< detailCount
; ix
++) {
478 CFStringRef key
= (CFStringRef
)keys
[ix
];
479 CSSM_RETURN statusCode
= CSSM_OK
;
480 for (unsigned int mapix
= 0; mapix
< resultmaplen
; mapix
++) {
481 CFStringRef str
= (CFStringRef
) cssmresultmap
[mapix
].checkstr
;
482 if (CFStringCompare(str
, key
, 0) == kCFCompareEqualTo
) {
483 statusCode
= (CSSM_RETURN
) cssmresultmap
[mapix
].resultcode
;
487 if (statusCode
== CSSMERR_TP_CERT_REVOKED
) {
489 CFNumberRef number
= (CFNumberRef
)CFDictionaryGetValue(detail
, key
);
490 if (number
&& CFNumberGetValue(number
, kCFNumberSInt32Type
, &reason
)) {
491 statusCodes
[*numStatusCodes
] = (CSSM_RETURN
)reason
;
494 statusCodes
[ix
] = statusCode
;
497 CFReleaseSafe(details
);
501 static uint8_t convertCssmResultToPriority(CSSM_RETURN resultCode
) {
502 switch (resultCode
) {
503 /* explicitly not trusted */
504 case CSSMERR_TP_CERT_REVOKED
:
505 case CSSMERR_APPLETP_TRUST_SETTING_DENY
:
507 /* failure to comply with X.509 */
508 case CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS
:
509 case CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT
:
510 case CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT
:
511 case CSSMERR_APPLETP_INVALID_AUTHORITY_ID
:
512 case CSSMERR_TP_INVALID_CERTIFICATE
:
513 case CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN
:
515 case CSSMERR_TP_CERT_EXPIRED
:
517 /* doesn't chain to trusted root */
518 case CSSMERR_TP_NOT_TRUSTED
:
519 case CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH
:
521 /* all others are policy-specific failures */
527 #include <libDER/oidsPriv.h>
528 #include <Security/oidscert.h>
529 static bool isSoftwareUpdateDevelopment(SecTrustRef trust
) {
530 bool isPolicy
= false, isEKU
= false;
531 CFArrayRef policies
= NULL
;
533 /* Policy used to evaluate was SWUpdateSigning */
534 SecTrustCopyPolicies(trust
, &policies
);
536 SecPolicyRef swUpdatePolicy
= SecPolicyCreateAppleSWUpdateSigning();
537 if (swUpdatePolicy
&& CFArrayContainsValue(policies
, CFRangeMake(0, CFArrayGetCount(policies
)),
541 if (swUpdatePolicy
) { CFRelease(swUpdatePolicy
); }
548 /* Only error was EKU on the leaf */
549 CFArrayRef details
= SecTrustCopyFilteredDetails(trust
);
550 CFIndex ix
, count
= CFArrayGetCount(details
);
551 bool hasDisqualifyingError
= false;
552 for (ix
= 0; ix
< count
; ix
++) {
553 CFDictionaryRef detail
= (CFDictionaryRef
)CFArrayGetValueAtIndex(details
, ix
);
554 if (ix
== 0) { // Leaf
555 if (CFDictionaryGetCount(detail
) != 1 || // One error
556 CFDictionaryGetValue(detail
, CFSTR("ExtendedKeyUsage")) != kCFBooleanFalse
) { // kSecPolicyCheckExtendedKeyUsage
557 hasDisqualifyingError
= true;
561 if (CFDictionaryGetCount(detail
) > 0) { // No errors on other certs
562 hasDisqualifyingError
= true;
567 CFReleaseSafe(details
);
568 if (hasDisqualifyingError
) {
572 /* EKU on the leaf is the Apple Development Code Signing OID */
573 SecCertificateRef leaf
= SecTrustGetCertificateAtIndex(trust
, 0);
574 CSSM_DATA
*fieldValue
= NULL
;
575 if (errSecSuccess
!= SecCertificateCopyFirstFieldValue(leaf
, &CSSMOID_ExtendedKeyUsage
, &fieldValue
)) {
578 if (fieldValue
&& fieldValue
->Data
&& fieldValue
->Length
== sizeof(CSSM_X509_EXTENSION
)) {
579 const CSSM_X509_EXTENSION
*ext
= (const CSSM_X509_EXTENSION
*)fieldValue
->Data
;
580 if (ext
->format
== CSSM_X509_DATAFORMAT_PARSED
) {
581 const CE_ExtendedKeyUsage
*ekus
= (const CE_ExtendedKeyUsage
*)ext
->value
.parsedValue
;
582 if (ekus
&& (ekus
->numPurposes
== 1) && ekus
->purposes
[0].Data
&&
583 (ekus
->purposes
[0].Length
== CSSMOID_APPLE_EKU_CODE_SIGNING_DEV
.Length
) &&
584 (memcmp(ekus
->purposes
[0].Data
, CSSMOID_APPLE_EKU_CODE_SIGNING_DEV
.Data
,
585 ekus
->purposes
[0].Length
) == 0)) {
590 SecCertificateReleaseFirstFieldValue(leaf
, &CSSMOID_ExtendedKeyUsage
, fieldValue
);
595 // Retrieve CSSM_LEVEL TP return code
597 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
598 OSStatus
SecTrustGetCssmResultCode(SecTrustRef trustRef
, OSStatus
*result
)
600 /* bridge to support old functionality */
601 #if SECTRUST_DEPRECATION_WARNINGS
602 syslog(LOG_ERR
, "WARNING: SecTrustGetCssmResultCode has been deprecated since 10.7, and will be removed in a future release. Please use SecTrustCopyProperties instead.");
604 if (!trustRef
|| !result
) {
608 SecTrustResultType trustResult
= kSecTrustResultInvalid
;
609 (void) SecTrustGetTrustResult(trustRef
, &trustResult
);
610 if (trustResult
== kSecTrustResultProceed
|| trustResult
== kSecTrustResultUnspecified
) {
611 if (result
) { *result
= 0; }
612 return errSecSuccess
;
615 /* Development Software Update certs return a special error code when evaluated
616 * against the AppleSWUpdateSigning policy. See <rdar://27362805>. */
617 if (isSoftwareUpdateDevelopment(trustRef
)) {
619 *result
= CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT
;
621 return errSecSuccess
;
624 OSStatus cssmResultCode
= errSecSuccess
;
625 uint8_t resultCodePriority
= 0xFF;
626 CFIndex ix
, count
= SecTrustGetCertificateCount(trustRef
);
627 for (ix
= 0; ix
< count
; ix
++) {
628 unsigned int numStatusCodes
;
629 CSSM_RETURN
*statusCodes
= NULL
;
630 statusCodes
= copyCssmStatusCodes(trustRef
, (uint32_t)ix
, &numStatusCodes
);
631 if (statusCodes
&& numStatusCodes
> 0) {
632 unsigned int statusIX
;
633 for (statusIX
= 0; statusIX
< numStatusCodes
; statusIX
++) {
634 CSSM_RETURN currStatus
= statusCodes
[statusIX
];
635 uint8_t currPriority
= convertCssmResultToPriority(currStatus
);
636 if (resultCodePriority
> currPriority
) {
637 cssmResultCode
= currStatus
;
638 resultCodePriority
= currPriority
;
642 if (statusCodes
) { free(statusCodes
); }
643 if (resultCodePriority
== 1) { break; }
647 *result
= cssmResultCode
;
649 return errSecSuccess
;
652 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
653 OSStatus
SecTrustGetTPHandle(SecTrustRef trust
, CSSM_TP_HANDLE
*handle
)
655 /* this function is unsupported in unified SecTrust */
656 #if SECTRUST_DEPRECATION_WARNINGS
657 syslog(LOG_ERR
, "WARNING: SecTrustGetTPHandle has been deprecated since 10.7, and cannot return CSSM objects in 10.11. Please stop using it.");
662 return errSecServiceNotAvailable
;
666 // Get the user's default anchor certificate set
669 OSStatus
SecTrustCopyAnchorCertificates(CFArrayRef
*anchorCertificates
)
673 return SecTrustSettingsCopyUnrestrictedRoots(
674 true, true, true, /* all domains */
680 /* We have an iOS-style SecTrustRef, but we need to return a CDSA-based SecKeyRef.
682 SecKeyRef
SecTrustCopyPublicKey(SecTrustRef trust
)
684 SecKeyRef pubKey
= NULL
;
685 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, 0);
686 (void) SecCertificateCopyPublicKey(certificate
, &pubKey
);
690 // cannot link against the new iOS SecTrust from this implementation,
691 // so there are no possible accessors for the fields of this struct
692 typedef struct __TSecTrust
{
694 CFArrayRef _certificates
;
697 CFArrayRef _responses
;
699 CFArrayRef _trustedLogs
;
700 CFDateRef _verifyDate
;
702 SecKeyRef _publicKey
;
704 CFDictionaryRef _info
;
705 CFArrayRef _exceptions
;
706 SecTrustResultType _trustResult
;
708 bool _keychainsAllowed
;
709 void* _legacy_info_array
;
710 void* _legacy_status_array
;
711 SecTrustResultType _trustResultBeforeExceptions
;
712 dispatch_queue_t _trustQueue
;
715 CFArrayRef
SecTrustCopyInputCertificates(SecTrustRef trust
)
717 if (!trust
) { return NULL
; };
718 TSecTrust
*secTrust
= (TSecTrust
*)trust
;
719 if (secTrust
->_certificates
) {
720 CFRetain(secTrust
->_certificates
);
722 return secTrust
->_certificates
;
725 CFArrayRef
SecTrustCopyInputAnchors(SecTrustRef trust
)
727 if (!trust
) { return NULL
; };
728 TSecTrust
*secTrust
= (TSecTrust
*)trust
;
729 if (secTrust
->_anchors
) {
730 CFRetain(secTrust
->_anchors
);
732 return secTrust
->_anchors
;
735 // Return the constructed certificate chain for this trust reference,
736 // making output certificates pointer-equivalent to any provided input
737 // certificates (where possible) for legacy behavioral compatibility.
738 // Caller must release this array.
740 CFArrayRef
SecTrustCopyConstructedChain(SecTrustRef trust
)
742 CFMutableArrayRef certChain
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
743 CFIndex idx
, count
= SecTrustGetCertificateCount(trust
);
744 for (idx
=0; idx
< count
; idx
++) {
745 SecCertificateRef certificate
= SecTrustGetCertificateAtIndex(trust
, idx
);
747 CFArrayAppendValue(certChain
, certificate
);
751 // Some callers make the assumption that the certificates in
752 // this chain are pointer-equivalent to ones they passed to the
753 // SecTrustCreateWithCertificates function. We'll maintain that
754 // behavior here for compatibility.
756 CFArrayRef inputCertArray
= SecTrustCopyInputCertificates(trust
);
757 CFArrayRef inputAnchorArray
= SecTrustCopyInputAnchors(trust
);
758 CFIndex inputCertIdx
, inputCertCount
= (inputCertArray
) ? CFArrayGetCount(inputCertArray
) : 0;
759 CFIndex inputAnchorIdx
, inputAnchorCount
= (inputAnchorArray
) ? CFArrayGetCount(inputAnchorArray
) : 0;
760 for (idx
=0; idx
< count
; idx
++) {
761 SecCertificateRef tmpCert
= (SecCertificateRef
) CFArrayGetValueAtIndex(certChain
, idx
);
763 SecCertificateRef matchCert
= NULL
;
764 for (inputCertIdx
=0; inputCertIdx
< inputCertCount
&& !matchCert
; inputCertIdx
++) {
765 SecCertificateRef inputCert
= (SecCertificateRef
) CFArrayGetValueAtIndex(inputCertArray
, inputCertIdx
);
766 if (inputCert
&& CFEqual(inputCert
, tmpCert
)) {
767 matchCert
= inputCert
;
770 for (inputAnchorIdx
=0; inputAnchorIdx
< inputAnchorCount
&& !matchCert
; inputAnchorIdx
++) {
771 SecCertificateRef inputAnchor
= (SecCertificateRef
) CFArrayGetValueAtIndex(inputAnchorArray
, inputAnchorIdx
);
772 if (inputAnchor
&& CFEqual(inputAnchor
, tmpCert
)) {
773 matchCert
= inputAnchor
;
777 CFArraySetValueAtIndex(certChain
, idx
, matchCert
);
781 if (inputCertArray
) {
782 CFRelease(inputCertArray
);
784 if (inputAnchorArray
) {
785 CFRelease(inputAnchorArray
);
791 // Here is where backward compatibility gets ugly. CSSM_TP_APPLE_EVIDENCE_INFO does not exist
792 // in the unified SecTrust world. Unfortunately, some clients are still calling legacy APIs
793 // (e.g. SecTrustGetResult) and grubbing through the info for StatusBits and StatusCodes.
794 // SecTrustGetEvidenceInfo builds the legacy evidence info structure as needed, and returns
795 // a pointer to it. The evidence data is allocated here and set in the _legacy_* fields
796 // of the TSecTrust; the trust object subsequently owns it. The returned pointer is expected
797 // to be valid for the lifetime of the SecTrustRef, or until the trust parameters are changed,
798 // which would force re-evaluation.
800 static CSSM_TP_APPLE_EVIDENCE_INFO
*
801 SecTrustGetEvidenceInfo(SecTrustRef trust
)
803 TSecTrust
*secTrust
= (TSecTrust
*)trust
;
807 if (secTrust
->_trustResult
!= kSecTrustResultInvalid
&&
808 secTrust
->_legacy_info_array
) {
809 // we've already got valid evidence info, return it now.
810 return (CSSM_TP_APPLE_EVIDENCE_INFO
*)secTrust
->_legacy_info_array
;
813 // Getting the count implicitly evaluates the chain if necessary.
814 CFIndex idx
, count
= SecTrustGetCertificateCount(trust
);
815 CFArrayRef inputCertArray
= SecTrustCopyInputCertificates(trust
);
816 CFArrayRef inputAnchorArray
= SecTrustCopyInputAnchors(trust
);
817 CFIndex inputCertIdx
, inputCertCount
= (inputCertArray
) ? CFArrayGetCount(inputCertArray
) : 0;
818 CFIndex inputAnchorIdx
, inputAnchorCount
= (inputAnchorArray
) ? CFArrayGetCount(inputAnchorArray
) : 0;
820 CSSM_TP_APPLE_EVIDENCE_INFO
*infoArray
= (CSSM_TP_APPLE_EVIDENCE_INFO
*)calloc(count
, sizeof(CSSM_TP_APPLE_EVIDENCE_INFO
));
821 CSSM_RETURN
*statusArray
= NULL
;
822 unsigned int numStatusCodes
= 0;
824 // Set status codes for each certificate in the constructed chain
825 for (idx
=0; idx
< count
; idx
++) {
826 SecCertificateRef cert
= SecTrustGetCertificateAtIndex(trust
, idx
);
830 CSSM_TP_APPLE_EVIDENCE_INFO
*evInfo
= &infoArray
[idx
];
832 /* first the booleans (StatusBits flags) */
833 CFAbsoluteTime now
= CFAbsoluteTimeGetCurrent();
834 if (secTrust
->_verifyDate
) {
835 now
= CFDateGetAbsoluteTime(secTrust
->_verifyDate
);
837 CFAbsoluteTime na
= SecCertificateNotValidAfter(cert
);
839 evInfo
->StatusBits
|= CSSM_CERT_STATUS_EXPIRED
;
841 CFAbsoluteTime nb
= SecCertificateNotValidBefore(cert
);
843 evInfo
->StatusBits
|= CSSM_CERT_STATUS_NOT_VALID_YET
;
845 for (inputAnchorIdx
=0; inputAnchorIdx
< inputAnchorCount
; inputAnchorIdx
++) {
846 SecCertificateRef inputAnchor
= (SecCertificateRef
) CFArrayGetValueAtIndex(inputAnchorArray
, inputAnchorIdx
);
847 if (inputAnchor
&& CFEqual(inputAnchor
, cert
)) {
848 evInfo
->StatusBits
|= CSSM_CERT_STATUS_IS_IN_ANCHORS
;
852 for (inputCertIdx
=0; inputCertIdx
< inputCertCount
; inputCertIdx
++) {
853 SecCertificateRef inputCert
= (SecCertificateRef
) CFArrayGetValueAtIndex(inputCertArray
, inputCertIdx
);
854 if (inputCert
&& CFEqual(inputCert
, cert
)) {
855 evInfo
->StatusBits
|= CSSM_CERT_STATUS_IS_IN_INPUT_CERTS
;
860 /* See if there are trust settings for this certificate. */
861 CFStringRef hashStr
= SecTrustSettingsCertHashStrFromCert(cert
);
862 bool foundMatch
= false;
863 bool foundAny
= false;
864 CSSM_RETURN
*errors
= NULL
;
865 uint32 errorCount
= 0;
867 SecTrustSettingsDomain foundDomain
= kSecTrustSettingsDomainUser
;
868 SecTrustSettingsResult foundResult
= kSecTrustSettingsResultInvalid
;
869 bool isSelfSigned
= false;
870 if ((count
- 1) == idx
) {
871 // Only the last cert in the chain needs to be considered
873 status
= SecCertificateIsSelfSigned(cert
, &selfSigned
);
874 isSelfSigned
= (status
) ? false : ((selfSigned
) ? true : false);
876 evInfo
->StatusBits
|= CSSM_CERT_STATUS_IS_ROOT
;
879 // STU: rdar://25554967
880 // %%% need to get policyOID, policyString, and keyUsage here!
882 status
= SecTrustSettingsEvaluateCert(
883 hashStr
, /* certHashStr */
884 NULL
, /* policyOID (optional) */
885 NULL
, /* policyString (optional) */
886 0, /* policyStringLen */
888 isSelfSigned
, /* isRootCert */
889 &foundDomain
, /* foundDomain */
890 &errors
, /* allowedErrors -- MUST FREE */
891 &errorCount
, /* numAllowedErrors */
892 &foundResult
, /* resultType */
893 &foundMatch
, /* foundMatchingEntry */
894 &foundAny
); /* foundAnyEntry */
896 if (status
== errSecSuccess
) {
898 switch (foundResult
) {
899 case kSecTrustSettingsResultTrustRoot
:
900 case kSecTrustSettingsResultTrustAsRoot
:
901 /* these two can be disambiguated by IS_ROOT */
902 evInfo
->StatusBits
|= CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST
;
904 case kSecTrustSettingsResultDeny
:
905 evInfo
->StatusBits
|= CSSM_CERT_STATUS_TRUST_SETTINGS_DENY
;
907 case kSecTrustSettingsResultUnspecified
:
908 case kSecTrustSettingsResultInvalid
:
921 unsigned int numCodes
=0;
922 CSSM_RETURN
*statusCodes
= copyCssmStatusCodes(trust
, (unsigned int)idx
, &numCodes
);
924 // Realloc space for these status codes at end of our status codes block.
925 // Two important things to note:
926 // 1. the actual length is numCodes+1 because copyCssmStatusCodes
927 // allocates one more element at the end for the CrlReason value.
928 // 2. realloc may cause the pointer to move, which means we will
929 // need to fix up the StatusCodes fields after we're done with this loop.
930 unsigned int totalStatusCodes
= numStatusCodes
+ numCodes
+ 1;
931 statusArray
= (CSSM_RETURN
*)realloc(statusArray
, totalStatusCodes
* sizeof(CSSM_RETURN
));
932 evInfo
->StatusCodes
= &statusArray
[numStatusCodes
];
933 evInfo
->NumStatusCodes
= numCodes
;
934 // Copy the new codes (plus one) into place
935 for (unsigned int cpix
= 0; cpix
<= numCodes
; cpix
++) {
936 evInfo
->StatusCodes
[cpix
] = statusCodes
[cpix
];
938 numStatusCodes
= totalStatusCodes
;
942 if(evInfo
->StatusBits
& (CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST
|
943 CSSM_CERT_STATUS_TRUST_SETTINGS_DENY
|
944 CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR
)) {
945 /* Something noteworthy happened involving TrustSettings */
946 uint32 whichDomain
= 0;
947 switch(foundDomain
) {
948 case kSecTrustSettingsDomainUser
:
949 whichDomain
= CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER
;
951 case kSecTrustSettingsDomainAdmin
:
952 whichDomain
= CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN
;
954 case kSecTrustSettingsDomainSystem
:
955 whichDomain
= CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM
;
958 evInfo
->StatusBits
|= whichDomain
;
961 /* index into raw cert group or AnchorCerts depending on IS_IN_ANCHORS */
962 //evInfo->Index = certInfo->index();
963 /* nonzero if cert came from a DLDB */
964 //evInfo->DlDbHandle = certInfo->dlDbHandle();
965 //evInfo->UniqueRecord = certInfo->uniqueRecord();
968 // Now that all the status codes have been allocated in a contiguous block,
969 // refresh the StatusCodes pointer in each array element.
971 for (idx
=0; idx
< count
; idx
++) {
972 CSSM_TP_APPLE_EVIDENCE_INFO
*evInfo
= &infoArray
[idx
];
973 evInfo
->StatusCodes
= &statusArray
[numStatusCodes
];
974 numStatusCodes
+= evInfo
->NumStatusCodes
+ 1;
977 secTrust
->_legacy_info_array
= infoArray
;
978 secTrust
->_legacy_status_array
= statusArray
;
980 if (inputCertArray
) {
981 CFRelease(inputCertArray
);
983 if (inputAnchorArray
) {
984 CFRelease(inputAnchorArray
);
987 return (CSSM_TP_APPLE_EVIDENCE_INFO
*)secTrust
->_legacy_info_array
;
990 CFArrayRef
SecTrustCopyProperties(SecTrustRef trust
) {
991 /* OS X creates a completely different structure with one dictionary for each certificate */
992 CFIndex ix
, count
= SecTrustGetCertificateCount(trust
);
994 CFMutableArrayRef properties
= CFArrayCreateMutable(kCFAllocatorDefault
, count
,
995 &kCFTypeArrayCallBacks
);
997 for (ix
= 0; ix
< count
; ix
++) {
998 CFMutableDictionaryRef certDict
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
,
999 &kCFTypeDictionaryValueCallBacks
);
1000 /* Populate the certificate title */
1001 SecCertificateRef cert
= SecTrustGetCertificateAtIndex(trust
, ix
);
1003 CFStringRef subjectSummary
= SecCertificateCopySubjectSummary(cert
);
1004 if (subjectSummary
) {
1005 CFDictionaryAddValue(certDict
, kSecPropertyTypeTitle
, subjectSummary
);
1006 CFRelease(subjectSummary
);
1010 /* Populate a revocation reason if the cert was revoked */
1011 unsigned int numStatusCodes
;
1012 CSSM_RETURN
*statusCodes
= NULL
;
1013 statusCodes
= copyCssmStatusCodes(trust
, (uint32_t)ix
, &numStatusCodes
);
1015 int32_t reason
= statusCodes
[numStatusCodes
]; // stored at end of status codes array
1017 CFNumberRef cfreason
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &reason
);
1019 CFDictionarySetValue(certDict
, kSecTrustRevocationReason
, cfreason
);
1020 CFRelease(cfreason
);
1026 /* Populate the error in the leaf dictionary */
1028 OSStatus error
= errSecSuccess
;
1029 (void)SecTrustGetCssmResultCode(trust
, &error
);
1030 CFStringRef errorStr
= SecCopyErrorMessageString(error
, NULL
);
1032 CFDictionarySetValue(certDict
, kSecPropertyTypeError
, errorStr
);
1033 CFRelease(errorStr
);
1037 CFArrayAppendValue(properties
, certDict
);
1038 CFRelease(certDict
);
1044 /* deprecated in 10.5 */
1045 OSStatus
SecTrustGetCSSMAnchorCertificates(const CSSM_DATA
**cssmAnchors
,
1046 uint32
*cssmAnchorCount
)
1048 /* this function is unsupported in unified SecTrust */
1049 #if SECTRUST_DEPRECATION_WARNINGS
1050 syslog(LOG_ERR
, "WARNING: SecTrustGetCSSMAnchorCertificates has been deprecated since 10.5, and cannot return CSSM objects in 10.11. Please stop using it.");
1053 *cssmAnchors
= NULL
;
1055 if (cssmAnchorCount
) {
1056 *cssmAnchorCount
= 0;
1058 return errSecServiceNotAvailable
;
1063 // Get and set user trust settings. Deprecated in 10.5.
1064 // User Trust getter, deprecated, works as it always has.
1066 OSStatus
SecTrustGetUserTrust(SecCertificateRef certificate
,
1067 SecPolicyRef policy
, SecTrustUserSetting
*trustSetting
)
1069 /* this function is unsupported in unified SecTrust */
1070 #if SECTRUST_DEPRECATION_WARNINGS
1071 syslog(LOG_ERR
, "WARNING: SecTrustGetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
1073 return errSecServiceNotAvailable
;
1077 // The public setter, also deprecated; it maps to the appropriate
1078 // Trust Settings call if possible, else throws errSecUnimplemented.
1080 OSStatus
SecTrustSetUserTrust(SecCertificateRef certificate
,
1081 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
1083 /* this function is unsupported in unified SecTrust */
1084 #if SECTRUST_DEPRECATION_WARNINGS
1085 syslog(LOG_ERR
, "WARNING: SecTrustSetUserTrust has been deprecated since 10.5, and does nothing in 10.11. Please stop using it.");
1087 return errSecServiceNotAvailable
;
1091 // This one is the now-private version of what SecTrustSetUserTrust() used to
1092 // be. The public API can no longer manipulate User Trust settings, only
1095 OSStatus
SecTrustSetUserTrustLegacy(SecCertificateRef certificate
,
1096 SecPolicyRef policy
, SecTrustUserSetting trustSetting
)
1098 /* this function is unsupported in unified SecTrust */
1099 #if SECTRUST_DEPRECATION_WARNINGS
1100 syslog(LOG_ERR
, "WARNING: SecTrustSetUserTrustLegacy does nothing in 10.11. Please stop using it.");
1102 return errSecServiceNotAvailable
;