/ OSX / sec / Security / SecTrustStore.c
SecTrustStore.c
  1  /*
  2   * Copyright (c) 2007-2020 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  
 24  /*
 25   * SecTrustStore.c - CertificateSource API to a system root certificate store
 26   */
 27  #include <Security/SecTrustStore.h>
 28  
 29  #include <Security/SecCertificateInternal.h>
 30  #include <Security/SecInternal.h>
 31  #include <Security/SecuritydXPC.h>
 32  #include <Security/SecPolicyPriv.h>
 33  #include <Security/SecPolicyInternal.h>
 34  #include <CoreFoundation/CFString.h>
 35  #include <AssertMacros.h>
 36  #include <ipc/securityd_client.h>
 37  #include "SecFramework.h"
 38  #include <sys/stat.h>
 39  #include <stdio.h>
 40  #include <os/activity.h>
 41  #include <dirent.h>
 42  #include <Security/SecTrustPriv.h>
 43  #include <Security/SecTrustSettingsPriv.h>
 44  #include <utilities/SecCFError.h>
 45  #include <utilities/SecCFWrappers.h>
 46  #include "utilities/SecDb.h"
 47  #include "SecTrustInternal.h"
 48  
 49  static CFStringRef kSecTrustStoreUserName = CFSTR("user");
 50  static CFStringRef kSecTrustStoreAdminName = CFSTR("admin");
 51  static CFStringRef kSecTrustStoreSystemName = CFSTR("system");
 52  
 53  SecTrustStoreRef SecTrustStoreForDomain(SecTrustStoreDomain domain) {
 54      CFStringRef domainName = NULL;
 55      switch (domain) {
 56          case kSecTrustStoreDomainUser:
 57              domainName = kSecTrustStoreUserName;
 58              break;
 59          case kSecTrustStoreDomainAdmin:
 60              domainName = kSecTrustStoreAdminName;
 61              break;
 62          case kSecTrustStoreDomainSystem:
 63              domainName = kSecTrustStoreSystemName;
 64              break;
 65          default:
 66              return NULL;
 67      }
 68  
 69      if (gTrustd) {
 70          return gTrustd->sec_trust_store_for_domain(domainName, NULL);
 71      } else {
 72          return (SecTrustStoreRef)domainName;
 73      }
 74  }
 75  
 76  static bool SecXPCDictionarySetCertificate(xpc_object_t message, const char *key, SecCertificateRef certificate, CFErrorRef *error) {
 77      if (certificate) {
 78          xpc_dictionary_set_data(message, key, SecCertificateGetBytePtr(certificate),
 79                                  SecCertificateGetLength(certificate));
 80          return true;
 81      }
 82      return SecError(errSecParam, error, CFSTR("NULL certificate"));
 83  }
 84  
 85  static bool string_cert_to_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef cert, CFErrorRef *error)
 86  {
 87      return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
 88          return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) &&
 89                  SecXPCDictionarySetCertificate(message, kSecXPCKeyCertificate, cert, blockError);
 90      }, NULL);
 91  }
 92  
 93  static bool string_cert_to_bool_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef cert, bool *result, CFErrorRef *error)
 94  {
 95      os_activity_t activity = os_activity_create("SecTrustStoreContains", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
 96      os_activity_scope(activity);
 97      bool status = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
 98          return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) &&
 99                 SecXPCDictionarySetCertificate(message, kSecXPCKeyCertificate, cert, blockError);
100      }, ^bool(xpc_object_t response, CFErrorRef *blockError) {
101          if (result)
102              *result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
103          return true;
104      });
105      os_release(activity);
106      return status;
107  }
108  
109  Boolean SecTrustStoreContains(SecTrustStoreRef ts,
110  	SecCertificateRef certificate) {
111      bool ok = false;
112  	__block bool contains = false;
113      require(ts, errOut);
114      ok = (SecOSStatusWith(^bool (CFErrorRef *error) {
115          return TRUSTD_XPC(sec_trust_store_contains, string_cert_to_bool_bool_error, ts, certificate, &contains, error);
116      }) == errSecSuccess);
117  
118  errOut:
119  	return ok && contains;
120  }
121  
122  
123  static bool string_cert_cftype_to_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef certificate, CFTypeRef trustSettingsDictOrArray, CFErrorRef *error)
124  {
125      return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
126          bool ok = false;
127          ok = SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) &&
128              SecXPCDictionarySetCertificate(message, kSecXPCKeyCertificate, certificate, blockError) &&
129              (!trustSettingsDictOrArray || SecXPCDictionarySetPList(message, kSecXPCKeySettings, trustSettingsDictOrArray, blockError));
130          return ok;
131      }, NULL);
132  }
133  
134  static OSStatus validateConstraint(Boolean isSelfSigned, CFMutableDictionaryRef trustSettingsDict) {
135      OSStatus result = errSecSuccess;
136  
137      /* Check "TrustRoot"/"TrustAsRoot" */
138      CFNumberRef resultNumber = NULL;
139      resultNumber = (CFNumberRef)CFDictionaryGetValue(trustSettingsDict, kSecTrustSettingsResult);
140      uint32_t resultValue = kSecTrustSettingsResultInvalid;
141      if (!isNumber(resultNumber) && !isSelfSigned) {
142          /* only self-signed certs get default of TrustAsRoot */
143          return errSecParam;
144      }
145      if (isNumber(resultNumber) && CFNumberGetValue(resultNumber, kCFNumberSInt32Type, &resultValue)) {
146          if (isSelfSigned && resultValue == kSecTrustSettingsResultTrustAsRoot) {
147              return errSecParam;
148          }
149          if (!isSelfSigned && resultValue == kSecTrustSettingsResultTrustRoot) {
150              return errSecParam;
151          }
152      }
153  
154      /* If there's a policy specified, change the contents */
155      SecPolicyRef policy = NULL;
156      policy = (SecPolicyRef)CFDictionaryGetValue(trustSettingsDict, kSecTrustSettingsPolicy);
157      if (policy) {
158          CFStringRef policyOid = NULL, policyName = NULL;
159          policyOid = SecPolicyGetOidString(policy);
160          policyName = SecPolicyGetName(policy);
161          CFDictionarySetValue(trustSettingsDict, kSecTrustSettingsPolicy, policyOid);
162          if (policyName) { CFDictionaryAddValue(trustSettingsDict, kSecTrustSettingsPolicyName, policyName); }
163      }
164  
165      return result;
166  }
167  
168  static OSStatus validateTrustSettings(Boolean isSelfSigned,
169              CFTypeRef trustSettingsDictOrArray,
170              CFTypeRef * CF_RETURNS_RETAINED modifiedTrustSettings) {
171      OSStatus status = errSecParam;
172      CFTypeRef result = NULL;
173  
174      /* NULL is a valid input */
175      if (!trustSettingsDictOrArray && isSelfSigned) {
176          return errSecSuccess;
177      } else if (!trustSettingsDictOrArray && !isSelfSigned) {
178          return errSecParam;
179      }
180  
181      if (CFDictionaryGetTypeID() == CFGetTypeID(trustSettingsDictOrArray)) {
182          result = CFDictionaryCreateMutableCopy(NULL, 0, trustSettingsDictOrArray);
183          status = validateConstraint(isSelfSigned, (CFMutableDictionaryRef)result);
184      } else if (CFArrayGetTypeID() == CFGetTypeID(trustSettingsDictOrArray)) {
185          require_action_quiet(result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks),
186                               out, status = errSecAllocate);
187          CFIndex ix, count = CFArrayGetCount(trustSettingsDictOrArray);
188          for (ix = 0; ix < count; ix++) {
189              CFDictionaryRef constraint = CFArrayGetValueAtIndex(trustSettingsDictOrArray, ix);
190              CFDictionaryRef modifiedConstraint = NULL;
191              require_noerr_quiet(status = validateTrustSettings(isSelfSigned, constraint, (CFTypeRef *)&modifiedConstraint), out);
192              CFArrayAppendValue((CFMutableArrayRef)result, modifiedConstraint);
193              CFReleaseNull(modifiedConstraint); /* constraint now owned by array */
194          }
195      }
196  
197  out:
198      if (errSecSuccess == status && modifiedTrustSettings) {
199          *modifiedTrustSettings = CFRetainSafe(result);
200      }
201      CFReleaseNull(result);
202      return status;
203  }
204  
205  OSStatus SecTrustStoreSetTrustSettings(SecTrustStoreRef ts,
206  	SecCertificateRef certificate,
207      CFTypeRef trustSettingsDictOrArray) {
208      __block OSStatus result;
209      __block CFTypeRef validatedTrustSettings = NULL;
210  
211      Boolean isSelfSigned = false;
212      require_noerr_quiet(result = SecCertificateIsSelfSigned(certificate, &isSelfSigned), out);
213      require_noerr_quiet(result = validateTrustSettings(isSelfSigned, trustSettingsDictOrArray, &validatedTrustSettings), out);
214  
215      os_activity_initiate("SecTrustStoreSetTrustSettings", OS_ACTIVITY_FLAG_DEFAULT, ^{
216          result = SecOSStatusWith(^bool (CFErrorRef *error) {
217              return TRUSTD_XPC(sec_trust_store_set_trust_settings, string_cert_cftype_to_error, ts, certificate, validatedTrustSettings, error);
218          });
219      });
220  
221  out:
222      CFReleaseNull(validatedTrustSettings);
223      return result;
224  }
225  
226  OSStatus SecTrustStoreRemoveCertificate(SecTrustStoreRef ts,
227      SecCertificateRef certificate)
228  {
229      __block OSStatus status = errSecParam;
230  
231      os_activity_t activity = os_activity_create("SecTrustStoreRemoveCertificate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
232      os_activity_scope(activity);
233      require(ts, errOut);
234  
235      status = SecOSStatusWith(^bool (CFErrorRef *error) {
236          return TRUSTD_XPC(sec_trust_store_remove_certificate, string_cert_to_bool_error, ts, certificate, error);
237      });
238  
239  errOut:
240      os_release(activity);
241  	return status;
242  }
243  
244  OSStatus SecTrustStoreGetSettingsVersionNumber(SecTrustSettingsVersionNumber* p_settings_version_number)
245  {
246      if (NULL == p_settings_version_number) {
247          return errSecParam;
248      }
249  
250      OSStatus status = errSecSuccess;
251      CFErrorRef error = nil;
252      uint64_t versionNumber = SecTrustGetTrustStoreVersionNumber(&error);
253      *p_settings_version_number = (SecTrustSettingsVersionNumber)versionNumber;
254  
255      if (error) {
256          status = (OSStatus)CFErrorGetCode(error);
257      }
258      CFReleaseSafe(error);
259      return status;
260  }
261  
262  OSStatus SecTrustStoreGetSettingsAssetVersionNumber(SecTrustSettingsAssetVersionNumber* p_settings_asset_version_number)
263  {
264      if (NULL == p_settings_asset_version_number) {
265          return errSecParam;
266      }
267  
268      OSStatus status = errSecSuccess;
269      CFErrorRef error = nil;
270      uint64_t versionNumber = SecTrustGetAssetVersionNumber(&error);
271      *p_settings_asset_version_number = (SecTrustSettingsAssetVersionNumber)versionNumber;
272  
273      if (error) {
274          status = (OSStatus)CFErrorGetCode(error);
275      }
276      CFReleaseSafe(error);
277      return status;
278  }
279  
280  static bool string_to_array_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error)
281  {
282      return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
283          return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError);
284      }, ^bool(xpc_object_t response, CFErrorRef *blockError) {
285          if (trustStoreContents) {
286              *trustStoreContents = SecXPCDictionaryCopyArray(response, kSecXPCKeyResult, blockError);
287              if (!*trustStoreContents) return false;
288          }
289          return true;
290      });
291  }
292  
293  OSStatus SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents)
294  {
295      __block CFArrayRef results = NULL;
296      OSStatus status = errSecParam;
297  
298      os_activity_t activity = os_activity_create("SecTrustStoreCopyAll", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
299      os_activity_scope(activity);
300      require(ts, errOut);
301  
302      status = SecOSStatusWith(^bool (CFErrorRef *error) {
303          return TRUSTD_XPC(sec_trust_store_copy_all, string_to_array_error, ts, &results, error);
304      });
305  
306      *trustStoreContents = results;
307  
308  errOut:
309      os_release(activity);
310      return status;
311  }
312  
313  static bool string_cert_to_array_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef cert, CFArrayRef *usageConstraints, CFErrorRef *error)
314  {
315      return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
316          return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) &&
317                  SecXPCDictionarySetCertificate(message, kSecXPCKeyCertificate, cert, blockError);
318      }, ^bool(xpc_object_t response, CFErrorRef *blockError) {
319          return SecXPCDictionaryCopyArrayOptional(response, kSecXPCKeyResult, usageConstraints, blockError);
320      });
321  }
322  
323  OSStatus SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, SecCertificateRef certificate, CFArrayRef *usageConstraints)
324  {
325      __block CFArrayRef results = NULL;
326      OSStatus status = errSecParam;
327  
328      os_activity_t activity = os_activity_create("SecTrustStoreCopyUsageConstraints", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
329      os_activity_scope(activity);
330      require(ts, errOut);
331      require(certificate, errOut);
332      require(usageConstraints, errOut);
333  
334      status = SecOSStatusWith(^bool (CFErrorRef *error) {
335          return TRUSTD_XPC(sec_trust_store_copy_usage_constraints, string_cert_to_array_error, ts, certificate, &results, error);
336      });
337  
338      *usageConstraints = results;
339  
340  errOut:
341      os_release(activity);
342      return status;
343  }
344  
345  #define do_if_registered(sdp, ...) if (gTrustd && gTrustd->sdp) { return gTrustd->sdp(__VA_ARGS__); }
346  
347  const CFStringRef kSecTrustStoreSPKIHashKey = CFSTR("SubjectPublicKeyInfoHash");
348  const CFStringRef kSecTrustStoreHashAlgorithmKey = CFSTR("HashAlgorithm");
349  
350  /* MARK: CT Enforcement Exceptions */
351  
352  const CFStringRef kSecCTExceptionsCAsKey = CFSTR("DisabledForCAs");
353  const CFStringRef kSecCTExceptionsDomainsKey = CFSTR("DisabledForDomains");
354  const CFStringRef kSecCTExceptionsHashAlgorithmKey = kSecTrustStoreHashAlgorithmKey;
355  const CFStringRef kSecCTExceptionsSPKIHashKey = kSecTrustStoreSPKIHashKey;
356  
357  bool SecTrustStoreSetCTExceptions(CFStringRef applicationIdentifier, CFDictionaryRef exceptions, CFErrorRef *error) {
358  #if !TARGET_OS_BRIDGE
359      if (applicationIdentifier && gTrustd && gTrustd->sec_trust_store_set_ct_exceptions) {
360          return gTrustd->sec_trust_store_set_ct_exceptions(applicationIdentifier, exceptions, error);
361      } else if (gTrustd && gTrustd->sec_trust_store_set_ct_exceptions) {
362          /* When calling from the TrustTests, we need to pass the appID for the tests. Ordinarily,
363           * this is done by trustd using the client's entitlements. */
364          return gTrustd->sec_trust_store_set_ct_exceptions(CFSTR("com.apple.trusttests"), exceptions, error);
365      }
366  
367      os_activity_t activity = os_activity_create("SecTrustStoreSetCTExceptions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
368      os_activity_scope(activity);
369  
370      __block bool result = false;
371      securityd_send_sync_and_do(kSecXPCOpSetCTExceptions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) {
372          SecXPCDictionarySetPListOptional(message, kSecTrustExceptionsKey, exceptions, block_error);
373          SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error);
374          return true;
375      }, ^bool(xpc_object_t response, CFErrorRef *block_error) {
376          result = SecXPCDictionaryGetBool(response, kSecXPCKeyResult, block_error);
377          return true;
378      });
379  
380      os_release(activity);
381      return result;
382  #else // TARGET_OS_BRIDGE
383      return SecError(errSecReadOnly, error, CFSTR("SecTrustStoreSetCTExceptions not supported on bridgeOS"));
384  #endif // TARGET_OS_BRIDGE
385  }
386  
387  CFDictionaryRef SecTrustStoreCopyCTExceptions(CFStringRef applicationIdentifier, CFErrorRef *error) {
388  #if !TARGET_OS_BRIDGE
389      do_if_registered(sec_trust_store_copy_ct_exceptions, applicationIdentifier, error);
390  
391      os_activity_t activity = os_activity_create("SecTrustStoreCopyCTExceptions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
392      os_activity_scope(activity);
393  
394      __block CFDictionaryRef result = NULL;
395      securityd_send_sync_and_do(kSecXPCOpCopyCTExceptions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) {
396          SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error);
397          return true;
398      }, ^bool(xpc_object_t response, CFErrorRef *block_error) {
399          (void)SecXPCDictionaryCopyDictionaryOptional(response, kSecTrustExceptionsKey, &result, block_error);
400          return true;
401      });
402  
403      os_release(activity);
404      return result;
405  #else // TARGET_OS_BRIDGE
406      SecError(errSecReadOnly, error, CFSTR("SecTrustStoreCopyCTExceptions not supported on bridgeOS"));
407      return NULL;
408  #endif // TARGET_OS_BRIDGE
409  }
410  
411  /* MARK: CA Revocation Additions */
412  
413  /* Specify explicit additions to the list of known CAs for which revocation will be checked.
414   * Input: dictionary with following key and value:
415   *   Key = kSecCARevocationAdditionsKey; Value = Array of dictionaries
416   * For revocation checking to be enabled for certificates issued by a CA, the CA must be specified as a
417   * dictionary entry containing the hash of the subjectPublicKeyInfo that appears in the CA certificate:
418   *   Key = kSecCARevocationHashAlgorithmKey; Value = String. Currently, must be ”sha256”.
419   *   Key = kSecCARevocationSPKIHashKey; Value = Data. Created by applying the specified hash algorithm
420   *   to the DER encoding of the certificate's subjectPublicKeyInfo.
421  */
422  
423  const CFStringRef kSecCARevocationAdditionsKey = CFSTR("EnabledForCAs");
424  const CFStringRef kSecCARevocationHashAlgorithmKey = kSecTrustStoreHashAlgorithmKey;
425  const CFStringRef kSecCARevocationSPKIHashKey = kSecTrustStoreSPKIHashKey;
426  
427  bool SecTrustStoreSetCARevocationAdditions(CFStringRef applicationIdentifier, CFDictionaryRef additions, CFErrorRef *error) {
428  #if !TARGET_OS_BRIDGE
429      if (applicationIdentifier && gTrustd && gTrustd->sec_trust_store_set_ca_revocation_additions) {
430          return gTrustd->sec_trust_store_set_ca_revocation_additions(applicationIdentifier, additions, error);
431      } else if (gTrustd && gTrustd->sec_trust_store_set_ca_revocation_additions) {
432          /* When calling from the TrustTests, we need to pass the appID for the tests. Ordinarily,
433           * this is done by trustd using the client's entitlements. */
434          return gTrustd->sec_trust_store_set_ca_revocation_additions(CFSTR("com.apple.trusttests"), additions, error);
435      }
436  
437      os_activity_t activity = os_activity_create("SecTrustStoreSetCARevocationAdditions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
438      os_activity_scope(activity);
439  
440      __block bool result = false;
441      securityd_send_sync_and_do(kSecXPCOpSetCARevocationAdditions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) {
442          SecXPCDictionarySetPListOptional(message, kSecTrustRevocationAdditionsKey, additions, block_error);
443          SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error);
444          return true;
445      }, ^bool(xpc_object_t response, CFErrorRef *block_error) {
446          result = SecXPCDictionaryGetBool(response, kSecXPCKeyResult, block_error);
447          return true;
448      });
449  
450      os_release(activity);
451      return result;
452  #else // TARGET_OS_BRIDGE
453      return SecError(errSecReadOnly, error, CFSTR("SecTrustStoreSetCARevocationAdditions not supported on bridgeOS"));
454  #endif // TARGET_OS_BRIDGE
455  }
456  
457  CFDictionaryRef SecTrustStoreCopyCARevocationAdditions(CFStringRef applicationIdentifier, CFErrorRef *error) {
458  #if !TARGET_OS_BRIDGE
459      do_if_registered(sec_trust_store_copy_ca_revocation_additions, applicationIdentifier, error);
460  
461      os_activity_t activity = os_activity_create("SecTrustStoreCopyCARevocationAdditions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
462      os_activity_scope(activity);
463  
464      __block CFDictionaryRef result = NULL;
465      securityd_send_sync_and_do(kSecXPCOpCopyCARevocationAdditions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) {
466          SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error);
467          return true;
468      }, ^bool(xpc_object_t response, CFErrorRef *block_error) {
469          (void)SecXPCDictionaryCopyDictionaryOptional(response, kSecTrustRevocationAdditionsKey, &result, block_error);
470          return true;
471      });
472  
473      os_release(activity);
474      return result;
475  #else // TARGET_OS_BRIDGE
476      SecError(errSecReadOnly, error, CFSTR("SecTrustStoreCopyCARevocationAdditions not supported on bridgeOS"));
477      return NULL;
478  #endif // TARGET_OS_BRIDGE
479  }
480  
481  /* MARK: Transparent Connection Pins */
482  
483  bool SecTrustStoreSetTransparentConnectionPins(CFStringRef applicationIdentifier, CFArrayRef pins, CFErrorRef *error) {
484  #if !TARGET_OS_BRIDGE
485      if (applicationIdentifier && gTrustd && gTrustd->sec_trust_store_set_transparent_connection_pins) {
486          return gTrustd->sec_trust_store_set_transparent_connection_pins(applicationIdentifier, pins, error);
487      } else if (gTrustd && gTrustd->sec_trust_store_set_transparent_connection_pins) {
488          /* When calling from the TrustTests, we need to pass the appID for the tests. Ordinarily,
489           * this is done by trustd using the client's entitlements. */
490          return gTrustd->sec_trust_store_set_transparent_connection_pins(CFSTR("com.apple.trusttests"), pins, error);
491      }
492  
493      os_activity_t activity = os_activity_create("SecTrustStoreSetTransparentConnectionPins", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
494      os_activity_scope(activity);
495  
496      __block bool result = false;
497      securityd_send_sync_and_do(kSecXPCOpSetTransparentConnectionPins, error, ^bool(xpc_object_t message, CFErrorRef *block_error) {
498          SecXPCDictionarySetPListOptional(message, kSecTrustAnchorsKey, pins, block_error);
499          SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error);
500          return true;
501      }, ^bool(xpc_object_t response, CFErrorRef *block_error) {
502          result = SecXPCDictionaryGetBool(response, kSecXPCKeyResult, block_error);
503          return true;
504      });
505  
506      os_release(activity);
507      return result;
508  #else // TARGET_OS_BRIDGE
509      return SecError(errSecReadOnly, error, CFSTR("SecTrustStoreSetTransparentConnectionPins not supported on bridgeOS"));
510  #endif // TARGET_OS_BRIDGE
511  }
512  
513  CF_RETURNS_RETAINED CFArrayRef SecTrustStoreCopyTransparentConnectionPins(CFStringRef applicationIdentifier, CFErrorRef *error) {
514  #if !TARGET_OS_BRIDGE
515      do_if_registered(sec_trust_store_copy_transparent_connection_pins, applicationIdentifier, error);
516  
517      os_activity_t activity = os_activity_create("SecTrustStoreCopyTransparentConnectionPins", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
518      os_activity_scope(activity);
519  
520      __block CFArrayRef result = NULL;
521      securityd_send_sync_and_do(kSecXPCOpCopyTransparentConnectionPins, error, ^bool(xpc_object_t message, CFErrorRef *block_error) {
522          SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error);
523          return true;
524      }, ^bool(xpc_object_t response, CFErrorRef *block_error) {
525          (void)SecXPCDictionaryCopyArrayOptional(response, kSecTrustAnchorsKey, &result, block_error);
526          return true;
527      });
528  
529      os_release(activity);
530      return result;
531  #else // TARGET_OS_BRIDGE
532      SecError(errSecReadOnly, error, CFSTR("SecTrustStoreCopyTransparentConnectionPins not supported on bridgeOS"));
533      return NULL;
534  #endif // TARGET_OS_BRIDGE
535  }