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