2 * Copyright (c) 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@
23 * SecCertificateSource.c - certificate sources for trust evaluation engine
27 #include <CoreFoundation/CoreFoundation.h>
28 #include <AssertMacros.h>
30 #include <CommonCrypto/CommonDigest.h>
32 #include <Security/SecCertificate.h>
33 #include <Security/SecCertificatePriv.h>
34 #include <Security/SecItem.h>
35 #include <Security/SecTrustSettingsPriv.h>
36 #include <Security/SecPolicyInternal.h>
38 #include <utilities/debugging.h>
39 #include <utilities/SecCFWrappers.h>
41 #include <securityd/SecTrustServer.h>
42 #include <securityd/SecItemServer.h>
43 #include <securityd/SecTrustStoreServer.h>
44 #include <securityd/SecCAIssuerRequest.h>
46 #include "OTATrustUtilities.h"
47 #include "SecCertificateSource.h"
49 /********************************************************
50 ***************** OTA Trust support ********************
51 ********************************************************/
54 //#ifndef SECITEM_SHIM_OSX
56 static CFArrayRef
subject_to_anchors(CFDataRef nic
);
57 static CFArrayRef
CopyCertsFromIndices(CFArrayRef offsets
);
59 static CFArrayRef
subject_to_anchors(CFDataRef nic
)
61 CFArrayRef result
= NULL
;
68 SecOTAPKIRef otapkiref
= SecOTAPKICopyCurrentOTAPKIRef();
69 if (NULL
== otapkiref
)
74 CFDictionaryRef lookupTable
= SecOTAPKICopyAnchorLookupTable(otapkiref
);
77 if (NULL
== lookupTable
)
82 unsigned char subject_digest
[CC_SHA1_DIGEST_LENGTH
];
83 memset(subject_digest
, 0, CC_SHA1_DIGEST_LENGTH
);
85 (void)CC_SHA1(CFDataGetBytePtr(nic
), (CC_LONG
)CFDataGetLength(nic
), subject_digest
);
86 CFDataRef sha1Digest
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, subject_digest
, CC_SHA1_DIGEST_LENGTH
, kCFAllocatorNull
);
89 result
= (CFArrayRef
)CFDictionaryGetValue(lookupTable
, sha1Digest
);
90 CFReleaseSafe(lookupTable
);
91 CFReleaseSafe(sha1Digest
);
96 static CFArrayRef
CopyCertDataFromIndices(CFArrayRef offsets
)
98 CFMutableArrayRef result
= NULL
;
100 SecOTAPKIRef otapkiref
= SecOTAPKICopyCurrentOTAPKIRef();
101 if (NULL
== otapkiref
)
106 const char* anchorTable
= SecOTAPKIGetAnchorTable(otapkiref
);
107 if (NULL
== anchorTable
)
109 CFReleaseSafe(otapkiref
);
113 CFIndex num_offsets
= CFArrayGetCount(offsets
);
115 result
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
117 for (CFIndex idx
= 0; idx
< num_offsets
; idx
++)
119 CFNumberRef offset
= (CFNumberRef
)CFArrayGetValueAtIndex(offsets
, idx
);
120 uint32_t offset_value
= 0;
121 if (CFNumberGetValue(offset
, kCFNumberSInt32Type
, &offset_value
))
123 char* pDataPtr
= (char *)(anchorTable
+ offset_value
);
124 //int32_t record_length = *((int32_t * )pDataPtr);
125 //record_length = record_length;
126 pDataPtr
+= sizeof(uint32_t);
128 int32_t cert_data_length
= *((int32_t * )pDataPtr
);
129 pDataPtr
+= sizeof(uint32_t);
131 CFDataRef cert_data
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (const UInt8
*)pDataPtr
,
132 cert_data_length
, kCFAllocatorNull
);
133 if (NULL
!= cert_data
)
135 CFArrayAppendValue(result
, cert_data
);
136 CFReleaseSafe(cert_data
);
140 CFReleaseSafe(otapkiref
);
144 static CFArrayRef
CopyCertsFromIndices(CFArrayRef offsets
)
146 CFMutableArrayRef result
= NULL
;
148 CFArrayRef cert_data_array
= CopyCertDataFromIndices(offsets
);
150 if (NULL
!= cert_data_array
)
152 result
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
153 CFIndex num_cert_datas
= CFArrayGetCount(cert_data_array
);
154 for (CFIndex idx
= 0; idx
< num_cert_datas
; idx
++)
156 CFDataRef cert_data
= (CFDataRef
)CFArrayGetValueAtIndex(cert_data_array
, idx
);
157 if (NULL
!= cert_data
)
159 SecCertificateRef cert
= SecCertificateCreateWithData(kCFAllocatorDefault
, cert_data
);
162 CFArrayAppendValue(result
, cert
);
167 CFRelease(cert_data_array
);
172 //#endif // SECITEM_SHIM_OSX
174 /********************************************************
175 *************** END OTA Trust support ******************
176 ********************************************************/
178 /********************************************************
179 ************ SecCertificateSource object ***************
180 ********************************************************/
182 bool SecCertificateSourceCopyParents(SecCertificateSourceRef source
,
183 SecCertificateRef certificate
,
184 void *context
, SecCertificateSourceParents callback
) {
185 return source
->copyParents(source
, certificate
, context
, callback
);
188 CFArrayRef
SecCertificateSourceCopyUsageConstraints(SecCertificateSourceRef source
,
189 SecCertificateRef certificate
) {
190 if (source
->copyUsageConstraints
) {
191 return source
->copyUsageConstraints(source
, certificate
);
197 bool SecCertificateSourceContains(SecCertificateSourceRef source
,
198 SecCertificateRef certificate
) {
199 return source
->contains(source
, certificate
);
203 // MARK: SecItemCertificateSource
204 /********************************************************
205 *********** SecItemCertificateSource object ************
206 ********************************************************/
207 struct SecItemCertificateSource
{
208 struct SecCertificateSource base
;
209 CFArrayRef accessGroups
;
211 typedef struct SecItemCertificateSource
*SecItemCertificateSourceRef
;
213 static CF_RETURNS_RETAINED CFTypeRef
SecItemCertificateSourceResultsPost(CFTypeRef raw_results
) {
214 if (isArray(raw_results
)) {
215 CFMutableArrayRef result
= CFArrayCreateMutable(kCFAllocatorDefault
, CFArrayGetCount(raw_results
), &kCFTypeArrayCallBacks
);
216 CFArrayForEach(raw_results
, ^(const void *value
) {
217 SecCertificateRef cert
= SecCertificateCreateWithData(kCFAllocatorDefault
, value
);
219 CFArrayAppendValue(result
, cert
);
224 } else if (isData(raw_results
)) {
225 return SecCertificateCreateWithData(kCFAllocatorDefault
, (CFDataRef
)raw_results
);
230 static bool SecItemCertificateSourceCopyParents(
231 SecCertificateSourceRef source
, SecCertificateRef certificate
,
232 void *context
, SecCertificateSourceParents callback
) {
233 SecItemCertificateSourceRef msource
= (SecItemCertificateSourceRef
)source
;
234 /* FIXME: Search for things other than just subject of our issuer if we
235 have a subjectID or authorityKeyIdentifier. */
236 CFDataRef normalizedIssuer
=
237 SecCertificateGetNormalizedIssuerContent(certificate
);
238 const void *keys
[] = {
245 kSecClassCertificate
,
250 CFDictionaryRef query
= CFDictionaryCreate(NULL
, keys
, values
, 4,
252 CFTypeRef results
= NULL
;
253 SecurityClient client
= {
255 .accessGroups
= msource
->accessGroups
,
256 .allowSystemKeychain
= true,
257 .allowSyncBubbleKeychain
= false,
258 .isNetworkExtension
= false,
261 /* We can make this async or run this on a queue now easily. */
262 CFErrorRef localError
= NULL
;
263 if (!_SecItemCopyMatching(query
, &client
, &results
, &localError
)) {
264 if (localError
&& (CFErrorGetCode(localError
) != errSecItemNotFound
)) {
265 secdebug("trust", "_SecItemCopyMatching: %@", localError
);
267 CFReleaseSafe(localError
);
270 CFTypeRef certs
= SecItemCertificateSourceResultsPost(results
);
271 CFReleaseSafe(results
);
272 callback(context
, certs
);
273 CFReleaseSafe(certs
);
277 static bool SecItemCertificateSourceContains(SecCertificateSourceRef source
,
278 SecCertificateRef certificate
) {
279 SecItemCertificateSourceRef msource
= (SecItemCertificateSourceRef
)source
;
280 /* Look up a certificate by issuer and serial number. */
281 CFDataRef normalizedIssuer
= SecCertificateGetNormalizedIssuerContent(certificate
);
282 CFRetainSafe(normalizedIssuer
);
283 CFDataRef serialNumber
=
284 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
285 SecCertificateCopySerialNumber(certificate
, NULL
);
287 SecCertificateCopySerialNumber(certificate
);
289 const void *keys
[] = {
296 kSecClassCertificate
,
301 SecurityClient client
= {
303 .accessGroups
= msource
->accessGroups
,
304 .allowSystemKeychain
= true,
305 .allowSyncBubbleKeychain
= false,
306 .isNetworkExtension
= false,
308 CFDictionaryRef query
= CFDictionaryCreate(NULL
, keys
, values
, 4, NULL
, NULL
);
309 CFErrorRef localError
= NULL
;
310 CFTypeRef results
= NULL
;
311 bool ok
= _SecItemCopyMatching(query
, &client
, &results
, &localError
);
312 CFReleaseSafe(query
);
313 CFReleaseSafe(serialNumber
);
314 CFReleaseSafe(normalizedIssuer
);
315 CFReleaseSafe(results
);
317 if (CFErrorGetCode(localError
) != errSecItemNotFound
) {
318 secdebug("trust", "_SecItemCopyMatching: %@", localError
);
320 CFReleaseSafe(localError
);
326 SecCertificateSourceRef
SecItemCertificateSourceCreate(CFArrayRef accessGroups
) {
327 SecItemCertificateSourceRef result
= (SecItemCertificateSourceRef
)malloc(sizeof(*result
));
328 result
->base
.copyParents
= SecItemCertificateSourceCopyParents
;
329 result
->base
.copyUsageConstraints
= NULL
;
330 result
->base
.contains
= SecItemCertificateSourceContains
;
331 result
->accessGroups
= accessGroups
;
332 CFRetainSafe(accessGroups
);
333 return (SecCertificateSourceRef
)result
;
336 void SecItemCertificateSourceDestroy(SecCertificateSourceRef source
) {
337 SecItemCertificateSourceRef msource
= (SecItemCertificateSourceRef
)source
;
338 CFReleaseSafe(msource
->accessGroups
);
343 // MARK: SecSystemAnchorSource
344 /********************************************************
345 *********** SecSystemAnchorSource object ************
346 ********************************************************/
348 static bool SecSystemAnchorSourceCopyParents(
349 SecCertificateSourceRef source
, SecCertificateRef certificate
,
350 void *context
, SecCertificateSourceParents callback
) {
351 //#ifndef SECITEM_SHIM_OSX
352 CFArrayRef parents
= NULL
;
353 CFArrayRef anchors
= NULL
;
354 SecOTAPKIRef otapkiref
= NULL
;
356 CFDataRef nic
= SecCertificateGetNormalizedIssuerContent(certificate
);
357 /* 64 bits cast: the worst that can happen here is we truncate the length and match an actual anchor.
358 It does not matter since we would be returning the wrong anchors */
359 assert((unsigned long)CFDataGetLength(nic
)<UINT_MAX
); /* Debug check. correct as long as CFIndex is signed long */
361 otapkiref
= SecOTAPKICopyCurrentOTAPKIRef();
362 require_quiet(otapkiref
, errOut
);
363 anchors
= subject_to_anchors(nic
);
364 require_quiet(anchors
, errOut
);
365 parents
= CopyCertsFromIndices(anchors
);
368 callback(context
, parents
);
369 CFReleaseSafe(parents
);
370 CFReleaseSafe(otapkiref
);
371 //#endif // SECITEM_SHIM_OSX
375 static CFArrayRef
SecSystemAnchorSourceCopyUsageConstraints(SecCertificateSourceRef __unused source
,
376 SecCertificateRef __unused certificate
)
378 CFMutableArrayRef result
= NULL
;
379 CFMutableDictionaryRef options
= NULL
, hashConstraint
= NULL
, trustRoot
= NULL
;
380 CFNumberRef trustResult
= NULL
;
382 require_quiet(options
= CFDictionaryCreateMutable(NULL
, 1,
383 &kCFTypeDictionaryKeyCallBacks
,
384 &kCFTypeDictionaryValueCallBacks
),
386 require_quiet(hashConstraint
= CFDictionaryCreateMutable(NULL
, 1,
387 &kCFTypeDictionaryKeyCallBacks
,
388 &kCFTypeDictionaryValueCallBacks
),
390 require_quiet(trustRoot
= CFDictionaryCreateMutable(NULL
, 1,
391 &kCFTypeDictionaryKeyCallBacks
,
392 &kCFTypeDictionaryValueCallBacks
),
395 uint32_t temp
= kSecTrustSettingsResultTrustRoot
;
396 require_quiet(trustResult
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &temp
), out
);
397 CFDictionaryAddValue(trustRoot
, kSecTrustSettingsResult
, trustResult
);
399 CFDictionaryAddValue(options
, kSecPolicyCheckSystemTrustedWeakHash
, kCFBooleanTrue
);
400 CFDictionaryAddValue(hashConstraint
, kSecTrustSettingsPolicyOptions
, options
);
402 require_quiet(result
= CFArrayCreateMutable(NULL
, 2, &kCFTypeArrayCallBacks
), out
);
403 CFArrayAppendValue(result
, hashConstraint
);
404 CFArrayAppendValue(result
, trustRoot
);
407 CFReleaseNull(options
);
408 CFReleaseNull(trustResult
);
409 CFReleaseNull(trustRoot
);
410 CFReleaseNull(hashConstraint
);
414 static bool SecSystemAnchorSourceContains(SecCertificateSourceRef source
,
415 SecCertificateRef certificate
) {
417 CFArrayRef anchors
= NULL
;
418 SecOTAPKIRef otapkiref
= NULL
;
419 CFArrayRef cert_datas
= NULL
;
421 CFDataRef nic
= SecCertificateGetNormalizedSubjectContent(certificate
);
422 /* 64 bits cast: the worst that can happen here is we truncate the length and match an actual anchor.
423 It does not matter since we would be returning the wrong anchors */
424 assert((unsigned long)CFDataGetLength(nic
)<UINT_MAX
); /* Debug check. correct as long as CFIndex is signed long */
426 otapkiref
= SecOTAPKICopyCurrentOTAPKIRef();
427 require_quiet(otapkiref
, errOut
);
428 anchors
= subject_to_anchors(nic
);
429 require_quiet(anchors
, errOut
);
430 cert_datas
= CopyCertDataFromIndices(anchors
);
431 require_quiet(cert_datas
, errOut
);
433 CFIndex cert_length
= SecCertificateGetLength(certificate
);
434 const UInt8
*cert_data_ptr
= SecCertificateGetBytePtr(certificate
);
436 CFIndex num_cert_datas
= CFArrayGetCount(cert_datas
);
437 for (CFIndex idx
= 0; idx
< num_cert_datas
; idx
++)
439 CFDataRef cert_data
= (CFDataRef
)CFArrayGetValueAtIndex(cert_datas
, idx
);
441 if (NULL
!= cert_data
)
443 if (CFGetTypeID(cert_data
) == CFDataGetTypeID())
445 CFIndex aCert_Length
= CFDataGetLength(cert_data
);
446 const UInt8
* aCert_Data_Ptr
= CFDataGetBytePtr(cert_data
);
448 if (aCert_Length
== cert_length
)
450 if (!memcmp(cert_data_ptr
, aCert_Data_Ptr
, cert_length
))
461 CFReleaseSafe(cert_datas
);
462 CFReleaseSafe(otapkiref
);
466 struct SecCertificateSource _kSecSystemAnchorSource
= {
467 SecSystemAnchorSourceCopyParents
,
468 SecSystemAnchorSourceCopyUsageConstraints
,
469 SecSystemAnchorSourceContains
472 const SecCertificateSourceRef kSecSystemAnchorSource
= &_kSecSystemAnchorSource
;
477 // MARK: SecUserAnchorSource
478 /********************************************************
479 ************* SecUserAnchorSource object ***************
480 ********************************************************/
481 static bool SecUserAnchorSourceCopyParents(SecCertificateSourceRef source
, SecCertificateRef certificate
,
482 void *context
, SecCertificateSourceParents callback
) {
483 CFArrayRef parents
= SecTrustStoreCopyParents(SecTrustStoreForDomain(kSecTrustStoreDomainUser
),
485 callback(context
, parents
);
486 CFReleaseSafe(parents
);
490 static CFArrayRef
SecUserAnchorSourceCopyUsageConstraints(SecCertificateSourceRef source
,
491 SecCertificateRef certificate
) {
492 CFDataRef digest
= SecCertificateGetSHA1Digest(certificate
);
495 CFArrayRef usageConstraints
= NULL
;
496 bool ok
= _SecTrustStoreCopyUsageConstraints(SecTrustStoreForDomain(kSecTrustStoreDomainUser
),
497 digest
, &usageConstraints
, NULL
);
498 return (ok
) ? usageConstraints
: NULL
;
501 static bool SecUserAnchorSourceContains(SecCertificateSourceRef source
,
502 SecCertificateRef certificate
) {
503 return SecTrustStoreContains(SecTrustStoreForDomain(kSecTrustStoreDomainUser
),
507 struct SecCertificateSource _kSecUserAnchorSource
= {
508 SecUserAnchorSourceCopyParents
,
509 SecUserAnchorSourceCopyUsageConstraints
,
510 SecUserAnchorSourceContains
513 const SecCertificateSourceRef kSecUserAnchorSource
= &_kSecUserAnchorSource
;
517 // MARK: SecMemoryCertificateSource
518 /********************************************************
519 ********** SecMemoryCertificateSource object ***********
520 ********************************************************/
521 struct SecMemoryCertificateSource
{
522 struct SecCertificateSource base
;
523 CFMutableSetRef certificates
;
524 CFMutableDictionaryRef subjects
;
526 typedef struct SecMemoryCertificateSource
*SecMemoryCertificateSourceRef
;
528 static bool SecMemoryCertificateSourceCopyParents(
529 SecCertificateSourceRef source
, SecCertificateRef certificate
,
530 void *context
, SecCertificateSourceParents callback
) {
531 SecMemoryCertificateSourceRef msource
=
532 (SecMemoryCertificateSourceRef
)source
;
533 CFDataRef normalizedIssuer
=
534 SecCertificateGetNormalizedIssuerContent(certificate
);
535 CFArrayRef parents
= (normalizedIssuer
) ? CFDictionaryGetValue(msource
->subjects
,
536 normalizedIssuer
) : NULL
;
537 /* FIXME filter parents by subjectID if certificate has an
538 authorityKeyIdentifier. */
539 secdebug("trust", "%@ parents -> %@", certificate
, parents
);
540 callback(context
, parents
);
544 static bool SecMemoryCertificateSourceContains(SecCertificateSourceRef source
,
545 SecCertificateRef certificate
) {
546 SecMemoryCertificateSourceRef msource
=
547 (SecMemoryCertificateSourceRef
)source
;
548 return CFSetContainsValue(msource
->certificates
, certificate
);
551 static void dictAddValueToArrayForKey(CFMutableDictionaryRef dict
,
552 const void *key
, const void *value
) {
556 CFMutableArrayRef values
=
557 (CFMutableArrayRef
)CFDictionaryGetValue(dict
, key
);
559 values
= CFArrayCreateMutable(kCFAllocatorDefault
, 0,
560 &kCFTypeArrayCallBacks
);
561 CFDictionaryAddValue(dict
, key
, values
);
566 CFArrayAppendValue(values
, value
);
569 static void SecMemoryCertificateSourceApplierFunction(const void *value
,
571 SecMemoryCertificateSourceRef msource
=
572 (SecMemoryCertificateSourceRef
)context
;
573 SecCertificateRef certificate
= (SecCertificateRef
)value
;
575 /* CFSet's API has no way to combine these 2 operations into 1 sadly. */
576 if (CFSetContainsValue(msource
->certificates
, certificate
))
578 CFSetAddValue(msource
->certificates
, certificate
);
580 CFDataRef key
= SecCertificateGetNormalizedSubjectContent(certificate
);
581 dictAddValueToArrayForKey(msource
->subjects
, key
, value
);
584 SecCertificateSourceRef
SecMemoryCertificateSourceCreate(CFArrayRef certificates
) {
585 SecMemoryCertificateSourceRef result
= (SecMemoryCertificateSourceRef
)
586 malloc(sizeof(*result
));
587 result
->base
.copyParents
= SecMemoryCertificateSourceCopyParents
;
588 result
->base
.copyUsageConstraints
= NULL
;
589 result
->base
.contains
= SecMemoryCertificateSourceContains
;
590 CFIndex count
= CFArrayGetCount(certificates
);
591 result
->certificates
= CFSetCreateMutable(kCFAllocatorDefault
, count
,
592 &kCFTypeSetCallBacks
);
593 result
->subjects
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
594 count
, &kCFTypeDictionaryKeyCallBacks
,
595 &kCFTypeDictionaryValueCallBacks
);
596 CFRange range
= { 0, count
};
597 CFArrayApplyFunction(certificates
, range
,
598 SecMemoryCertificateSourceApplierFunction
, result
);
600 return (SecCertificateSourceRef
)result
;
603 void SecMemoryCertificateSourceDestroy(SecCertificateSourceRef source
) {
604 SecMemoryCertificateSourceRef msource
=
605 (SecMemoryCertificateSourceRef
)source
;
606 CFRelease(msource
->certificates
);
607 CFRelease(msource
->subjects
);
612 // MARK: SecCAIssuerCertificateSource
613 /********************************************************
614 ********* SecCAIssuerCertificateSource object **********
615 ********************************************************/
616 static bool SecCAIssuerCertificateSourceCopyParents(
617 SecCertificateSourceRef source
, SecCertificateRef certificate
,
618 void *context
, SecCertificateSourceParents callback
) {
619 return SecCAIssuerCopyParents(certificate
, SecPathBuilderGetQueue((SecPathBuilderRef
)context
), context
, callback
);
622 static bool SecCAIssuerCertificateSourceContains(
623 SecCertificateSourceRef source
, SecCertificateRef certificate
) {
627 struct SecCertificateSource _kSecCAIssuerSource
= {
628 SecCAIssuerCertificateSourceCopyParents
,
630 SecCAIssuerCertificateSourceContains
633 const SecCertificateSourceRef kSecCAIssuerSource
= &_kSecCAIssuerSource
;
636 #include <Security/SecItemPriv.h>
638 // MARK: SecLegacyCertificateSource
639 /********************************************************
640 ********** SecLegacyCertificateSource object ***********
641 ********************************************************/
643 static bool SecLegacyCertificateSourceCopyParents(
644 SecCertificateSourceRef source
, SecCertificateRef certificate
,
645 void *context
, SecCertificateSourceParents callback
) {
646 CFArrayRef parents
= SecItemCopyParentCertificates(certificate
, NULL
);
647 callback(context
, parents
);
648 CFReleaseSafe(parents
);
652 static bool SecLegacyCertificateSourceContains(
653 SecCertificateSourceRef source
, SecCertificateRef certificate
) {
654 SecCertificateRef cert
= SecItemCopyStoredCertificate(certificate
, NULL
);
655 bool result
= (cert
) ? true : false;
660 struct SecCertificateSource _kSecLegacyCertificateSource
= {
661 SecLegacyCertificateSourceCopyParents
,
663 SecLegacyCertificateSourceContains
666 const SecCertificateSourceRef kSecLegacyCertificateSource
= &_kSecLegacyCertificateSource
;
668 #endif /* SecLegacyCertificateSource */
672 // MARK: SecLegacyAnchorSource
673 /********************************************************
674 ************ SecLegacyAnchorSource object **************
675 ********************************************************/
677 static bool SecLegacyAnchorSourceCopyParents(SecCertificateSourceRef source
, SecCertificateRef certificate
,
678 void *context
, SecCertificateSourceParents callback
) {
679 CFMutableArrayRef anchors
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
680 CFArrayRef parents
= SecItemCopyParentCertificates(certificate
, NULL
);
681 CFArrayRef trusted
= NULL
;
682 if (parents
== NULL
) {
685 /* Get the custom anchors which have been trusted in the user and admin domains.
686 * We don't need system domain roots here, since SecSystemAnchorSource provides those.
688 OSStatus status
= SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted
);
689 if (status
== errSecSuccess
&& trusted
) {
690 CFIndex index
, count
= CFArrayGetCount(parents
);
691 for (index
= 0; index
< count
; index
++) {
692 SecCertificateRef parent
= (SecCertificateRef
)CFArrayGetValueAtIndex(parents
, index
);
693 if (parent
&& CFArrayContainsValue(trusted
, CFRangeMake(0, CFArrayGetCount(trusted
)), parent
)) {
694 CFArrayAppendValue(anchors
, parent
);
700 callback(context
, anchors
);
701 CFReleaseSafe(anchors
);
702 CFReleaseSafe(parents
);
703 CFReleaseSafe(trusted
);
707 static CFArrayRef
SecLegacyAnchorSourceCopyUsageConstraints(SecCertificateSourceRef source
,
708 SecCertificateRef certificate
) {
709 CFArrayRef result
= NULL
;
710 CFArrayRef userTrustSettings
= NULL
, adminTrustSettings
= NULL
;
712 OSStatus status
= SecTrustSettingsCopyTrustSettings(certificate
,
713 kSecTrustSettingsDomainUser
,
715 if ((status
== errSecSuccess
) && (userTrustSettings
!= NULL
)) {
716 result
= CFRetain(userTrustSettings
);
719 status
= SecTrustSettingsCopyTrustSettings(certificate
,
720 kSecTrustSettingsDomainAdmin
,
721 &adminTrustSettings
);
722 /* user trust settings overrule admin trust settings */
723 if ((status
== errSecSuccess
) && (adminTrustSettings
!= NULL
) && (result
== NULL
)) {
724 result
= CFRetain(adminTrustSettings
);
727 CFReleaseNull(userTrustSettings
);
728 CFReleaseNull(adminTrustSettings
);
732 static bool SecLegacyAnchorSourceContains(SecCertificateSourceRef source
,
733 SecCertificateRef certificate
) {
734 if (certificate
== NULL
) {
737 CFArrayRef trusted
= NULL
;
739 OSStatus status
= SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted
);
740 if ((status
== errSecSuccess
) && (trusted
!= NULL
)) {
741 CFIndex index
, count
= CFArrayGetCount(trusted
);
742 for (index
= 0; index
< count
; index
++) {
743 SecCertificateRef anchor
= (SecCertificateRef
)CFArrayGetValueAtIndex(trusted
, index
);
744 if (anchor
&& CFEqual(anchor
, certificate
)) {
750 CFReleaseSafe(trusted
);
754 struct SecCertificateSource _kSecLegacyAnchorSource
= {
755 SecLegacyAnchorSourceCopyParents
,
756 SecLegacyAnchorSourceCopyUsageConstraints
,
757 SecLegacyAnchorSourceContains
760 const SecCertificateSourceRef kSecLegacyAnchorSource
= &_kSecLegacyAnchorSource
;
762 #endif /* SecLegacyAnchorSource */