]> git.saurik.com Git - apple/security.git/blob - trust/trustd/SecCertificateSource.c
Security-59306.101.1.tar.gz
[apple/security.git] / trust / trustd / 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 "trust/trustd/SecTrustServer.h"
44 #include "keychain/securityd/SecItemServer.h"
45 #include "trust/trustd/SecTrustStoreServer.h"
46 #include "trust/trustd/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(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 CFErrorRef localError = NULL;
264 CFDataRef serialNumber = SecCertificateCopySerialNumberData(certificate, &localError);
265 bool result = SecItemCertificateExists(normalizedIssuer, serialNumber, msource->accessGroups, &localError);
266 if (localError) {
267 if (CFErrorGetCode(localError) != errSecItemNotFound) {
268 secdebug("trust", "SecItemCertificateExists_ios: %@", localError);
269 }
270 CFReleaseSafe(localError);
271 }
272 CFReleaseSafe(serialNumber);
273 CFReleaseSafe(normalizedIssuer);
274 return result;
275 }
276
277 SecCertificateSourceRef SecItemCertificateSourceCreate(CFArrayRef accessGroups) {
278 SecItemCertificateSourceRef result = (SecItemCertificateSourceRef)malloc(sizeof(*result));
279 result->base.copyParents = SecItemCertificateSourceCopyParents;
280 result->base.copyUsageConstraints = NULL;
281 result->base.contains = SecItemCertificateSourceContains;
282 result->accessGroups = accessGroups;
283 CFRetainSafe(accessGroups);
284 return (SecCertificateSourceRef)result;
285 }
286
287 void SecItemCertificateSourceDestroy(SecCertificateSourceRef source) {
288 SecItemCertificateSourceRef msource = (SecItemCertificateSourceRef)source;
289 CFReleaseSafe(msource->accessGroups);
290 free(msource);
291 }
292
293 // MARK: -
294 // MARK: SecSystemAnchorSource
295 /********************************************************
296 *********** SecSystemAnchorSource object ************
297 ********************************************************/
298
299 static bool SecSystemAnchorSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
300 void *context, SecCertificateSourceParents callback) {
301 CFArrayRef parents = NULL;
302 CFArrayRef anchors = NULL;
303
304 CFDataRef nic = SecCertificateGetNormalizedIssuerContent(certificate);
305 /* 64 bits cast: the worst that can happen here is we truncate the length and match an actual anchor.
306 It does not matter since we would be returning the wrong anchors */
307 assert((unsigned long)CFDataGetLength(nic)<UINT_MAX); /* Debug check. correct as long as CFIndex is signed long */
308
309 anchors = subject_to_anchors(nic);
310 require_quiet(anchors, errOut);
311 parents = CopyCertsFromIndices(anchors);
312
313 errOut:
314 callback(context, parents);
315 CFReleaseSafe(parents);
316 return true;
317 }
318
319 static CFArrayRef SecSystemAnchorSourceCopyUsageConstraints(SecCertificateSourceRef __unused source,
320 SecCertificateRef __unused certificate)
321 {
322 CFMutableArrayRef result = NULL;
323 CFMutableDictionaryRef options = NULL, strengthConstraints = NULL, trustRoot = NULL;
324 CFNumberRef trustResult = NULL;
325
326 require_quiet(options = CFDictionaryCreateMutable(NULL, 1,
327 &kCFTypeDictionaryKeyCallBacks,
328 &kCFTypeDictionaryValueCallBacks),
329 out);
330 require_quiet(strengthConstraints = CFDictionaryCreateMutable(NULL, 1,
331 &kCFTypeDictionaryKeyCallBacks,
332 &kCFTypeDictionaryValueCallBacks),
333 out);
334 require_quiet(trustRoot = CFDictionaryCreateMutable(NULL, 1,
335 &kCFTypeDictionaryKeyCallBacks,
336 &kCFTypeDictionaryValueCallBacks),
337 out);
338
339 uint32_t temp = kSecTrustSettingsResultTrustRoot;
340 require_quiet(trustResult = CFNumberCreate(NULL, kCFNumberSInt32Type, &temp), out);
341 CFDictionaryAddValue(trustRoot, kSecTrustSettingsResult, trustResult);
342
343 CFDictionaryAddValue(options, kSecPolicyCheckSystemTrustedWeakHash, kCFBooleanTrue);
344 CFDictionaryAddValue(options, kSecPolicyCheckSystemTrustedWeakKey, kCFBooleanTrue);
345 CFDictionaryAddValue(strengthConstraints, kSecTrustSettingsPolicyOptions, options);
346
347 require_quiet(result = CFArrayCreateMutable(NULL, 2, &kCFTypeArrayCallBacks), out);
348 CFArrayAppendValue(result, strengthConstraints);
349 CFArrayAppendValue(result, trustRoot);
350
351 out:
352 CFReleaseNull(options);
353 CFReleaseNull(trustResult);
354 CFReleaseNull(trustRoot);
355 CFReleaseNull(strengthConstraints);
356 return result;
357 }
358
359 static bool SecSystemAnchorSourceContains(SecCertificateSourceRef source,
360 SecCertificateRef certificate) {
361 bool result = false;
362 CFArrayRef anchors = NULL;
363 SecOTAPKIRef otapkiref = NULL;
364 CFArrayRef cert_datas = NULL;
365
366 CFDataRef nic = SecCertificateGetNormalizedSubjectContent(certificate);
367 /* 64 bits cast: the worst that can happen here is we truncate the length and match an actual anchor.
368 It does not matter since we would be returning the wrong anchors */
369 assert((unsigned long)CFDataGetLength(nic)<UINT_MAX); /* Debug check. correct as long as CFIndex is signed long */
370
371 otapkiref = SecOTAPKICopyCurrentOTAPKIRef();
372 require_quiet(otapkiref, errOut);
373 anchors = subject_to_anchors(nic);
374 require_quiet(anchors, errOut);
375 cert_datas = CopyCertDataFromIndices(anchors);
376 require_quiet(cert_datas, errOut);
377
378 CFIndex cert_length = SecCertificateGetLength(certificate);
379 const UInt8 *cert_data_ptr = SecCertificateGetBytePtr(certificate);
380
381 CFIndex num_cert_datas = CFArrayGetCount(cert_datas);
382 for (CFIndex idx = 0; idx < num_cert_datas; idx++)
383 {
384 CFDataRef cert_data = (CFDataRef)CFArrayGetValueAtIndex(cert_datas, idx);
385
386 if (NULL != cert_data)
387 {
388 if (CFGetTypeID(cert_data) == CFDataGetTypeID())
389 {
390 CFIndex aCert_Length = CFDataGetLength(cert_data);
391 const UInt8* aCert_Data_Ptr = CFDataGetBytePtr(cert_data);
392
393 if (aCert_Length == cert_length)
394 {
395 if (!memcmp(cert_data_ptr, aCert_Data_Ptr, cert_length))
396 {
397 result = true;
398 break;
399 }
400 }
401 }
402 }
403 }
404
405 errOut:
406 CFReleaseSafe(cert_datas);
407 CFReleaseSafe(otapkiref);
408 return result;
409 }
410
411 struct SecCertificateSource _kSecSystemAnchorSource = {
412 SecSystemAnchorSourceCopyParents,
413 SecSystemAnchorSourceCopyUsageConstraints,
414 SecSystemAnchorSourceContains
415 };
416
417 const SecCertificateSourceRef kSecSystemAnchorSource = &_kSecSystemAnchorSource;
418
419
420 #if TARGET_OS_IPHONE
421 // MARK: -
422 // MARK: SecUserAnchorSource
423 /********************************************************
424 ************* SecUserAnchorSource object ***************
425 ********************************************************/
426 static bool SecUserAnchorSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
427 void *context, SecCertificateSourceParents callback) {
428 CFArrayRef parents = SecTrustStoreCopyParents(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
429 certificate, NULL);
430 callback(context, parents);
431 CFReleaseSafe(parents);
432 return true;
433 }
434
435 static CFArrayRef SecUserAnchorSourceCopyUsageConstraints(SecCertificateSourceRef source,
436 SecCertificateRef certificate) {
437 CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
438 if (!digest)
439 return NULL;
440 CFArrayRef usageConstraints = NULL;
441 bool ok = _SecTrustStoreCopyUsageConstraints(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
442 digest, &usageConstraints, NULL);
443 if (ok) {
444 return usageConstraints;
445 } else {
446 CFReleaseNull(usageConstraints);
447 return NULL;
448 }
449 }
450
451 static bool SecUserAnchorSourceContains(SecCertificateSourceRef source,
452 SecCertificateRef certificate) {
453 return SecTrustStoreContains(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
454 certificate);
455 }
456
457 struct SecCertificateSource _kSecUserAnchorSource = {
458 SecUserAnchorSourceCopyParents,
459 SecUserAnchorSourceCopyUsageConstraints,
460 SecUserAnchorSourceContains
461 };
462
463 const SecCertificateSourceRef kSecUserAnchorSource = &_kSecUserAnchorSource;
464 #endif
465
466 // MARK: -
467 // MARK: SecMemoryCertificateSource
468 /********************************************************
469 ********** SecMemoryCertificateSource object ***********
470 ********************************************************/
471 struct SecMemoryCertificateSource {
472 struct SecCertificateSource base;
473 CFMutableSetRef certificates;
474 CFMutableDictionaryRef subjects;
475 };
476 typedef struct SecMemoryCertificateSource *SecMemoryCertificateSourceRef;
477
478 static bool SecMemoryCertificateSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
479 void *context, SecCertificateSourceParents callback) {
480 SecMemoryCertificateSourceRef msource =
481 (SecMemoryCertificateSourceRef)source;
482 CFDataRef normalizedIssuer =
483 SecCertificateGetNormalizedIssuerContent(certificate);
484 CFArrayRef parents = (normalizedIssuer) ? CFDictionaryGetValue(msource->subjects,
485 normalizedIssuer) : NULL;
486 /* FIXME filter parents by subjectID if certificate has an
487 authorityKeyIdentifier. */
488 secdebug("trust", "%@ parents -> %@", certificate, parents);
489 callback(context, parents);
490 return true;
491 }
492
493 static bool SecMemoryCertificateSourceContains(SecCertificateSourceRef source,
494 SecCertificateRef certificate) {
495 SecMemoryCertificateSourceRef msource =
496 (SecMemoryCertificateSourceRef)source;
497 return CFSetContainsValue(msource->certificates, certificate);
498 }
499
500 static void dictAddValueToArrayForKey(CFMutableDictionaryRef dict,
501 const void *key, const void *value) {
502 if (!key)
503 return;
504
505 CFMutableArrayRef values =
506 (CFMutableArrayRef)CFDictionaryGetValue(dict, key);
507 if (!values) {
508 values = CFArrayCreateMutable(kCFAllocatorDefault, 0,
509 &kCFTypeArrayCallBacks);
510 CFDictionaryAddValue(dict, key, values);
511 CFRelease(values);
512 }
513
514 if (values)
515 CFArrayAppendValue(values, value);
516 }
517
518 static void SecMemoryCertificateSourceApplierFunction(const void *value, void *context) {
519 SecMemoryCertificateSourceRef msource =
520 (SecMemoryCertificateSourceRef)context;
521 SecCertificateRef certificate = (SecCertificateRef)value;
522
523 /* CFSet's API has no way to combine these 2 operations into 1 sadly. */
524 if (CFSetContainsValue(msource->certificates, certificate))
525 return;
526 CFSetAddValue(msource->certificates, certificate);
527
528 CFDataRef key = SecCertificateGetNormalizedSubjectContent(certificate);
529 dictAddValueToArrayForKey(msource->subjects, key, value);
530 }
531
532 SecCertificateSourceRef SecMemoryCertificateSourceCreate(CFArrayRef certificates) {
533 SecMemoryCertificateSourceRef result = (SecMemoryCertificateSourceRef)
534 malloc(sizeof(*result));
535 result->base.copyParents = SecMemoryCertificateSourceCopyParents;
536 result->base.copyUsageConstraints = NULL;
537 result->base.contains = SecMemoryCertificateSourceContains;
538 CFIndex count = CFArrayGetCount(certificates);
539 result->certificates = CFSetCreateMutable(kCFAllocatorDefault, count,
540 &kCFTypeSetCallBacks);
541 result->subjects = CFDictionaryCreateMutable(kCFAllocatorDefault,
542 count, &kCFTypeDictionaryKeyCallBacks,
543 &kCFTypeDictionaryValueCallBacks);
544 CFRange range = { 0, count };
545 CFArrayApplyFunction(certificates, range,
546 SecMemoryCertificateSourceApplierFunction, result);
547
548 return (SecCertificateSourceRef)result;
549 }
550
551 void SecMemoryCertificateSourceDestroy(SecCertificateSourceRef source) {
552 SecMemoryCertificateSourceRef msource =
553 (SecMemoryCertificateSourceRef)source;
554 CFRelease(msource->certificates);
555 CFRelease(msource->subjects);
556 free(msource);
557 }
558
559 // MARK: -
560 // MARK: SecCAIssuerCertificateSource
561 /********************************************************
562 ********* SecCAIssuerCertificateSource object **********
563 ********************************************************/
564 static bool SecCAIssuerCertificateSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
565 void *context, SecCertificateSourceParents callback) {
566 /* Some expired certs have dead domains. Let's not check them. */
567 SecPathBuilderRef builder = (SecPathBuilderRef)context;
568 CFAbsoluteTime verifyDate = SecPathBuilderGetVerifyTime(builder);
569 if (SecPathBuilderHasTemporalParentChecks(builder) && !SecCertificateIsValid(certificate, verifyDate)) {
570 secinfo("async", "skipping CAIssuer fetch for expired %@", certificate);
571 callback(context, NULL);
572 return true;
573 }
574 return SecCAIssuerCopyParents(certificate, context, callback);
575 }
576
577 static bool SecCAIssuerCertificateSourceContains(SecCertificateSourceRef source, SecCertificateRef certificate) {
578 return false;
579 }
580
581 struct SecCertificateSource _kSecCAIssuerSource = {
582 SecCAIssuerCertificateSourceCopyParents,
583 NULL,
584 SecCAIssuerCertificateSourceContains
585 };
586
587 const SecCertificateSourceRef kSecCAIssuerSource = &_kSecCAIssuerSource;
588
589 #if TARGET_OS_OSX
590 #include <Security/SecItemPriv.h>
591 // MARK: -
592 // MARK: SecLegacyCertificateSource
593 /********************************************************
594 ********** SecLegacyCertificateSource object ***********
595 ********************************************************/
596
597 static bool SecLegacyCertificateSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
598 void *context, SecCertificateSourceParents callback) {
599 CFArrayRef parents = SecItemCopyParentCertificates_osx(certificate, NULL);
600 callback(context, parents);
601 CFReleaseSafe(parents);
602 return true;
603 }
604
605 static bool SecLegacyCertificateSourceContains(SecCertificateSourceRef source, SecCertificateRef certificate) {
606 SecCertificateRef cert = SecItemCopyStoredCertificate(certificate, NULL);
607 bool result = (cert) ? true : false;
608 CFReleaseSafe(cert);
609 return result;
610 }
611
612 struct SecCertificateSource _kSecLegacyCertificateSource = {
613 SecLegacyCertificateSourceCopyParents,
614 NULL,
615 SecLegacyCertificateSourceContains
616 };
617
618 const SecCertificateSourceRef kSecLegacyCertificateSource = &_kSecLegacyCertificateSource;
619
620 #endif /* SecLegacyCertificateSource */
621
622 #if TARGET_OS_OSX
623 // MARK: -
624 // MARK: SecLegacyAnchorSource
625 /********************************************************
626 ************ SecLegacyAnchorSource object **************
627 ********************************************************/
628
629 static bool SecLegacyAnchorSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
630 void *context, SecCertificateSourceParents callback) {
631 CFMutableArrayRef anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
632 CFArrayRef parents = SecItemCopyParentCertificates_osx(certificate, NULL);
633 CFArrayRef trusted = NULL;
634 if (parents == NULL) {
635 goto finish;
636 }
637 /* Get the custom anchors which have been trusted in the user and admin domains.
638 * We don't need system domain roots here, since SecSystemAnchorSource provides those.
639 */
640 OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted);
641 if (status == errSecSuccess && trusted) {
642 CFIndex index, count = CFArrayGetCount(parents);
643 for (index = 0; index < count; index++) {
644 SecCertificateRef parent = (SecCertificateRef)CFArrayGetValueAtIndex(parents, index);
645 if (parent && CFArrayContainsValue(trusted, CFRangeMake(0, CFArrayGetCount(trusted)), parent)) {
646 CFArrayAppendValue(anchors, parent);
647 }
648 }
649 }
650
651 finish:
652 callback(context, anchors);
653 CFReleaseSafe(anchors);
654 CFReleaseSafe(parents);
655 CFReleaseSafe(trusted);
656 return true;
657 }
658
659 static CFArrayRef SecLegacyAnchorSourceCopyUsageConstraints(SecCertificateSourceRef source,
660 SecCertificateRef certificate) {
661 CFArrayRef result = NULL;
662 CFArrayRef userTrustSettings = NULL, adminTrustSettings = NULL;
663
664 OSStatus status = SecTrustSettingsCopyTrustSettings(certificate,
665 kSecTrustSettingsDomainUser,
666 &userTrustSettings);
667 if ((status == errSecSuccess) && (userTrustSettings != NULL)) {
668 result = CFRetain(userTrustSettings);
669 }
670
671 status = SecTrustSettingsCopyTrustSettings(certificate,
672 kSecTrustSettingsDomainAdmin,
673 &adminTrustSettings);
674 /* user trust settings overrule admin trust settings */
675 if ((status == errSecSuccess) && (adminTrustSettings != NULL) && (result == NULL)) {
676 result = CFRetain(adminTrustSettings);
677 }
678
679 CFReleaseNull(userTrustSettings);
680 CFReleaseNull(adminTrustSettings);
681 return result;
682 }
683
684 static bool SecLegacyAnchorSourceContains(SecCertificateSourceRef source,
685 SecCertificateRef certificate) {
686 if (certificate == NULL) {
687 return false;
688 }
689 CFArrayRef trusted = NULL;
690 bool result = false;
691 OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted);
692 if ((status == errSecSuccess) && (trusted != NULL)) {
693 CFIndex index, count = CFArrayGetCount(trusted);
694 for (index = 0; index < count; index++) {
695 SecCertificateRef anchor = (SecCertificateRef)CFRetainSafe(CFArrayGetValueAtIndex(trusted, index));
696 if (anchor && (CFGetTypeID(anchor) != CFGetTypeID(certificate))) {
697 /* This should only happen if trustd and the Security framework are using different SecCertificate TypeIDs.
698 * This occurs in TrustTests where we rebuild SecCertificate.c for code coverage purposes, so we end up with
699 * two registered SecCertificate types. So we'll make a SecCertificate of our type. */
700 SecCertificateRef temp = SecCertificateCreateWithBytes(NULL, SecCertificateGetBytePtr(anchor), SecCertificateGetLength(anchor));
701 CFAssignRetained(anchor, temp);
702 }
703 if (anchor && CFEqual(anchor, certificate)) {
704 result = true;
705 }
706 CFReleaseNull(anchor);
707 if (result) {
708 break;
709 }
710 }
711 }
712 CFReleaseSafe(trusted);
713 return result;
714 }
715
716 struct SecCertificateSource _kSecLegacyAnchorSource = {
717 SecLegacyAnchorSourceCopyParents,
718 SecLegacyAnchorSourceCopyUsageConstraints,
719 SecLegacyAnchorSourceContains
720 };
721
722 const SecCertificateSourceRef kSecLegacyAnchorSource = &_kSecLegacyAnchorSource;
723
724 #endif /* SecLegacyAnchorSource */