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