]> git.saurik.com Git - apple/security.git/blob - trust/trustd/SecCertificateSource.c
Security-59754.41.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 // MARK: -
420 // MARK: SecUserAnchorSource
421 /********************************************************
422 ************* SecUserAnchorSource object ***************
423 ********************************************************/
424 static bool SecUserAnchorSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
425 void *context, SecCertificateSourceParents callback) {
426 CFArrayRef parents = SecTrustStoreCopyParents(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
427 certificate, NULL);
428 callback(context, parents);
429 CFReleaseSafe(parents);
430 return true;
431 }
432
433 static CFArrayRef SecUserAnchorSourceCopyUsageConstraints(SecCertificateSourceRef source,
434 SecCertificateRef certificate) {
435 CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
436 if (!digest)
437 return NULL;
438 CFArrayRef usageConstraints = NULL;
439 bool ok = _SecTrustStoreCopyUsageConstraints(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
440 digest, &usageConstraints, NULL);
441 if (ok) {
442 return usageConstraints;
443 } else {
444 CFReleaseNull(usageConstraints);
445 return NULL;
446 }
447 }
448
449 static bool SecUserAnchorSourceContains(SecCertificateSourceRef source,
450 SecCertificateRef certificate) {
451 return SecTrustStoreContains(SecTrustStoreForDomain(kSecTrustStoreDomainUser),
452 certificate);
453 }
454
455 struct SecCertificateSource _kSecUserAnchorSource = {
456 SecUserAnchorSourceCopyParents,
457 SecUserAnchorSourceCopyUsageConstraints,
458 SecUserAnchorSourceContains
459 };
460
461 const SecCertificateSourceRef kSecUserAnchorSource = &_kSecUserAnchorSource;
462
463 // MARK: -
464 // MARK: SecMemoryCertificateSource
465 /********************************************************
466 ********** SecMemoryCertificateSource object ***********
467 ********************************************************/
468 struct SecMemoryCertificateSource {
469 struct SecCertificateSource base;
470 CFMutableSetRef certificates;
471 CFMutableDictionaryRef subjects;
472 };
473 typedef struct SecMemoryCertificateSource *SecMemoryCertificateSourceRef;
474
475 static bool SecMemoryCertificateSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
476 void *context, SecCertificateSourceParents callback) {
477 SecMemoryCertificateSourceRef msource =
478 (SecMemoryCertificateSourceRef)source;
479 CFDataRef normalizedIssuer =
480 SecCertificateGetNormalizedIssuerContent(certificate);
481 CFArrayRef parents = (normalizedIssuer) ? CFDictionaryGetValue(msource->subjects,
482 normalizedIssuer) : NULL;
483 /* FIXME filter parents by subjectID if certificate has an
484 authorityKeyIdentifier. */
485 secdebug("trust", "%@ parents -> %@", certificate, parents);
486 callback(context, parents);
487 return true;
488 }
489
490 static bool SecMemoryCertificateSourceContains(SecCertificateSourceRef source,
491 SecCertificateRef certificate) {
492 SecMemoryCertificateSourceRef msource =
493 (SecMemoryCertificateSourceRef)source;
494 return CFSetContainsValue(msource->certificates, certificate);
495 }
496
497 static void dictAddValueToArrayForKey(CFMutableDictionaryRef dict,
498 const void *key, const void *value) {
499 if (!key)
500 return;
501
502 CFMutableArrayRef values =
503 (CFMutableArrayRef)CFDictionaryGetValue(dict, key);
504 if (!values) {
505 values = CFArrayCreateMutable(kCFAllocatorDefault, 0,
506 &kCFTypeArrayCallBacks);
507 CFDictionaryAddValue(dict, key, values);
508 CFRelease(values);
509 }
510
511 if (values)
512 CFArrayAppendValue(values, value);
513 }
514
515 static void SecMemoryCertificateSourceApplierFunction(const void *value, void *context) {
516 SecMemoryCertificateSourceRef msource =
517 (SecMemoryCertificateSourceRef)context;
518 SecCertificateRef certificate = (SecCertificateRef)value;
519
520 /* CFSet's API has no way to combine these 2 operations into 1 sadly. */
521 if (CFSetContainsValue(msource->certificates, certificate))
522 return;
523 CFSetAddValue(msource->certificates, certificate);
524
525 CFDataRef key = SecCertificateGetNormalizedSubjectContent(certificate);
526 dictAddValueToArrayForKey(msource->subjects, key, value);
527 }
528
529 SecCertificateSourceRef SecMemoryCertificateSourceCreate(CFArrayRef certificates) {
530 SecMemoryCertificateSourceRef result = (SecMemoryCertificateSourceRef)
531 malloc(sizeof(*result));
532 result->base.copyParents = SecMemoryCertificateSourceCopyParents;
533 result->base.copyUsageConstraints = NULL;
534 result->base.contains = SecMemoryCertificateSourceContains;
535 CFIndex count = CFArrayGetCount(certificates);
536 result->certificates = CFSetCreateMutable(kCFAllocatorDefault, count,
537 &kCFTypeSetCallBacks);
538 result->subjects = CFDictionaryCreateMutable(kCFAllocatorDefault,
539 count, &kCFTypeDictionaryKeyCallBacks,
540 &kCFTypeDictionaryValueCallBacks);
541 CFRange range = { 0, count };
542 CFArrayApplyFunction(certificates, range,
543 SecMemoryCertificateSourceApplierFunction, result);
544
545 return (SecCertificateSourceRef)result;
546 }
547
548 void SecMemoryCertificateSourceDestroy(SecCertificateSourceRef source) {
549 SecMemoryCertificateSourceRef msource =
550 (SecMemoryCertificateSourceRef)source;
551 CFRelease(msource->certificates);
552 CFRelease(msource->subjects);
553 free(msource);
554 }
555
556 // MARK: -
557 // MARK: SecCAIssuerCertificateSource
558 /********************************************************
559 ********* SecCAIssuerCertificateSource object **********
560 ********************************************************/
561 static bool SecCAIssuerCertificateSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
562 void *context, SecCertificateSourceParents callback) {
563 /* Some expired certs have dead domains. Let's not check them. */
564 SecPathBuilderRef builder = (SecPathBuilderRef)context;
565 CFAbsoluteTime verifyDate = SecPathBuilderGetVerifyTime(builder);
566 if (SecPathBuilderHasTemporalParentChecks(builder) && !SecCertificateIsValid(certificate, verifyDate)) {
567 secinfo("async", "skipping CAIssuer fetch for expired %@", certificate);
568 callback(context, NULL);
569 return true;
570 }
571 return SecCAIssuerCopyParents(certificate, context, callback);
572 }
573
574 static bool SecCAIssuerCertificateSourceContains(SecCertificateSourceRef source, SecCertificateRef certificate) {
575 return false;
576 }
577
578 struct SecCertificateSource _kSecCAIssuerSource = {
579 SecCAIssuerCertificateSourceCopyParents,
580 NULL,
581 SecCAIssuerCertificateSourceContains
582 };
583
584 const SecCertificateSourceRef kSecCAIssuerSource = &_kSecCAIssuerSource;
585
586 #if TARGET_OS_OSX
587 #include <Security/SecItemPriv.h>
588 // MARK: -
589 // MARK: SecLegacyCertificateSource
590 /********************************************************
591 ********** SecLegacyCertificateSource object ***********
592 ********************************************************/
593
594 static bool SecLegacyCertificateSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
595 void *context, SecCertificateSourceParents callback) {
596 CFArrayRef parents = SecItemCopyParentCertificates_osx(certificate, NULL);
597 callback(context, parents);
598 CFReleaseSafe(parents);
599 return true;
600 }
601
602 static bool SecLegacyCertificateSourceContains(SecCertificateSourceRef source, SecCertificateRef certificate) {
603 SecCertificateRef cert = SecItemCopyStoredCertificate(certificate, NULL);
604 bool result = (cert) ? true : false;
605 CFReleaseSafe(cert);
606 return result;
607 }
608
609 struct SecCertificateSource _kSecLegacyCertificateSource = {
610 SecLegacyCertificateSourceCopyParents,
611 NULL,
612 SecLegacyCertificateSourceContains
613 };
614
615 const SecCertificateSourceRef kSecLegacyCertificateSource = &_kSecLegacyCertificateSource;
616
617 #endif /* SecLegacyCertificateSource */
618
619 #if TARGET_OS_OSX
620 // MARK: -
621 // MARK: SecLegacyAnchorSource
622 /********************************************************
623 ************ SecLegacyAnchorSource object **************
624 ********************************************************/
625
626 static bool SecLegacyAnchorSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate,
627 void *context, SecCertificateSourceParents callback) {
628 CFMutableArrayRef anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
629 CFArrayRef trusted = NULL;
630 CFDataRef normalizedIssuer = SecCertificateCopyNormalizedIssuerSequence(certificate);
631 if (!normalizedIssuer) {
632 goto finish;
633 }
634
635 /* Get the custom anchors which have been trusted in the user and admin domains.
636 * We don't need system domain roots here, since SecSystemAnchorSource provides those.
637 */
638 OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted);
639 if (status == errSecSuccess && trusted) {
640 CFIndex index, count = CFArrayGetCount(trusted);
641 for (index = 0; index < count; index++) {
642 SecCertificateRef potentialParent = (SecCertificateRef)CFArrayGetValueAtIndex(trusted, index);
643 CFDataRef normalizedSubject = SecCertificateCopyNormalizedSubjectSequence(potentialParent);
644 if (CFEqualSafe(normalizedIssuer, normalizedSubject)) {
645 CFArrayAppendValue(anchors, potentialParent);
646 }
647 CFReleaseSafe(normalizedSubject);
648 }
649 }
650
651 finish:
652 callback(context, anchors);
653 CFReleaseSafe(anchors);
654 CFReleaseSafe(trusted);
655 CFReleaseSafe(normalizedIssuer);
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_Cached(certificate,
665 kSecTrustSettingsDomainAdmin,
666 &adminTrustSettings);
667 if ((status == errSecSuccess) && (adminTrustSettings != NULL)) {
668 /* admin trust settings overrule user trust settings (rdar://37052515) */
669 return adminTrustSettings;
670 }
671
672 status = SecTrustSettingsCopyTrustSettings_Cached(certificate,
673 kSecTrustSettingsDomainUser,
674 &userTrustSettings);
675 if (status == errSecSuccess) {
676 result = CFRetainSafe(userTrustSettings);
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
690 if (SecTrustSettingsUserAdminDomainsContain(certificate)) {
691 return true;
692 } else {
693 CFArrayRef trusted = NULL;
694 bool result = false;
695 OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted);
696 if ((status == errSecSuccess) && (trusted != NULL)) {
697 if ((CFArrayGetCount(trusted) > 0) && CFGetTypeID(CFArrayGetValueAtIndex(trusted, 0)) != CFGetTypeID(certificate)) {
698 /* This fallback should only happen if trustd and the Security framework are using different SecCertificate TypeIDs.
699 * This occurs in TrustTests where we rebuild SecCertificate.c for code coverage purposes, so we end up with
700 * two registered SecCertificate types. So we'll make a SecCertificate of our type. */
701 CFIndex index, count = CFArrayGetCount(trusted);
702 for (index = 0; index < count; index++) {
703 SecCertificateRef anchor = (SecCertificateRef)CFRetainSafe(CFArrayGetValueAtIndex(trusted, index));
704 if (anchor && (CFGetTypeID(anchor) != CFGetTypeID(certificate))) {
705 SecCertificateRef temp = SecCertificateCreateWithBytes(NULL, SecCertificateGetBytePtr(anchor), SecCertificateGetLength(anchor));
706 CFAssignRetained(anchor, temp);
707 }
708 if (anchor && CFEqual(anchor, certificate)) {
709 result = true;
710 }
711 CFReleaseNull(anchor);
712 if (result) {
713 break;
714 }
715 }
716 }
717 CFReleaseSafe(trusted);
718 return result;
719 }
720 }
721 return false;
722 }
723
724 struct SecCertificateSource _kSecLegacyAnchorSource = {
725 SecLegacyAnchorSourceCopyParents,
726 SecLegacyAnchorSourceCopyUsageConstraints,
727 SecLegacyAnchorSourceContains
728 };
729
730 const SecCertificateSourceRef kSecLegacyAnchorSource = &_kSecLegacyAnchorSource;
731
732 #endif /* SecLegacyAnchorSource */