]> git.saurik.com Git - apple/security.git/blob - OSX/sec/securityd/SecCertificateSource.c
Security-58286.41.2.tar.gz
[apple/security.git] / OSX / sec / securityd / SecCertificateSource.c
1 /*
2 * Copyright (c) 2016-2017 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 * SecCertificateSource.c - certificate sources for trust evaluation engine
24 *
25 */
26
27 #include <CoreFoundation/CoreFoundation.h>
28 #include <AssertMacros.h>
29
30 #include <CommonCrypto/CommonDigest.h>
31
32 #include <Security/SecCertificate.h>
33 #include <Security/SecCertificatePriv.h>
34 #include <Security/SecItem.h>
35 #include <Security/SecItemInternal.h>
36 #include <Security/SecTrustSettingsPriv.h>
37 #include <Security/SecPolicyInternal.h>
38
39 #include <utilities/debugging.h>
40 #include <utilities/SecCFWrappers.h>
41
42 #include <securityd/SecTrustServer.h>
43 #include <securityd/SecItemServer.h>
44 #include <securityd/SecTrustStoreServer.h>
45 #include <securityd/SecCAIssuerRequest.h>
46
47 #include "OTATrustUtilities.h"
48 #include "SecCertificateSource.h"
49
50 /********************************************************
51 ***************** OTA Trust support ********************
52 ********************************************************/
53
54
55 //#ifndef SECITEM_SHIM_OSX
56
57 static CFArrayRef subject_to_anchors(CFDataRef nic);
58 static CFArrayRef CopyCertsFromIndices(CFArrayRef offsets);
59
60 static CFArrayRef subject_to_anchors(CFDataRef nic)
61 {
62 CFArrayRef result = NULL;
63
64 if (NULL == nic)
65 {
66 return result;
67 }
68
69 SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef();
70 if (NULL == otapkiref)
71 {
72 return result;
73 }
74
75 CFDictionaryRef lookupTable = SecOTAPKICopyAnchorLookupTable(otapkiref);
76 CFRelease(otapkiref);
77
78 if (NULL == lookupTable)
79 {
80 return result;
81 }
82
83 unsigned char subject_digest[CC_SHA1_DIGEST_LENGTH];
84 memset(subject_digest, 0, CC_SHA1_DIGEST_LENGTH);
85
86 (void)CC_SHA1(CFDataGetBytePtr(nic), (CC_LONG)CFDataGetLength(nic), subject_digest);
87 CFDataRef sha1Digest = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, subject_digest, CC_SHA1_DIGEST_LENGTH, kCFAllocatorNull);
88
89
90 result = (CFArrayRef)CFDictionaryGetValue(lookupTable, sha1Digest);
91 CFReleaseSafe(lookupTable);
92 CFReleaseSafe(sha1Digest);
93
94 return result;
95 }
96
97 static CFArrayRef CopyCertDataFromIndices(CFArrayRef offsets)
98 {
99 CFMutableArrayRef result = NULL;
100
101 SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef();
102 if (NULL == otapkiref)
103 {
104 return result;
105 }
106
107 const char* anchorTable = SecOTAPKIGetAnchorTable(otapkiref);
108 if (NULL == anchorTable)
109 {
110 CFReleaseSafe(otapkiref);
111 return result;
112 }
113
114 CFIndex num_offsets = CFArrayGetCount(offsets);
115
116 result = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
117
118 for (CFIndex idx = 0; idx < num_offsets; idx++)
119 {
120 CFNumberRef offset = (CFNumberRef)CFArrayGetValueAtIndex(offsets, idx);
121 uint32_t offset_value = 0;
122 if (CFNumberGetValue(offset, kCFNumberSInt32Type, &offset_value))
123 {
124 char* pDataPtr = (char *)(anchorTable + offset_value);
125 //int32_t record_length = *((int32_t * )pDataPtr);
126 //record_length = record_length;
127 pDataPtr += sizeof(uint32_t);
128
129 int32_t cert_data_length = *((int32_t * )pDataPtr);
130 pDataPtr += sizeof(uint32_t);
131
132 CFDataRef cert_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)pDataPtr,
133 cert_data_length, kCFAllocatorNull);
134 if (NULL != cert_data)
135 {
136 CFArrayAppendValue(result, cert_data);
137 CFReleaseSafe(cert_data);
138 }
139 }
140 }
141 CFReleaseSafe(otapkiref);
142 return result;
143 }
144
145 static CFArrayRef CopyCertsFromIndices(CFArrayRef offsets)
146 {
147 CFMutableArrayRef result = NULL;
148
149 CFArrayRef cert_data_array = CopyCertDataFromIndices(offsets);
150
151 if (NULL != cert_data_array)
152 {
153 result = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
154 CFIndex num_cert_datas = CFArrayGetCount(cert_data_array);
155 for (CFIndex idx = 0; idx < num_cert_datas; idx++)
156 {
157 CFDataRef cert_data = (CFDataRef)CFArrayGetValueAtIndex(cert_data_array, idx);
158 if (NULL != cert_data)
159 {
160 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, cert_data);
161 if (NULL != cert)
162 {
163 CFArrayAppendValue(result, cert);
164 CFRelease(cert);
165 }
166 }
167 }
168 CFRelease(cert_data_array);
169 }
170 return result;
171
172 }
173 //#endif // SECITEM_SHIM_OSX
174
175 /********************************************************
176 *************** END OTA Trust support ******************
177 ********************************************************/
178
179 /********************************************************
180 ************ SecCertificateSource object ***************
181 ********************************************************/
182
183 bool SecCertificateSourceCopyParents(SecCertificateSourceRef source,
184 SecCertificateRef certificate,
185 void *context, SecCertificateSourceParents callback) {
186 return source->copyParents(source, certificate, context, callback);
187 }
188
189 CFArrayRef SecCertificateSourceCopyUsageConstraints(SecCertificateSourceRef source,
190 SecCertificateRef certificate) {
191 if (source->copyUsageConstraints) {
192 return source->copyUsageConstraints(source, certificate);
193 } else {
194 return NULL;
195 }
196 }
197
198 bool SecCertificateSourceContains(SecCertificateSourceRef source,
199 SecCertificateRef certificate) {
200 return source->contains(source, certificate);
201 }
202
203 // MARK: -
204 // MARK: SecItemCertificateSource
205 /********************************************************
206 *********** SecItemCertificateSource object ************
207 ********************************************************/
208 struct SecItemCertificateSource {
209 struct SecCertificateSource base;
210 CFArrayRef accessGroups;
211 };
212 typedef struct SecItemCertificateSource *SecItemCertificateSourceRef;
213
214 static CF_RETURNS_RETAINED CFArrayRef _Nullable SecItemCertificateSourceResultsPost(CFTypeRef raw_results) {
215 CFMutableArrayRef result = NULL;
216 if (isArray(raw_results)) {
217 result = CFArrayCreateMutable(kCFAllocatorDefault, CFArrayGetCount(raw_results), &kCFTypeArrayCallBacks);
218 CFArrayForEach(raw_results, ^(const void *value) {
219 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, value);
220 if (cert) {
221 CFArrayAppendValue(result, cert);
222 CFRelease(cert);
223 }
224 });
225 } else if (isData(raw_results)) {
226 result = CFArrayCreateMutable(kCFAllocatorDefault, CFArrayGetCount(raw_results), &kCFTypeArrayCallBacks);
227 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)raw_results);
228 if (cert) {
229 CFArrayAppendValue(result, cert);
230 CFRelease(cert);
231 }
232 }
233 return result;
234 }
235
236 static bool SecItemCertificateSourceCopyParents(
237 SecCertificateSourceRef source, SecCertificateRef certificate,
238 void *context, SecCertificateSourceParents callback) {
239 SecItemCertificateSourceRef msource = (SecItemCertificateSourceRef)source;
240 CFDataRef normalizedIssuer = SecCertificateGetNormalizedIssuerContent(certificate);
241
242 CFErrorRef localError = NULL;
243 CFArrayRef results = SecItemCopyParentCertificates_ios(normalizedIssuer, msource->accessGroups, &localError);
244 if (!results) {
245 if (localError && (CFErrorGetCode(localError) != errSecItemNotFound)) {
246 secdebug("trust", "SecItemCopyParentCertificates_ios: %@", localError);
247 }
248 CFReleaseSafe(localError);
249 }
250 CFArrayRef certs = SecItemCertificateSourceResultsPost(results);
251 CFReleaseSafe(results);
252 callback(context, certs);
253 CFReleaseSafe(certs);
254 return true;
255 }
256
257 static bool SecItemCertificateSourceContains(SecCertificateSourceRef source,
258 SecCertificateRef certificate) {
259 SecItemCertificateSourceRef msource = (SecItemCertificateSourceRef)source;
260 /* Look up a certificate by issuer and serial number. */
261 CFDataRef normalizedIssuer = SecCertificateGetNormalizedIssuerContent(certificate);
262 CFRetainSafe(normalizedIssuer);
263 CFDataRef serialNumber =
264 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
265 SecCertificateCopySerialNumber(certificate, NULL);
266 #else
267 SecCertificateCopySerialNumber(certificate);
268 #endif
269 CFErrorRef localError = NULL;
270 bool result = SecItemCertificateExists(normalizedIssuer, serialNumber, msource->accessGroups, &localError);
271 if (localError) {
272 if (CFErrorGetCode(localError) != errSecItemNotFound) {
273 secdebug("trust", "SecItemCertificateExists_ios: %@", localError);
274 }
275 CFReleaseSafe(localError);
276 }
277 CFReleaseSafe(serialNumber);
278 CFReleaseSafe(normalizedIssuer);
279 return result;
280 }
281
282 SecCertificateSourceRef SecItemCertificateSourceCreate(CFArrayRef accessGroups) {
283 SecItemCertificateSourceRef result = (SecItemCertificateSourceRef)malloc(sizeof(*result));
284 result->base.copyParents = SecItemCertificateSourceCopyParents;
285 result->base.copyUsageConstraints = NULL;
286 result->base.contains = SecItemCertificateSourceContains;
287 result->accessGroups = accessGroups;
288 CFRetainSafe(accessGroups);
289 return (SecCertificateSourceRef)result;
290 }
291
292 void SecItemCertificateSourceDestroy(SecCertificateSourceRef source) {
293 SecItemCertificateSourceRef msource = (SecItemCertificateSourceRef)source;
294 CFReleaseSafe(msource->accessGroups);
295 free(msource);
296 }
297
298 // MARK: -
299 // MARK: SecSystemAnchorSource
300 /********************************************************
301 *********** SecSystemAnchorSource object ************
302 ********************************************************/
303
304 static bool SecSystemAnchorSourceCopyParents(
305 SecCertificateSourceRef source, SecCertificateRef certificate,
306 void *context, SecCertificateSourceParents callback) {
307 //#ifndef SECITEM_SHIM_OSX
308 CFArrayRef parents = NULL;
309 CFArrayRef anchors = NULL;
310 SecOTAPKIRef otapkiref = NULL;
311
312 CFDataRef nic = SecCertificateGetNormalizedIssuerContent(certificate);
313 /* 64 bits cast: the worst that can happen here is we truncate the length and match an actual anchor.
314 It does not matter since we would be returning the wrong anchors */
315 assert((unsigned long)CFDataGetLength(nic)<UINT_MAX); /* Debug check. correct as long as CFIndex is signed long */
316
317 otapkiref = SecOTAPKICopyCurrentOTAPKIRef();
318 require_quiet(otapkiref, errOut);
319 anchors = subject_to_anchors(nic);
320 require_quiet(anchors, errOut);
321 parents = CopyCertsFromIndices(anchors);
322
323 errOut:
324 callback(context, parents);
325 CFReleaseSafe(parents);
326 CFReleaseSafe(otapkiref);
327 //#endif // SECITEM_SHIM_OSX
328 return true;
329 }
330
331 static CFArrayRef SecSystemAnchorSourceCopyUsageConstraints(SecCertificateSourceRef __unused source,
332 SecCertificateRef __unused certificate)
333 {
334 CFMutableArrayRef result = NULL;
335 CFMutableDictionaryRef options = NULL, strengthConstraints = NULL, trustRoot = NULL;
336 CFNumberRef trustResult = NULL;
337
338 require_quiet(options = CFDictionaryCreateMutable(NULL, 1,
339 &kCFTypeDictionaryKeyCallBacks,
340 &kCFTypeDictionaryValueCallBacks),
341 out);
342 require_quiet(strengthConstraints = CFDictionaryCreateMutable(NULL, 1,
343 &kCFTypeDictionaryKeyCallBacks,
344 &kCFTypeDictionaryValueCallBacks),
345 out);
346 require_quiet(trustRoot = CFDictionaryCreateMutable(NULL, 1,
347 &kCFTypeDictionaryKeyCallBacks,
348 &kCFTypeDictionaryValueCallBacks),
349 out);
350
351 uint32_t temp = kSecTrustSettingsResultTrustRoot;
352 require_quiet(trustResult = CFNumberCreate(NULL, kCFNumberSInt32Type, &temp), out);
353 CFDictionaryAddValue(trustRoot, kSecTrustSettingsResult, trustResult);
354
355 CFDictionaryAddValue(options, kSecPolicyCheckSystemTrustedWeakHash, kCFBooleanTrue);
356 CFDictionaryAddValue(options, kSecPolicyCheckSystemTrustedWeakKey, kCFBooleanTrue);
357 CFDictionaryAddValue(strengthConstraints, kSecTrustSettingsPolicyOptions, options);
358
359 require_quiet(result = CFArrayCreateMutable(NULL, 2, &kCFTypeArrayCallBacks), out);
360 CFArrayAppendValue(result, strengthConstraints);
361 CFArrayAppendValue(result, trustRoot);
362
363 out:
364 CFReleaseNull(options);
365 CFReleaseNull(trustResult);
366 CFReleaseNull(trustRoot);
367 CFReleaseNull(strengthConstraints);
368 return result;
369 }
370
371 static bool SecSystemAnchorSourceContains(SecCertificateSourceRef source,
372 SecCertificateRef certificate) {
373 bool result = false;
374 CFArrayRef anchors = NULL;
375 SecOTAPKIRef otapkiref = NULL;
376 CFArrayRef cert_datas = NULL;
377
378 CFDataRef nic = SecCertificateGetNormalizedSubjectContent(certificate);
379 /* 64 bits cast: the worst that can happen here is we truncate the length and match an actual anchor.
380 It does not matter since we would be returning the wrong anchors */
381 assert((unsigned long)CFDataGetLength(nic)<UINT_MAX); /* Debug check. correct as long as CFIndex is signed long */
382
383 otapkiref = SecOTAPKICopyCurrentOTAPKIRef();
384 require_quiet(otapkiref, errOut);
385 anchors = subject_to_anchors(nic);
386 require_quiet(anchors, errOut);
387 cert_datas = CopyCertDataFromIndices(anchors);
388 require_quiet(cert_datas, errOut);
389
390 CFIndex cert_length = SecCertificateGetLength(certificate);
391 const UInt8 *cert_data_ptr = SecCertificateGetBytePtr(certificate);
392
393 CFIndex num_cert_datas = CFArrayGetCount(cert_datas);
394 for (CFIndex idx = 0; idx < num_cert_datas; idx++)
395 {
396 CFDataRef cert_data = (CFDataRef)CFArrayGetValueAtIndex(cert_datas, idx);
397
398 if (NULL != cert_data)
399 {
400 if (CFGetTypeID(cert_data) == CFDataGetTypeID())
401 {
402 CFIndex aCert_Length = CFDataGetLength(cert_data);
403 const UInt8* aCert_Data_Ptr = CFDataGetBytePtr(cert_data);
404
405 if (aCert_Length == cert_length)
406 {
407 if (!memcmp(cert_data_ptr, aCert_Data_Ptr, cert_length))
408 {
409 result = true;
410 break;
411 }
412 }
413 }
414 }
415 }
416
417 errOut:
418 CFReleaseSafe(cert_datas);
419 CFReleaseSafe(otapkiref);
420 return result;
421 }
422
423 struct SecCertificateSource _kSecSystemAnchorSource = {
424 SecSystemAnchorSourceCopyParents,
425 SecSystemAnchorSourceCopyUsageConstraints,
426 SecSystemAnchorSourceContains
427 };
428
429 const SecCertificateSourceRef kSecSystemAnchorSource = &_kSecSystemAnchorSource;
430
431
432 #if TARGET_OS_IPHONE
433 // MARK: -
434 // MARK: SecUserAnchorSource
435 /********************************************************
436 ************* SecUserAnchorSource object ***************
437 ********************************************************/
438 static bool SecUserAnchorSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
439 void *context, SecCertificateSourceParents callback) {
440 CFArrayRef parents = SecTrustStoreCopyParents(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
441 certificate, NULL);
442 callback(context, parents);
443 CFReleaseSafe(parents);
444 return true;
445 }
446
447 static CFArrayRef SecUserAnchorSourceCopyUsageConstraints(SecCertificateSourceRef source,
448 SecCertificateRef certificate) {
449 CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
450 if (!digest)
451 return NULL;
452 CFArrayRef usageConstraints = NULL;
453 bool ok = _SecTrustStoreCopyUsageConstraints(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
454 digest, &usageConstraints, NULL);
455 if (ok) {
456 return usageConstraints;
457 } else {
458 CFReleaseNull(usageConstraints);
459 return NULL;
460 }
461 }
462
463 static bool SecUserAnchorSourceContains(SecCertificateSourceRef source,
464 SecCertificateRef certificate) {
465 return SecTrustStoreContains(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
466 certificate);
467 }
468
469 struct SecCertificateSource _kSecUserAnchorSource = {
470 SecUserAnchorSourceCopyParents,
471 SecUserAnchorSourceCopyUsageConstraints,
472 SecUserAnchorSourceContains
473 };
474
475 const SecCertificateSourceRef kSecUserAnchorSource = &_kSecUserAnchorSource;
476 #endif
477
478 // MARK: -
479 // MARK: SecMemoryCertificateSource
480 /********************************************************
481 ********** SecMemoryCertificateSource object ***********
482 ********************************************************/
483 struct SecMemoryCertificateSource {
484 struct SecCertificateSource base;
485 CFMutableSetRef certificates;
486 CFMutableDictionaryRef subjects;
487 };
488 typedef struct SecMemoryCertificateSource *SecMemoryCertificateSourceRef;
489
490 static bool SecMemoryCertificateSourceCopyParents(
491 SecCertificateSourceRef source, SecCertificateRef certificate,
492 void *context, SecCertificateSourceParents callback) {
493 SecMemoryCertificateSourceRef msource =
494 (SecMemoryCertificateSourceRef)source;
495 CFDataRef normalizedIssuer =
496 SecCertificateGetNormalizedIssuerContent(certificate);
497 CFArrayRef parents = (normalizedIssuer) ? CFDictionaryGetValue(msource->subjects,
498 normalizedIssuer) : NULL;
499 /* FIXME filter parents by subjectID if certificate has an
500 authorityKeyIdentifier. */
501 secdebug("trust", "%@ parents -> %@", certificate, parents);
502 callback(context, parents);
503 return true;
504 }
505
506 static bool SecMemoryCertificateSourceContains(SecCertificateSourceRef source,
507 SecCertificateRef certificate) {
508 SecMemoryCertificateSourceRef msource =
509 (SecMemoryCertificateSourceRef)source;
510 return CFSetContainsValue(msource->certificates, certificate);
511 }
512
513 static void dictAddValueToArrayForKey(CFMutableDictionaryRef dict,
514 const void *key, const void *value) {
515 if (!key)
516 return;
517
518 CFMutableArrayRef values =
519 (CFMutableArrayRef)CFDictionaryGetValue(dict, key);
520 if (!values) {
521 values = CFArrayCreateMutable(kCFAllocatorDefault, 0,
522 &kCFTypeArrayCallBacks);
523 CFDictionaryAddValue(dict, key, values);
524 CFRelease(values);
525 }
526
527 if (values)
528 CFArrayAppendValue(values, value);
529 }
530
531 static void SecMemoryCertificateSourceApplierFunction(const void *value,
532 void *context) {
533 SecMemoryCertificateSourceRef msource =
534 (SecMemoryCertificateSourceRef)context;
535 SecCertificateRef certificate = (SecCertificateRef)value;
536
537 /* CFSet's API has no way to combine these 2 operations into 1 sadly. */
538 if (CFSetContainsValue(msource->certificates, certificate))
539 return;
540 CFSetAddValue(msource->certificates, certificate);
541
542 CFDataRef key = SecCertificateGetNormalizedSubjectContent(certificate);
543 dictAddValueToArrayForKey(msource->subjects, key, value);
544 }
545
546 SecCertificateSourceRef SecMemoryCertificateSourceCreate(CFArrayRef certificates) {
547 SecMemoryCertificateSourceRef result = (SecMemoryCertificateSourceRef)
548 malloc(sizeof(*result));
549 result->base.copyParents = SecMemoryCertificateSourceCopyParents;
550 result->base.copyUsageConstraints = NULL;
551 result->base.contains = SecMemoryCertificateSourceContains;
552 CFIndex count = CFArrayGetCount(certificates);
553 result->certificates = CFSetCreateMutable(kCFAllocatorDefault, count,
554 &kCFTypeSetCallBacks);
555 result->subjects = CFDictionaryCreateMutable(kCFAllocatorDefault,
556 count, &kCFTypeDictionaryKeyCallBacks,
557 &kCFTypeDictionaryValueCallBacks);
558 CFRange range = { 0, count };
559 CFArrayApplyFunction(certificates, range,
560 SecMemoryCertificateSourceApplierFunction, result);
561
562 return (SecCertificateSourceRef)result;
563 }
564
565 void SecMemoryCertificateSourceDestroy(SecCertificateSourceRef source) {
566 SecMemoryCertificateSourceRef msource =
567 (SecMemoryCertificateSourceRef)source;
568 CFRelease(msource->certificates);
569 CFRelease(msource->subjects);
570 free(msource);
571 }
572
573 // MARK: -
574 // MARK: SecCAIssuerCertificateSource
575 /********************************************************
576 ********* SecCAIssuerCertificateSource object **********
577 ********************************************************/
578 static bool SecCAIssuerCertificateSourceCopyParents(
579 SecCertificateSourceRef source, SecCertificateRef certificate,
580 void *context, SecCertificateSourceParents callback) {
581 /* Some expired certs have dead domains. Let's not check them. */
582 SecPathBuilderRef builder = (SecPathBuilderRef)context;
583 CFAbsoluteTime verifyDate = SecPathBuilderGetVerifyTime(builder);
584 if (SecPathBuilderHasTemporalParentChecks(builder) && !SecCertificateIsValid(certificate, verifyDate)) {
585 secinfo("async", "skipping CAIssuer fetch for expired %@", certificate);
586 callback(context, NULL);
587 return true;
588 }
589 return SecCAIssuerCopyParents(certificate, SecPathBuilderGetQueue(builder), context, callback);
590 }
591
592 static bool SecCAIssuerCertificateSourceContains(
593 SecCertificateSourceRef source, SecCertificateRef certificate) {
594 return false;
595 }
596
597 struct SecCertificateSource _kSecCAIssuerSource = {
598 SecCAIssuerCertificateSourceCopyParents,
599 NULL,
600 SecCAIssuerCertificateSourceContains
601 };
602
603 const SecCertificateSourceRef kSecCAIssuerSource = &_kSecCAIssuerSource;
604
605 #if TARGET_OS_OSX
606 #include <Security/SecItemPriv.h>
607 // MARK: -
608 // MARK: SecLegacyCertificateSource
609 /********************************************************
610 ********** SecLegacyCertificateSource object ***********
611 ********************************************************/
612
613 static bool SecLegacyCertificateSourceCopyParents(
614 SecCertificateSourceRef source, SecCertificateRef certificate,
615 void *context, SecCertificateSourceParents callback) {
616 CFArrayRef parents = SecItemCopyParentCertificates_osx(certificate, NULL);
617 callback(context, parents);
618 CFReleaseSafe(parents);
619 return true;
620 }
621
622 static bool SecLegacyCertificateSourceContains(
623 SecCertificateSourceRef source, SecCertificateRef certificate) {
624 SecCertificateRef cert = SecItemCopyStoredCertificate(certificate, NULL);
625 bool result = (cert) ? true : false;
626 CFReleaseSafe(cert);
627 return result;
628 }
629
630 struct SecCertificateSource _kSecLegacyCertificateSource = {
631 SecLegacyCertificateSourceCopyParents,
632 NULL,
633 SecLegacyCertificateSourceContains
634 };
635
636 const SecCertificateSourceRef kSecLegacyCertificateSource = &_kSecLegacyCertificateSource;
637
638 #endif /* SecLegacyCertificateSource */
639
640 #if TARGET_OS_OSX
641 // MARK: -
642 // MARK: SecLegacyAnchorSource
643 /********************************************************
644 ************ SecLegacyAnchorSource object **************
645 ********************************************************/
646
647 static bool SecLegacyAnchorSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
648 void *context, SecCertificateSourceParents callback) {
649 CFMutableArrayRef anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
650 CFArrayRef parents = SecItemCopyParentCertificates_osx(certificate, NULL);
651 CFArrayRef trusted = NULL;
652 if (parents == NULL) {
653 goto finish;
654 }
655 /* Get the custom anchors which have been trusted in the user and admin domains.
656 * We don't need system domain roots here, since SecSystemAnchorSource provides those.
657 */
658 OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted);
659 if (status == errSecSuccess && trusted) {
660 CFIndex index, count = CFArrayGetCount(parents);
661 for (index = 0; index < count; index++) {
662 SecCertificateRef parent = (SecCertificateRef)CFArrayGetValueAtIndex(parents, index);
663 if (parent && CFArrayContainsValue(trusted, CFRangeMake(0, CFArrayGetCount(trusted)), parent)) {
664 CFArrayAppendValue(anchors, parent);
665 }
666 }
667 }
668
669 finish:
670 callback(context, anchors);
671 CFReleaseSafe(anchors);
672 CFReleaseSafe(parents);
673 CFReleaseSafe(trusted);
674 return true;
675 }
676
677 static CFArrayRef SecLegacyAnchorSourceCopyUsageConstraints(SecCertificateSourceRef source,
678 SecCertificateRef certificate) {
679 CFArrayRef result = NULL;
680 CFArrayRef userTrustSettings = NULL, adminTrustSettings = NULL;
681
682 OSStatus status = SecTrustSettingsCopyTrustSettings(certificate,
683 kSecTrustSettingsDomainUser,
684 &userTrustSettings);
685 if ((status == errSecSuccess) && (userTrustSettings != NULL)) {
686 result = CFRetain(userTrustSettings);
687 }
688
689 status = SecTrustSettingsCopyTrustSettings(certificate,
690 kSecTrustSettingsDomainAdmin,
691 &adminTrustSettings);
692 /* user trust settings overrule admin trust settings */
693 if ((status == errSecSuccess) && (adminTrustSettings != NULL) && (result == NULL)) {
694 result = CFRetain(adminTrustSettings);
695 }
696
697 CFReleaseNull(userTrustSettings);
698 CFReleaseNull(adminTrustSettings);
699 return result;
700 }
701
702 static bool SecLegacyAnchorSourceContains(SecCertificateSourceRef source,
703 SecCertificateRef certificate) {
704 if (certificate == NULL) {
705 return false;
706 }
707 CFArrayRef trusted = NULL;
708 bool result = false;
709 OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted);
710 if ((status == errSecSuccess) && (trusted != NULL)) {
711 CFIndex index, count = CFArrayGetCount(trusted);
712 for (index = 0; index < count; index++) {
713 SecCertificateRef anchor = (SecCertificateRef)CFArrayGetValueAtIndex(trusted, index);
714 if (anchor && CFEqual(anchor, certificate)) {
715 result = true;
716 break;
717 }
718 }
719 }
720 CFReleaseSafe(trusted);
721 return result;
722 }
723
724 struct SecCertificateSource _kSecLegacyAnchorSource = {
725 SecLegacyAnchorSourceCopyParents,
726 SecLegacyAnchorSourceCopyUsageConstraints,
727 SecLegacyAnchorSourceContains
728 };
729
730 const SecCertificateSourceRef kSecLegacyAnchorSource = &_kSecLegacyAnchorSource;
731
732 #endif /* SecLegacyAnchorSource */