]> git.saurik.com Git - apple/security.git/blame - libsecurity_keychain/lib/SecTrust.cpp
Security-55471.14.8.tar.gz
[apple/security.git] / libsecurity_keychain / lib / SecTrust.cpp
CommitLineData
b1ab9ed8 1/*
4d3cab3d 2 * Copyright (c) 2002-2010,2012-2013 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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"
427c49bc 29#include "SecInternal.h"
4d3cab3d 30#include "SecInternalP.h"
b1ab9ed8
A
31#include "SecTrustSettings.h"
32#include "SecCertificatePriv.h"
4d3cab3d
A
33#include "SecCertificateP.h"
34#include "SecCertificatePrivP.h"
b1ab9ed8 35#include <security_utilities/cfutilities.h>
427c49bc 36#include <security_utilities/cfmunge.h>
b1ab9ed8
A
37#include <CoreFoundation/CoreFoundation.h>
38
427c49bc
A
39// forward declarations
40CFArrayRef SecTrustCopyDetails(SecTrustRef trust);
41static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix);
42static void SecTrustCheckException(const void *key, const void *value, void *context);
43
44typedef struct SecTrustCheckExceptionContext {
45 CFDictionaryRef exception;
46 bool exceptionNotFound;
47} SecTrustCheckExceptionContext;
48
49// public trust result constants
50CFTypeRef kSecTrustEvaluationDate = CFSTR("TrustEvaluationDate");
51CFTypeRef kSecTrustExtendedValidation = CFSTR("TrustExtendedValidation");
52CFTypeRef kSecTrustOrganizationName = CFSTR("Organization");
53CFTypeRef kSecTrustResultValue = CFSTR("TrustResultValue");
54CFTypeRef kSecTrustRevocationChecked = CFSTR("TrustRevocationChecked");
55CFTypeRef kSecTrustRevocationValidUntilDate = CFSTR("TrustExpirationDate");
56CFTypeRef kSecTrustResultDetails = CFSTR("TrustResultDetails");
b1ab9ed8
A
57
58//
59// CF boilerplate
60//
61CFTypeID 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//
74OSStatus SecTrustCreateWithCertificates(
427c49bc 75 CFTypeRef certificates,
b1ab9ed8
A
76 CFTypeRef policies,
77 SecTrustRef *trustRef)
78{
427c49bc 79 BEGIN_SECAPI
b1ab9ed8 80 Required(trustRef);
427c49bc
A
81 *trustRef = (new Trust(certificates, policies))->handle();
82 END_SECAPI
b1ab9ed8
A
83}
84
85OSStatus
86SecTrustSetPolicies(SecTrustRef trustRef, CFTypeRef policies)
87{
88 BEGIN_SECAPI
89 Trust::required(trustRef)->policies(policies);
90 END_SECAPI
91}
92
93OSStatus
94SecTrustSetOptions(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
111OSStatus 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
124OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, CFArrayRef anchorCertificates)
125{
126 BEGIN_SECAPI
127 Trust::required(trust)->anchors(anchorCertificates);
128 END_SECAPI
129}
130
131OSStatus 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
139OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray)
140{
427c49bc
A
141 BEGIN_SECAPI
142 StorageManager::KeychainList keychains;
b1ab9ed8
A
143 // avoid unnecessary global initializations if an empty array is passed in
144 if (!( (keychainOrArray != NULL) &&
427c49bc
A
145 (CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) &&
146 (CFArrayGetCount((CFArrayRef)keychainOrArray) == 0) )) {
b1ab9ed8
A
147 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
148 }
427c49bc
A
149 Trust::required(trust)->searchLibs(keychains);
150 END_SECAPI
b1ab9ed8
A
151}
152
153
154OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate)
155{
156 BEGIN_SECAPI
157 Trust::required(trust)->time(verifyDate);
158 END_SECAPI
159}
160
161
162CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust)
163{
164 CFAbsoluteTime verifyTime = 0;
427c49bc 165 OSStatus __secapiresult = errSecSuccess;
b1ab9ed8
A
166 try {
167 CFRef<CFDateRef> verifyDate = Trust::required(trust)->time();
168 verifyTime = CFDateGetAbsoluteTime(verifyDate);
b1ab9ed8
A
169 }
170 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
171 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
172 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
173 catch (...) { __secapiresult=errSecInternalComponent; }
174 return verifyTime;
b1ab9ed8
A
175}
176
427c49bc 177
427c49bc 178OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *resultP)
b1ab9ed8 179{
427c49bc
A
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;
b1ab9ed8
A
232}
233
234OSStatus 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();
427c49bc
A
242 SecTrustResultType trustResult = trustObj->result();
243 result(trust, trustResult);
b1ab9ed8
A
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//
255OSStatus 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//
272OSStatus 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//
284OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result)
285{
286 BEGIN_SECAPI
287 Trust *trustObj = Trust::required(trust);
288 if (result == nil)
427c49bc 289 return errSecParam;
b1ab9ed8
A
290 trustObj->extendedResult(*result);
291 END_SECAPI
292}
293
294//
295// Retrieve CSSM-level information for those who want to dig down
296//
297OSStatus 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//
307OSStatus SecTrustGetCssmResultCode(SecTrustRef trustRef, OSStatus *result)
308{
427c49bc
A
309 BEGIN_SECAPI
310 Trust *trust = Trust::required(trustRef);
b1ab9ed8 311 if (trust->result() == kSecTrustResultInvalid)
427c49bc 312 return errSecParam;
b1ab9ed8
A
313 else
314 Required(result) = trust->cssmResultCode();
427c49bc 315 END_SECAPI
b1ab9ed8
A
316}
317
318OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle)
319{
427c49bc
A
320 BEGIN_SECAPI
321 Required(handle) = Trust::required(trust)->getTPHandle();
322 END_SECAPI
b1ab9ed8
A
323}
324
325OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies)
326{
427c49bc
A
327 BEGIN_SECAPI
328 CFArrayRef currentPolicies = Trust::required(trust)->policies();
b1ab9ed8
A
329 if (currentPolicies != NULL)
330 {
331 CFRetain(currentPolicies);
332 }
333
427c49bc
A
334 Required(policies) = currentPolicies;
335 END_SECAPI
336}
337
338OSStatus 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
348OSStatus 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
365OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData)
366{
367 BEGIN_SECAPI
368 Trust::required(trust)->responses(responseData);
369 END_SECAPI
b1ab9ed8
A
370}
371
372OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchorCertificates)
373{
427c49bc
A
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
b1ab9ed8
A
379}
380
381//
382// Get the user's default anchor certificate set
383//
384OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchorCertificates)
385{
427c49bc 386 BEGIN_SECAPI
b1ab9ed8
A
387
388 return SecTrustSettingsCopyUnrestrictedRoots(
427c49bc
A
389 true, true, true, /* all domains */
390 anchorCertificates);
b1ab9ed8 391
427c49bc 392 END_SECAPI
b1ab9ed8
A
393}
394
395/* new in 10.6 */
396SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust)
397{
398 SecKeyRef pubKey = NULL;
399 CFArrayRef certChain = NULL;
400 CFArrayRef evidenceChain = NULL;
401 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
427c49bc 402 OSStatus __secapiresult = errSecSuccess;
b1ab9ed8
A
403 try {
404 Trust *trustObj = Trust::required(trust);
405 if (trustObj->result() == kSecTrustResultInvalid)
406 MacOSError::throwMe(errSecTrustNotAvailable);
407 if (trustObj->evidence() == nil)
408 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
409 evidenceChain = trustObj->evidence();
b1ab9ed8
A
410 }
411 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
412 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
413 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
414 catch (...) { __secapiresult=errSecInternalComponent; }
b1ab9ed8
A
415
416 if (certChain)
417 CFRelease(certChain);
418
419 if (evidenceChain) {
420 if (CFArrayGetCount(evidenceChain) > 0) {
421 SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, 0);
422 __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey);
423 }
424 // do not release evidenceChain, as it is owned by the trust object.
425 }
427c49bc 426 return pubKey;
b1ab9ed8
A
427}
428
429/* new in 10.6 */
430CFIndex SecTrustGetCertificateCount(SecTrustRef trust)
431{
432 CFIndex chainLen = 0;
433 CFArrayRef certChain = NULL;
434 CFArrayRef evidenceChain = NULL;
435 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
427c49bc 436 OSStatus __secapiresult = errSecSuccess;
b1ab9ed8
A
437 try {
438 Trust *trustObj = Trust::required(trust);
427c49bc
A
439 if (trustObj->result() == kSecTrustResultInvalid) {
440 trustObj->evaluate();
441 if (trustObj->result() == kSecTrustResultInvalid)
442 MacOSError::throwMe(errSecTrustNotAvailable);
443 }
b1ab9ed8
A
444 if (trustObj->evidence() == nil)
445 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
446 evidenceChain = trustObj->evidence();
b1ab9ed8
A
447 }
448 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
449 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
450 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
451 catch (...) { __secapiresult=errSecInternalComponent; }
b1ab9ed8
A
452
453 if (certChain)
454 CFRelease(certChain);
455
456 if (evidenceChain)
457 chainLen = CFArrayGetCount(evidenceChain); // don't release, trust object owns it.
458
459 return chainLen;
460}
461
462/* new in 10.6 */
463SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix)
464{
465 SecCertificateRef certificate = NULL;
466 CFArrayRef certChain = NULL;
467 CFArrayRef evidenceChain = NULL;
468 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
427c49bc 469 OSStatus __secapiresult = errSecSuccess;
b1ab9ed8
A
470 try {
471 Trust *trustObj = Trust::required(trust);
427c49bc
A
472 if (trustObj->result() == kSecTrustResultInvalid) {
473 trustObj->evaluate();
474 if (trustObj->result() == kSecTrustResultInvalid)
475 MacOSError::throwMe(errSecTrustNotAvailable);
476 }
b1ab9ed8
A
477 if (trustObj->evidence() == nil)
478 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
479 evidenceChain = trustObj->evidence();
b1ab9ed8
A
480 }
481 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
482 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
483 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
484 catch (...) { __secapiresult=errSecInternalComponent; }
b1ab9ed8
A
485
486 if (certChain)
487 CFRelease(certChain);
488
489 if (evidenceChain) {
490 if (ix < CFArrayGetCount(evidenceChain)) {
491 certificate = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, ix);
492 // note: we do not retain this certificate. The assumption here is
493 // that the certificate is retained by the trust object, so it is
494 // valid unil the trust is released (or until re-evaluated.)
495 // also note: we do not release the evidenceChain, as it is owned
496 // by the trust object.
497 }
498 }
499 return certificate;
500}
501
427c49bc
A
502
503static CFStringRef kSecCertificateDetailSHA1Digest = CFSTR("SHA1Digest");
504static CFStringRef kSecCertificateDetailStatusCodes = CFSTR("StatusCodes");
505
506static void
507_AppendStatusCode(CFMutableArrayRef array, OSStatus statusCode)
508{
509 if (!array)
510 return;
511 SInt32 num = statusCode;
512 CFNumberRef numRef = CFNumberCreate(NULL, kCFNumberSInt32Type, &num);
513 if (!numRef)
514 return;
515 CFArrayAppendValue(array, numRef);
516 CFRelease(numRef);
517}
518
519CFArrayRef SecTrustCopyDetails(SecTrustRef trust)
520{
521 // This function returns an array of dictionaries, one per certificate,
522 // holding status info for each certificate in the evaluated chain.
523 //
524 CFIndex count, chainLen = 0;
525 CFArrayRef certChain = NULL;
526 CFMutableArrayRef details = NULL;
527 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
528 OSStatus __secapiresult = errSecSuccess;
529 try {
530 Trust *trustObj = Trust::required(trust);
531 if (trustObj->result() == kSecTrustResultInvalid) {
532 trustObj->evaluate();
533 if (trustObj->result() == kSecTrustResultInvalid)
534 MacOSError::throwMe(errSecTrustNotAvailable);
535 }
536 trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain));
537 }
538 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
539 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
540 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
541 catch (...) { __secapiresult=errSecInternalComponent; }
542
543 if (certChain) {
544 chainLen = CFArrayGetCount(certChain);
545 CFRelease(certChain);
546 }
547 if (statusChain) {
548 details = CFArrayCreateMutable(NULL, chainLen, &kCFTypeArrayCallBacks);
549 for (count = 0; count < chainLen; count++) {
550 CFMutableDictionaryRef certDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
551 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
552 CFMutableArrayRef statusCodes = CFArrayCreateMutable(kCFAllocatorDefault,
553 0, &kCFTypeArrayCallBacks);
554 CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &statusChain[count];
555 CSSM_TP_APPLE_CERT_STATUS statBits = evInfo->StatusBits;
556
557 // translate status bits
558 if (statBits & CSSM_CERT_STATUS_EXPIRED)
559 _AppendStatusCode(statusCodes, errSecCertificateExpired);
560 if (statBits & CSSM_CERT_STATUS_NOT_VALID_YET)
561 _AppendStatusCode(statusCodes, errSecCertificateNotValidYet);
562 if (statBits & CSSM_CERT_STATUS_TRUST_SETTINGS_DENY)
563 _AppendStatusCode(statusCodes, errSecTrustSettingDeny);
564
565 // translate status codes
566 unsigned int i;
567 for (i = 0; i < evInfo->NumStatusCodes; i++) {
568 CSSM_RETURN scode = evInfo->StatusCodes[i];
569 _AppendStatusCode(statusCodes, (OSStatus)scode);
570 }
571
572 CFDictionarySetValue(certDict, kSecCertificateDetailStatusCodes, statusCodes);
573 CFRelease(statusCodes);
574 CFArrayAppendValue(details, certDict);
575 CFRelease(certDict);
576 }
577 }
578 return details;
579}
580
581static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix)
582{
583 CFArrayRef exceptions = NULL;
584 OSStatus __secapiresult = errSecSuccess;
585 try {
586 exceptions = Trust::required(trust)->exceptions();
587 }
588 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
589 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
590 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
591 catch (...) { __secapiresult=errSecInternalComponent; }
592
593 if (!exceptions || ix >= CFArrayGetCount(exceptions))
594 return NULL;
595 CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
596 if (CFGetTypeID(exception) != CFDictionaryGetTypeID())
597 return NULL;
598
599 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
600 if (!certificate)
601 return NULL;
602
603 /* If the exception contains the current certificate's sha1Digest in the
604 kSecCertificateDetailSHA1Digest key then we use it otherwise we ignore it. */
605 CFDataRef sha1Digest = SecCertificateGetSHA1Digest(certificate);
606 CFTypeRef digestValue = CFDictionaryGetValue(exception, kSecCertificateDetailSHA1Digest);
607 if (!digestValue || !CFEqual(sha1Digest, digestValue))
608 exception = NULL;
609
610 return exception;
611}
612
613static void SecTrustCheckException(const void *key, const void *value, void *context)
614{
615 struct SecTrustCheckExceptionContext *cec = (struct SecTrustCheckExceptionContext *)context;
616 if (cec->exception) {
617 CFTypeRef exceptionValue = CFDictionaryGetValue(cec->exception, key);
618 if (!exceptionValue || !CFEqual(value, exceptionValue)) {
619 cec->exceptionNotFound = true;
620 }
621 } else {
622 cec->exceptionNotFound = true;
623 }
624}
625
626/* new in 10.9 */
627CFDataRef SecTrustCopyExceptions(SecTrustRef trust)
628{
629 CFArrayRef details = SecTrustCopyDetails(trust);
630 CFIndex pathLength = details ? CFArrayGetCount(details) : 0;
631 CFMutableArrayRef exceptions = CFArrayCreateMutable(kCFAllocatorDefault,
632 pathLength, &kCFTypeArrayCallBacks);
633 CFIndex ix;
634 for (ix = 0; ix < pathLength; ++ix) {
635 CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
636 CFIndex detailCount = CFDictionaryGetCount(detail);
637 CFMutableDictionaryRef exception;
638 if (ix == 0 || detailCount > 0) {
639 exception = CFDictionaryCreateMutableCopy(kCFAllocatorDefault,
640 detailCount + 1, detail);
641 SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix);
642 CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
643 if (digest) {
644 CFDictionaryAddValue(exception, kSecCertificateDetailSHA1Digest, digest);
645 }
646 } else {
647 /* Add empty exception dictionaries for non leaf certs which have no exceptions
648 * to save space.
649 */
650 exception = (CFMutableDictionaryRef)CFDictionaryCreate(kCFAllocatorDefault,
651 NULL, NULL, 0,
652 &kCFTypeDictionaryKeyCallBacks,
653 &kCFTypeDictionaryValueCallBacks);
654 }
655 CFArrayAppendValue(exceptions, exception);
656 CFReleaseNull(exception);
657 }
658 CFReleaseSafe(details);
659
660 /* Remove any trailing empty dictionaries to save even more space (we skip the leaf
661 since it will never be empty). */
662 for (ix = pathLength; ix-- > 1;) {
663 CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix);
664 if (CFDictionaryGetCount(exception) == 0) {
665 CFArrayRemoveValueAtIndex(exceptions, ix);
666 } else {
667 break;
668 }
669 }
670
671 CFDataRef encodedExceptions = CFPropertyListCreateData(kCFAllocatorDefault,
672 exceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL);
673 CFRelease(exceptions);
674
675 return encodedExceptions;
676}
677
678/* new in 10.9 */
679bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions)
680{
681 CFArrayRef exceptions;
682 exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault,
683 encodedExceptions, kCFPropertyListImmutable, NULL, NULL);
684 if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) {
685 CFRelease(exceptions);
686 exceptions = NULL;
687 }
688
689 OSStatus __secapiresult = errSecSuccess;
690 try {
691 Trust::required(trust)->exceptions(exceptions);
692 }
693 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
694 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
695 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
696 catch (...) { __secapiresult=errSecInternalComponent; }
697
698 /* If there is a valid exception entry for our current leaf we're golden. */
699 if (SecTrustGetExceptionForCertificateAtIndex(trust, 0))
700 return true;
701
702 /* The passed in exceptions didn't match our current leaf, so we discard it. */
703 try {
704 Trust::required(trust)->exceptions(NULL);
705 __secapiresult = errSecSuccess;
706 }
707 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
708 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
709 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
710 catch (...) { __secapiresult=errSecInternalComponent; }
711
712 return false;
713}
714
715/* new in 10.9 */
716CFDictionaryRef
717SecTrustCopyResult(SecTrustRef trust)
718{
719 CFDictionaryRef result = NULL;
720 try {
721 result = Trust::required(trust)->results();
722 // merge details into result
723 CFArrayRef details = SecTrustCopyDetails(trust);
724 if (details) {
725 CFDictionarySetValue((CFMutableDictionaryRef)result,
726 kSecTrustResultDetails, details);
727 CFRelease(details);
728 }
729 }
730 catch (...) {
731 if (result) {
732 CFRelease(result);
733 result = NULL;
734 }
735 }
736 return result;
737}
738
b1ab9ed8
A
739/* new in 10.7 */
740CFArrayRef
741SecTrustCopyProperties(SecTrustRef trust)
742{
743 /* can't use SECAPI macros, since this function does not return OSStatus */
744 CFArrayRef result = NULL;
745 try {
746 result = Trust::required(trust)->properties();
747 }
748 catch (...) {
749 if (result) {
750 CFRelease(result);
751 result = NULL;
752 }
427c49bc 753 }
b1ab9ed8
A
754 return result;
755}
756
757
758/* deprecated in 10.5 */
759OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors,
760 uint32 *cssmAnchorCount)
761{
762 BEGIN_SECAPI
763 CertGroup certs;
764 Trust::gStore().getCssmRootCertificates(certs);
765 Required(cssmAnchors) = certs.blobCerts();
766 Required(cssmAnchorCount) = certs.count();
767 END_SECAPI
768}
769
770
771//
772// Get and set user trust settings. Deprecated in 10.5.
773// User Trust getter, deprecated, works as it always has.
774//
775OSStatus SecTrustGetUserTrust(SecCertificateRef certificate,
776 SecPolicyRef policy, SecTrustUserSetting *trustSetting)
777{
778 BEGIN_SECAPI
779 StorageManager::KeychainList searchList;
780 globals().storageManager.getSearchList(searchList);
781 Required(trustSetting) = Trust::gStore().find(
782 Certificate::required(certificate),
783 Policy::required(policy),
784 searchList);
785 END_SECAPI
786}
787
788//
789// The public setter, also deprecated; it maps to the appropriate
427c49bc 790// Trust Settings call if possible, else throws errSecUnimplemented.
b1ab9ed8
A
791//
792OSStatus SecTrustSetUserTrust(SecCertificateRef certificate,
793 SecPolicyRef policy, SecTrustUserSetting trustSetting)
794{
795 SecTrustSettingsResult tsResult = kSecTrustSettingsResultInvalid;
796 OSStatus ortn;
797 Boolean isRoot;
798
799 Policy::required(policy);
800 switch(trustSetting) {
801 case kSecTrustResultProceed:
802 /* different SecTrustSettingsResult depending in root-ness */
803 ortn = SecCertificateIsSelfSigned(certificate, &isRoot);
804 if(ortn) {
805 return ortn;
806 }
807 if(isRoot) {
808 tsResult = kSecTrustSettingsResultTrustRoot;
809 }
810 else {
811 tsResult = kSecTrustSettingsResultTrustAsRoot;
812 }
813 break;
814 case kSecTrustResultDeny:
815 tsResult = kSecTrustSettingsResultDeny;
816 break;
817 default:
427c49bc 818 return errSecUnimplemented;
b1ab9ed8
A
819 }
820
821 /* make a usage constraints dictionary */
822 CFRef<CFMutableDictionaryRef> usageDict(CFDictionaryCreateMutable(NULL,
823 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
824 CFDictionaryAddValue(usageDict, kSecTrustSettingsPolicy, policy);
825 if(tsResult != kSecTrustSettingsResultTrustRoot) {
826 /* skip if we're specifying the default */
827 SInt32 result = tsResult;
828 CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &result);
829 CFDictionarySetValue(usageDict, kSecTrustSettingsResult, cfNum);
830 CFRelease(cfNum);
831 }
832 return SecTrustSettingsSetTrustSettings(certificate, kSecTrustSettingsDomainUser,
833 usageDict);
834}
835
836//
837// This one is the now-private version of what SecTrustSetUserTrust() used to
838// be. The public API can no longer manipulate User Trust settings, only
839// view them.
840//
841OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate,
842 SecPolicyRef policy, SecTrustUserSetting trustSetting)
843{
844 BEGIN_SECAPI
845 switch (trustSetting) {
846 case kSecTrustResultProceed:
847 case kSecTrustResultConfirm:
848 case kSecTrustResultDeny:
849 case kSecTrustResultUnspecified:
850 break;
851 default:
852 MacOSError::throwMe(errSecInvalidTrustSetting);
853 }
854 Trust::gStore().assign(
855 Certificate::required(certificate),
856 Policy::required(policy),
857 trustSetting);
858 END_SECAPI
859}
860
861/* SecGetAppleTPHandle - @@@NOT EXPORTED YET; copied from SecurityInterface,
862 but could be useful in the future.
863*/
864/*
865CSSM_TP_HANDLE
866SecGetAppleTPHandle()
867{
868 BEGIN_SECAPI
869 return TP(gGuidAppleX509TP)->handle();
870 END_SECAPI1(NULL);
871}
872*/
873
874