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