+static CFArrayRef
+_CopyMatchingIssuers(CFArrayRef matchIssuers) {
+ CFMutableArrayRef result = NULL;
+ CFMutableDictionaryRef query = NULL;
+ CFMutableDictionaryRef policyProperties = NULL;
+ SecPolicyRef policy = NULL;
+ CFTypeRef matchedCertificates = NULL;
+
+ require_quiet(policyProperties = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), out);
+ CFDictionarySetValue(policyProperties, kSecPolicyKU_KeyCertSign, kCFBooleanTrue);
+ require_quiet(policy = SecPolicyCreateWithProperties(kSecPolicyAppleX509Basic, policyProperties), out);
+
+ require_quiet(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), out);
+ CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
+ CFDictionarySetValue(query, kSecMatchIssuers, matchIssuers);
+ CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
+ CFDictionarySetValue(query, kSecReturnAttributes, kCFBooleanTrue);
+ CFDictionarySetValue(query, kSecUseCertificatesWithMatchIssuers, kCFBooleanTrue);
+ CFDictionarySetValue(query, kSecMatchPolicy, policy);
+
+ if (SecItemCopyMatching_osx(query, &matchedCertificates) == errSecSuccess && CFGetTypeID(matchedCertificates) == CFArrayGetTypeID()) {
+ require_quiet(result = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, (CFArrayRef)matchedCertificates), out);
+ for(CFIndex i = 0; i < CFArrayGetCount((CFArrayRef)matchedCertificates); ++i) {
+ CFDictionaryRef attributes = (CFDictionaryRef)CFArrayGetValueAtIndex((CFArrayRef)matchedCertificates, i);
+ CFTypeRef subject = CFDictionaryGetValue(attributes, kSecAttrSubject);
+ if (!CFArrayContainsValue(result, CFRangeMake(0, CFArrayGetCount(result)), subject)) {
+ CFArrayAppendValue(result, subject);
+ }
+ }
+ }
+
+out:
+ CFReleaseSafe(query);
+ CFReleaseSafe(policyProperties);
+ CFReleaseSafe(policy);
+ CFReleaseSafe(matchedCertificates);
+
+ return result;
+}
+