]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_keychain/lib/SecTrust.cpp
Security-57031.10.10.tar.gz
[apple/security.git] / Security / libsecurity_keychain / lib / SecTrust.cpp
1 /*
2 * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include "SecTrust.h"
25 #include "SecTrustPriv.h"
26 #include "Trust.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>
38
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);
43
44 typedef struct SecTrustCheckExceptionContext {
45 CFDictionaryRef exception;
46 bool exceptionNotFound;
47 } SecTrustCheckExceptionContext;
48
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");
57
58 //
59 // CF boilerplate
60 //
61 CFTypeID SecTrustGetTypeID(void)
62 {
63 BEGIN_SECAPI
64
65 return gTypes().Trust.typeID;
66
67 END_SECAPI1(_kCFRuntimeNotATypeID)
68 }
69
70
71 //
72 // Sec* API bridge functions
73 //
74 OSStatus SecTrustCreateWithCertificates(
75 CFTypeRef certificates,
76 CFTypeRef policies,
77 SecTrustRef *trustRef)
78 {
79 BEGIN_SECAPI
80 Required(trustRef);
81 *trustRef = (new Trust(certificates, policies))->handle();
82 END_SECAPI
83 }
84
85 OSStatus
86 SecTrustSetPolicies(SecTrustRef trustRef, CFTypeRef policies)
87 {
88 BEGIN_SECAPI
89 Trust::required(trustRef)->policies(policies);
90 END_SECAPI
91 }
92
93 OSStatus
94 SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options)
95 {
96 BEGIN_SECAPI
97 CSSM_APPLE_TP_ACTION_DATA actionData = {
98 CSSM_APPLE_TP_ACTION_VERSION,
99 (CSSM_APPLE_TP_ACTION_FLAGS)options
100 };
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);
108 END_SECAPI
109 }
110
111 OSStatus SecTrustSetParameters(
112 SecTrustRef trustRef,
113 CSSM_TP_ACTION action,
114 CFDataRef actionData)
115 {
116 BEGIN_SECAPI
117 Trust *trust = Trust::required(trustRef);
118 trust->action(action);
119 trust->actionData(actionData);
120 END_SECAPI
121 }
122
123
124 OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, CFArrayRef anchorCertificates)
125 {
126 BEGIN_SECAPI
127 Trust::required(trust)->anchors(anchorCertificates);
128 END_SECAPI
129 }
130
131 OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, Boolean anchorCertificatesOnly)
132 {
133 BEGIN_SECAPI
134 Trust::AnchorPolicy policy = (anchorCertificatesOnly) ? Trust::useAnchorsOnly : Trust::useAnchorsAndBuiltIns;
135 Trust::required(trust)->anchorPolicy(policy);
136 END_SECAPI
137 }
138
139 OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray)
140 {
141 BEGIN_SECAPI
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);
148 }
149 Trust::required(trust)->searchLibs(keychains);
150 END_SECAPI
151 }
152
153
154 OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate)
155 {
156 BEGIN_SECAPI
157 Trust::required(trust)->time(verifyDate);
158 END_SECAPI
159 }
160
161
162 CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust)
163 {
164 CFAbsoluteTime verifyTime = 0;
165 OSStatus __secapiresult = errSecSuccess;
166 try {
167 CFRef<CFDateRef> verifyDate = Trust::required(trust)->time();
168 verifyTime = CFDateGetAbsoluteTime(verifyDate);
169 }
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; }
174 return verifyTime;
175 }
176
177
178 OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *resultP)
179 {
180 SecTrustResultType trustResult = kSecTrustResultInvalid;
181 CFArrayRef exceptions = NULL;
182 OSStatus __secapiresult = errSecSuccess;
183 try {
184 Trust *trustObj = Trust::required(trust);
185 trustObj->evaluate();
186 trustResult = trustObj->result();
187 exceptions = trustObj->exceptions();
188 }
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; }
193
194 if (__secapiresult) {
195 return __secapiresult;
196 }
197
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;
203 }
204 else if (trustResult == kSecTrustResultRecoverableTrustFailure && exceptions) {
205 /* If we have exceptions get details and match to exceptions. */
206 CFArrayRef details = SecTrustCopyDetails(trust);
207 if (details) {
208 CFIndex pathLength = CFArrayGetCount(details);
209 struct SecTrustCheckExceptionContext context = {};
210 CFIndex ix;
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) {
218 break;
219 }
220 }
221 if (!context.exceptionNotFound)
222 trustResult = kSecTrustResultProceed;
223 }
224 }
225
226
227 secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult);
228 if (resultP) {
229 *resultP = trustResult;
230 }
231 return __secapiresult;
232 }
233
234 OSStatus SecTrustEvaluateAsync(SecTrustRef trust,
235 dispatch_queue_t queue, SecTrustCallback result)
236 {
237 BEGIN_SECAPI
238 dispatch_async(queue, ^{
239 try {
240 Trust *trustObj = Trust::required(trust);
241 trustObj->evaluate();
242 SecTrustResultType trustResult = trustObj->result();
243 result(trust, trustResult);
244 }
245 catch (...) {
246 result(trust, kSecTrustResultInvalid);
247 };
248 });
249 END_SECAPI
250 }
251
252 //
253 // Construct the "official" result evidence and return it
254 //
255 OSStatus SecTrustGetResult(
256 SecTrustRef trustRef,
257 SecTrustResultType *result,
258 CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain)
259 {
260 BEGIN_SECAPI
261 Trust *trust = Trust::required(trustRef);
262 if (result)
263 *result = trust->result();
264 if (certChain && statusChain)
265 trust->buildEvidence(*certChain, TPEvidenceInfo::overlayVar(*statusChain));
266 END_SECAPI
267 }
268
269 //
270 // Retrieve result of trust evaluation only
271 //
272 OSStatus SecTrustGetTrustResult(SecTrustRef trustRef,
273 SecTrustResultType *result)
274 {
275 BEGIN_SECAPI
276 Trust *trust = Trust::required(trustRef);
277 if (result) *result = trust->result();
278 END_SECAPI
279 }
280
281 //
282 // Retrieve extended validation trust results
283 //
284 OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result)
285 {
286 BEGIN_SECAPI
287 Trust *trustObj = Trust::required(trust);
288 if (result == nil)
289 return errSecParam;
290 trustObj->extendedResult(*result);
291 END_SECAPI
292 }
293
294 //
295 // Retrieve CSSM-level information for those who want to dig down
296 //
297 OSStatus SecTrustGetCssmResult(SecTrustRef trust, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result)
298 {
299 BEGIN_SECAPI
300 Required(result) = Trust::required(trust)->cssmResult();
301 END_SECAPI
302 }
303
304 //
305 // Retrieve CSSM_LEVEL TP return code
306 //
307 OSStatus SecTrustGetCssmResultCode(SecTrustRef trustRef, OSStatus *result)
308 {
309 BEGIN_SECAPI
310 Trust *trust = Trust::required(trustRef);
311 if (trust->result() == kSecTrustResultInvalid)
312 return errSecParam;
313 else
314 Required(result) = trust->cssmResultCode();
315 END_SECAPI
316 }
317
318 OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle)
319 {
320 BEGIN_SECAPI
321 Required(handle) = Trust::required(trust)->getTPHandle();
322 END_SECAPI
323 }
324
325 OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies)
326 {
327 BEGIN_SECAPI
328 CFArrayRef currentPolicies = Trust::required(trust)->policies();
329 if (currentPolicies != NULL)
330 {
331 CFRetain(currentPolicies);
332 }
333
334 Required(policies) = currentPolicies;
335 END_SECAPI
336 }
337
338 OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, Boolean allowFetch)
339 {
340 BEGIN_SECAPI
341 Trust *trustObj = Trust::required(trust);
342 Trust::NetworkPolicy netPolicy = (allowFetch) ?
343 Trust::useNetworkEnabled : Trust::useNetworkDisabled;
344 trustObj->networkPolicy(netPolicy);
345 END_SECAPI
346 }
347
348 OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, Boolean *allowFetch)
349 {
350 BEGIN_SECAPI
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);
357 } else {
358 // caller has explicitly set the network policy
359 allowed = (netPolicy == Trust::useNetworkEnabled);
360 }
361 Required(allowFetch) = allowed;
362 END_SECAPI
363 }
364
365 OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData)
366 {
367 BEGIN_SECAPI
368 Trust::required(trust)->responses(responseData);
369 END_SECAPI
370 }
371
372 OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchorCertificates)
373 {
374 BEGIN_SECAPI
375 CFArrayRef customAnchors = Trust::required(trust)->anchors();
376 Required(anchorCertificates) = (customAnchors) ?
377 (const CFArrayRef)CFRetain(customAnchors) : (const CFArrayRef)NULL;
378 END_SECAPI
379 }
380
381 //
382 // Get the user's default anchor certificate set
383 //
384 OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchorCertificates)
385 {
386 BEGIN_SECAPI
387
388 return SecTrustSettingsCopyUnrestrictedRoots(
389 true, true, true, /* all domains */
390 anchorCertificates);
391
392 END_SECAPI
393 }
394
395 /* new in 10.6 */
396 SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust)
397 {
398 SecKeyRef pubKey = NULL;
399 CFArrayRef certChain = NULL;
400 CFArrayRef evidenceChain = NULL;
401 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
402 OSStatus __secapiresult = errSecSuccess;
403 try {
404 Trust *trustObj = Trust::required(trust);
405 if (trustObj->result() == kSecTrustResultInvalid) {
406 // Trust hasn't been evaluated; attempt to retrieve public key from leaf.
407 SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, 0);
408 __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey);
409 if (pubKey) {
410 return pubKey;
411 }
412 // Otherwise, we must evaluate first.
413 trustObj->evaluate();
414 if (trustObj->result() == kSecTrustResultInvalid) {
415 MacOSError::throwMe(errSecTrustNotAvailable);
416 }
417 }
418 if (trustObj->evidence() == nil) {
419 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
420 }
421 evidenceChain = trustObj->evidence();
422 }
423 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
424 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
425 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
426 catch (...) { __secapiresult=errSecInternalComponent; }
427
428 if (certChain)
429 CFRelease(certChain);
430
431 if (evidenceChain) {
432 if (CFArrayGetCount(evidenceChain) > 0) {
433 SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, 0);
434 __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey);
435 }
436 // do not release evidenceChain, as it is owned by the trust object.
437 }
438 return pubKey;
439 }
440
441 /* new in 10.6 */
442 CFIndex SecTrustGetCertificateCount(SecTrustRef trust)
443 {
444 CFIndex chainLen = 0;
445 CFArrayRef certChain = NULL;
446 CFArrayRef evidenceChain = NULL;
447 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
448 OSStatus __secapiresult = errSecSuccess;
449 try {
450 Trust *trustObj = Trust::required(trust);
451 if (trustObj->result() == kSecTrustResultInvalid) {
452 trustObj->evaluate();
453 if (trustObj->result() == kSecTrustResultInvalid)
454 MacOSError::throwMe(errSecTrustNotAvailable);
455 }
456 if (trustObj->evidence() == nil)
457 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
458 evidenceChain = trustObj->evidence();
459 }
460 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
461 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
462 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
463 catch (...) { __secapiresult=errSecInternalComponent; }
464
465 if (certChain)
466 CFRelease(certChain);
467
468 if (evidenceChain)
469 chainLen = CFArrayGetCount(evidenceChain); // don't release, trust object owns it.
470
471 return chainLen;
472 }
473
474 /* new in 10.6 */
475 SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix)
476 {
477 SecCertificateRef certificate = NULL;
478 CFArrayRef certChain = NULL;
479 CFArrayRef evidenceChain = NULL;
480 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
481 OSStatus __secapiresult = errSecSuccess;
482 try {
483 Trust *trustObj = Trust::required(trust);
484 if (trustObj->result() == kSecTrustResultInvalid) {
485 // If caller is asking for the leaf, we can return it without
486 // having to evaluate the entire chain. Note that we don't retain
487 // the cert as it's owned by the trust and this is a 'Get' API.
488 if (ix == 0) {
489 CFArrayRef certs = trustObj->certificates();
490 if (certs && (CFArrayGetCount(certs) > 0)) {
491 certificate = (SecCertificateRef) CFArrayGetValueAtIndex(certs, 0);
492 if (certificate) {
493 return certificate;
494 }
495 }
496 }
497 // Otherwise, we must evaluate first.
498 trustObj->evaluate();
499 if (trustObj->result() == kSecTrustResultInvalid) {
500 MacOSError::throwMe(errSecTrustNotAvailable);
501 }
502 }
503 if (trustObj->evidence() == nil) {
504 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
505 }
506 evidenceChain = trustObj->evidence();
507 }
508 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
509 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
510 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
511 catch (...) { __secapiresult=errSecInternalComponent; }
512
513 if (certChain)
514 CFRelease(certChain);
515
516 if (evidenceChain) {
517 if (ix < CFArrayGetCount(evidenceChain)) {
518 certificate = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, ix);
519 // note: we do not retain this certificate. The assumption here is
520 // that the certificate is retained by the trust object, so it is
521 // valid unil the trust is released (or until re-evaluated.)
522 // also note: we do not release the evidenceChain, as it is owned
523 // by the trust object.
524 }
525 }
526 return certificate;
527 }
528
529
530 static CFStringRef kSecCertificateDetailSHA1Digest = CFSTR("SHA1Digest");
531 static CFStringRef kSecCertificateDetailStatusCodes = CFSTR("StatusCodes");
532
533 static void
534 _AppendStatusCode(CFMutableArrayRef array, OSStatus statusCode)
535 {
536 if (!array)
537 return;
538 SInt32 num = statusCode;
539 CFNumberRef numRef = CFNumberCreate(NULL, kCFNumberSInt32Type, &num);
540 if (!numRef)
541 return;
542 CFArrayAppendValue(array, numRef);
543 CFRelease(numRef);
544 }
545
546 CFArrayRef SecTrustCopyDetails(SecTrustRef trust)
547 {
548 // This function returns an array of dictionaries, one per certificate,
549 // holding status info for each certificate in the evaluated chain.
550 //
551 CFIndex count, chainLen = 0;
552 CFArrayRef certChain = NULL;
553 CFMutableArrayRef details = NULL;
554 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
555 OSStatus __secapiresult = errSecSuccess;
556 try {
557 Trust *trustObj = Trust::required(trust);
558 if (trustObj->result() == kSecTrustResultInvalid) {
559 trustObj->evaluate();
560 if (trustObj->result() == kSecTrustResultInvalid)
561 MacOSError::throwMe(errSecTrustNotAvailable);
562 }
563 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
564 }
565 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
566 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
567 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
568 catch (...) { __secapiresult=errSecInternalComponent; }
569
570 if (certChain) {
571 chainLen = CFArrayGetCount(certChain);
572 CFRelease(certChain);
573 }
574 if (statusChain) {
575 details = CFArrayCreateMutable(NULL, chainLen, &kCFTypeArrayCallBacks);
576 for (count = 0; count < chainLen; count++) {
577 CFMutableDictionaryRef certDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
578 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
579 CFMutableArrayRef statusCodes = CFArrayCreateMutable(kCFAllocatorDefault,
580 0, &kCFTypeArrayCallBacks);
581 CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &statusChain[count];
582 CSSM_TP_APPLE_CERT_STATUS statBits = evInfo->StatusBits;
583
584 // translate status bits
585 if (statBits & CSSM_CERT_STATUS_EXPIRED)
586 _AppendStatusCode(statusCodes, errSecCertificateExpired);
587 if (statBits & CSSM_CERT_STATUS_NOT_VALID_YET)
588 _AppendStatusCode(statusCodes, errSecCertificateNotValidYet);
589 if (statBits & CSSM_CERT_STATUS_TRUST_SETTINGS_DENY)
590 _AppendStatusCode(statusCodes, errSecTrustSettingDeny);
591
592 // translate status codes
593 unsigned int i;
594 for (i = 0; i < evInfo->NumStatusCodes; i++) {
595 CSSM_RETURN scode = evInfo->StatusCodes[i];
596 _AppendStatusCode(statusCodes, (OSStatus)scode);
597 }
598
599 CFDictionarySetValue(certDict, kSecCertificateDetailStatusCodes, statusCodes);
600 CFRelease(statusCodes);
601 CFArrayAppendValue(details, certDict);
602 CFRelease(certDict);
603 }
604 }
605 return details;
606 }
607
608 static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix)
609 {
610 CFArrayRef exceptions = NULL;
611 OSStatus __secapiresult = errSecSuccess;
612 try {
613 exceptions = Trust::required(trust)->exceptions();
614 }
615 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
616 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
617 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
618 catch (...) { __secapiresult=errSecInternalComponent; }
619
620 if (!exceptions || ix >= CFArrayGetCount(exceptions))
621 return NULL;
622 CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
623 if (CFGetTypeID(exception) != CFDictionaryGetTypeID())
624 return NULL;
625
626 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
627 if (!certificate)
628 return NULL;
629
630 /* If the exception contains the current certificate's sha1Digest in the
631 kSecCertificateDetailSHA1Digest key then we use it otherwise we ignore it. */
632 CFDataRef sha1Digest = SecCertificateGetSHA1Digest(certificate);
633 CFTypeRef digestValue = CFDictionaryGetValue(exception, kSecCertificateDetailSHA1Digest);
634 if (!digestValue || !CFEqual(sha1Digest, digestValue))
635 exception = NULL;
636
637 return exception;
638 }
639
640 static void SecTrustCheckException(const void *key, const void *value, void *context)
641 {
642 struct SecTrustCheckExceptionContext *cec = (struct SecTrustCheckExceptionContext *)context;
643 if (cec->exception) {
644 CFTypeRef exceptionValue = CFDictionaryGetValue(cec->exception, key);
645 if (!exceptionValue || !CFEqual(value, exceptionValue)) {
646 cec->exceptionNotFound = true;
647 }
648 } else {
649 cec->exceptionNotFound = true;
650 }
651 }
652
653 /* new in 10.9 */
654 CFDataRef SecTrustCopyExceptions(SecTrustRef trust)
655 {
656 CFArrayRef details = SecTrustCopyDetails(trust);
657 CFIndex pathLength = details ? CFArrayGetCount(details) : 0;
658 CFMutableArrayRef exceptions = CFArrayCreateMutable(kCFAllocatorDefault,
659 pathLength, &kCFTypeArrayCallBacks);
660 CFIndex ix;
661 for (ix = 0; ix < pathLength; ++ix) {
662 CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
663 CFIndex detailCount = CFDictionaryGetCount(detail);
664 CFMutableDictionaryRef exception;
665 if (ix == 0 || detailCount > 0) {
666 exception = CFDictionaryCreateMutableCopy(kCFAllocatorDefault,
667 detailCount + 1, detail);
668 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
669 CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
670 if (digest) {
671 CFDictionaryAddValue(exception, kSecCertificateDetailSHA1Digest, digest);
672 }
673 } else {
674 /* Add empty exception dictionaries for non leaf certs which have no exceptions
675 * to save space.
676 */
677 exception = (CFMutableDictionaryRef)CFDictionaryCreate(kCFAllocatorDefault,
678 NULL, NULL, 0,
679 &kCFTypeDictionaryKeyCallBacks,
680 &kCFTypeDictionaryValueCallBacks);
681 }
682 CFArrayAppendValue(exceptions, exception);
683 CFReleaseNull(exception);
684 }
685 CFReleaseSafe(details);
686
687 /* Remove any trailing empty dictionaries to save even more space (we skip the leaf
688 since it will never be empty). */
689 for (ix = pathLength; ix-- > 1;) {
690 CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
691 if (CFDictionaryGetCount(exception) == 0) {
692 CFArrayRemoveValueAtIndex(exceptions, ix);
693 } else {
694 break;
695 }
696 }
697
698 CFDataRef encodedExceptions = CFPropertyListCreateData(kCFAllocatorDefault,
699 exceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL);
700 CFRelease(exceptions);
701
702 return encodedExceptions;
703 }
704
705 /* new in 10.9 */
706 bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions)
707 {
708 CFArrayRef exceptions;
709 exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault,
710 encodedExceptions, kCFPropertyListImmutable, NULL, NULL);
711 if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) {
712 CFRelease(exceptions);
713 exceptions = NULL;
714 }
715
716 OSStatus __secapiresult = errSecSuccess;
717 try {
718 Trust::required(trust)->exceptions(exceptions);
719 }
720 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
721 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
722 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
723 catch (...) { __secapiresult=errSecInternalComponent; }
724
725 /* If there is a valid exception entry for our current leaf we're golden. */
726 if (SecTrustGetExceptionForCertificateAtIndex(trust, 0))
727 return true;
728
729 /* The passed in exceptions didn't match our current leaf, so we discard it. */
730 try {
731 Trust::required(trust)->exceptions(NULL);
732 __secapiresult = errSecSuccess;
733 }
734 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
735 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
736 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
737 catch (...) { __secapiresult=errSecInternalComponent; }
738
739 return false;
740 }
741
742 /* new in 10.9 */
743 CFDictionaryRef
744 SecTrustCopyResult(SecTrustRef trust)
745 {
746 CFDictionaryRef result = NULL;
747 try {
748 result = Trust::required(trust)->results();
749 // merge details into result
750 CFArrayRef details = SecTrustCopyDetails(trust);
751 if (details) {
752 CFDictionarySetValue((CFMutableDictionaryRef)result,
753 kSecTrustResultDetails, details);
754 CFRelease(details);
755 }
756 }
757 catch (...) {
758 if (result) {
759 CFRelease(result);
760 result = NULL;
761 }
762 }
763 return result;
764 }
765
766 /* new in 10.7 */
767 CFArrayRef
768 SecTrustCopyProperties(SecTrustRef trust)
769 {
770 /* can't use SECAPI macros, since this function does not return OSStatus */
771 CFArrayRef result = NULL;
772 try {
773 result = Trust::required(trust)->properties();
774 }
775 catch (...) {
776 if (result) {
777 CFRelease(result);
778 result = NULL;
779 }
780 }
781 return result;
782 }
783
784
785 /* deprecated in 10.5 */
786 OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors,
787 uint32 *cssmAnchorCount)
788 {
789 BEGIN_SECAPI
790 CertGroup certs;
791 Trust::gStore().getCssmRootCertificates(certs);
792 Required(cssmAnchors) = certs.blobCerts();
793 Required(cssmAnchorCount) = certs.count();
794 END_SECAPI
795 }
796
797
798 //
799 // Get and set user trust settings. Deprecated in 10.5.
800 // User Trust getter, deprecated, works as it always has.
801 //
802 OSStatus SecTrustGetUserTrust(SecCertificateRef certificate,
803 SecPolicyRef policy, SecTrustUserSetting *trustSetting)
804 {
805 BEGIN_SECAPI
806 StorageManager::KeychainList searchList;
807 globals().storageManager.getSearchList(searchList);
808 Required(trustSetting) = Trust::gStore().find(
809 Certificate::required(certificate),
810 Policy::required(policy),
811 searchList);
812 END_SECAPI
813 }
814
815 //
816 // The public setter, also deprecated; it maps to the appropriate
817 // Trust Settings call if possible, else throws errSecUnimplemented.
818 //
819 OSStatus SecTrustSetUserTrust(SecCertificateRef certificate,
820 SecPolicyRef policy, SecTrustUserSetting trustSetting)
821 {
822 SecTrustSettingsResult tsResult = kSecTrustSettingsResultInvalid;
823 OSStatus ortn;
824 Boolean isRoot;
825
826 Policy::required(policy);
827 switch(trustSetting) {
828 case kSecTrustResultProceed:
829 /* different SecTrustSettingsResult depending in root-ness */
830 ortn = SecCertificateIsSelfSigned(certificate, &isRoot);
831 if(ortn) {
832 return ortn;
833 }
834 if(isRoot) {
835 tsResult = kSecTrustSettingsResultTrustRoot;
836 }
837 else {
838 tsResult = kSecTrustSettingsResultTrustAsRoot;
839 }
840 break;
841 case kSecTrustResultDeny:
842 tsResult = kSecTrustSettingsResultDeny;
843 break;
844 default:
845 return errSecUnimplemented;
846 }
847
848 /* make a usage constraints dictionary */
849 CFRef<CFMutableDictionaryRef> usageDict(CFDictionaryCreateMutable(NULL,
850 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
851 CFDictionaryAddValue(usageDict, kSecTrustSettingsPolicy, policy);
852 if(tsResult != kSecTrustSettingsResultTrustRoot) {
853 /* skip if we're specifying the default */
854 SInt32 result = tsResult;
855 CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &result);
856 CFDictionarySetValue(usageDict, kSecTrustSettingsResult, cfNum);
857 CFRelease(cfNum);
858 }
859 return SecTrustSettingsSetTrustSettings(certificate, kSecTrustSettingsDomainUser,
860 usageDict);
861 }
862
863 //
864 // This one is the now-private version of what SecTrustSetUserTrust() used to
865 // be. The public API can no longer manipulate User Trust settings, only
866 // view them.
867 //
868 OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate,
869 SecPolicyRef policy, SecTrustUserSetting trustSetting)
870 {
871 BEGIN_SECAPI
872 switch (trustSetting) {
873 case kSecTrustResultProceed:
874 case kSecTrustResultConfirm:
875 case kSecTrustResultDeny:
876 case kSecTrustResultUnspecified:
877 break;
878 default:
879 MacOSError::throwMe(errSecInvalidTrustSetting);
880 }
881 Trust::gStore().assign(
882 Certificate::required(certificate),
883 Policy::required(policy),
884 trustSetting);
885 END_SECAPI
886 }
887
888 /* SecGetAppleTPHandle - @@@NOT EXPORTED YET; copied from SecurityInterface,
889 but could be useful in the future.
890 */
891 /*
892 CSSM_TP_HANDLE
893 SecGetAppleTPHandle()
894 {
895 BEGIN_SECAPI
896 return TP(gGuidAppleX509TP)->handle();
897 END_SECAPI1(NULL);
898 }
899 */
900
901