]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecTrustStore.c
Security-59306.11.20.tar.gz
[apple/security.git] / OSX / sec / Security / SecTrustStore.c
1 /*
2 * Copyright (c) 2007-2018 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
51 SecTrustStoreRef SecTrustStoreForDomain(SecTrustStoreDomain domain) {
52 CFStringRef domainName;
53 if (domain == kSecTrustStoreDomainUser) {
54 domainName = kSecTrustStoreUserName;
55 } else {
56 return NULL;
57 }
58
59 if (gTrustd) {
60 return gTrustd->sec_trust_store_for_domain(domainName, NULL);
61 } else {
62 return (SecTrustStoreRef)domainName;
63 }
64 }
65
66 static bool string_data_to_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFDataRef digest, CFErrorRef *error)
67 {
68 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
69 return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) &&
70 SecXPCDictionarySetData(message, kSecXPCKeyDigest, digest, blockError);
71 }, NULL);
72 }
73
74 static bool string_data_to_bool_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFDataRef digest, bool *result, CFErrorRef *error)
75 {
76 os_activity_t activity = os_activity_create("SecTrustStoreContains", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
77 os_activity_scope(activity);
78 bool status = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
79 return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) &&
80 SecXPCDictionarySetData(message, kSecXPCKeyDigest, digest, error);
81 }, ^bool(xpc_object_t response, CFErrorRef *blockError) {
82 if (result)
83 *result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
84 return true;
85 });
86 os_release(activity);
87 return status;
88 }
89
90 Boolean SecTrustStoreContains(SecTrustStoreRef ts,
91 SecCertificateRef certificate) {
92 CFDataRef digest;
93 bool ok = false;
94 __block bool contains = false;
95
96 require(ts, errOut);
97 require(digest = SecCertificateGetSHA1Digest(certificate), errOut);
98
99
100 ok = (SecOSStatusWith(^bool (CFErrorRef *error) {
101 return TRUSTD_XPC(sec_trust_store_contains, string_data_to_bool_bool_error, ts, digest, &contains, error);
102 }) == errSecSuccess);
103
104 errOut:
105 return ok && contains;
106 }
107
108 static bool SecXPCDictionarySetCertificate(xpc_object_t message, const char *key, SecCertificateRef certificate, CFErrorRef *error) {
109 if (certificate) {
110 xpc_dictionary_set_data(message, key, SecCertificateGetBytePtr(certificate),
111 SecCertificateGetLength(certificate));
112 return true;
113 }
114 return SecError(errSecParam, error, CFSTR("NULL certificate"));
115 }
116
117
118 static bool string_cert_cftype_to_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef certificate, CFTypeRef trustSettingsDictOrArray, CFErrorRef *error)
119 {
120 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
121 bool ok = false;
122 ok = SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) &&
123 SecXPCDictionarySetCertificate(message, kSecXPCKeyCertificate, certificate, blockError) &&
124 (!trustSettingsDictOrArray || SecXPCDictionarySetPList(message, kSecXPCKeySettings, trustSettingsDictOrArray, blockError));
125 return ok;
126 }, NULL);
127 }
128
129 static OSStatus validateConstraint(Boolean isSelfSigned, CFMutableDictionaryRef trustSettingsDict) {
130 OSStatus result = errSecSuccess;
131
132 /* Check "TrustRoot"/"TrustAsRoot" */
133 CFNumberRef resultNumber = NULL;
134 resultNumber = (CFNumberRef)CFDictionaryGetValue(trustSettingsDict, kSecTrustSettingsResult);
135 uint32_t resultValue = kSecTrustSettingsResultInvalid;
136 if (!isNumber(resultNumber) && !isSelfSigned) {
137 /* only self-signed certs get default of TrustAsRoot */
138 return errSecParam;
139 }
140 if (isNumber(resultNumber) && CFNumberGetValue(resultNumber, kCFNumberSInt32Type, &resultValue)) {
141 if (isSelfSigned && resultValue == kSecTrustSettingsResultTrustAsRoot) {
142 return errSecParam;
143 }
144 if (!isSelfSigned && resultValue == kSecTrustSettingsResultTrustRoot) {
145 return errSecParam;
146 }
147 }
148
149 /* If there's a policy specified, change the contents */
150 SecPolicyRef policy = NULL;
151 policy = (SecPolicyRef)CFDictionaryGetValue(trustSettingsDict, kSecTrustSettingsPolicy);
152 if (policy) {
153 CFStringRef policyOid = NULL, policyName = NULL;
154 policyOid = SecPolicyGetOidString(policy);
155 policyName = SecPolicyGetName(policy);
156 CFDictionarySetValue(trustSettingsDict, kSecTrustSettingsPolicy, policyOid);
157 if (policyName) { CFDictionaryAddValue(trustSettingsDict, kSecTrustSettingsPolicyName, policyName); }
158 }
159
160 return result;
161 }
162
163 static OSStatus validateTrustSettings(Boolean isSelfSigned,
164 CFTypeRef trustSettingsDictOrArray,
165 CFTypeRef * CF_RETURNS_RETAINED modifiedTrustSettings) {
166 OSStatus status = errSecParam;
167 CFTypeRef result = NULL;
168
169 /* NULL is a valid input */
170 if (!trustSettingsDictOrArray && isSelfSigned) {
171 return errSecSuccess;
172 } else if (!trustSettingsDictOrArray && !isSelfSigned) {
173 return errSecParam;
174 }
175
176 if (CFDictionaryGetTypeID() == CFGetTypeID(trustSettingsDictOrArray)) {
177 result = CFDictionaryCreateMutableCopy(NULL, 0, trustSettingsDictOrArray);
178 status = validateConstraint(isSelfSigned, (CFMutableDictionaryRef)result);
179 } else if (CFArrayGetTypeID() == CFGetTypeID(trustSettingsDictOrArray)) {
180 require_action_quiet(result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks),
181 out, status = errSecAllocate);
182 CFIndex ix, count = CFArrayGetCount(trustSettingsDictOrArray);
183 for (ix = 0; ix < count; ix++) {
184 CFDictionaryRef constraint = CFArrayGetValueAtIndex(trustSettingsDictOrArray, ix);
185 CFDictionaryRef modifiedConstraint = NULL;
186 require_noerr_quiet(status = validateTrustSettings(isSelfSigned, constraint, (CFTypeRef *)&modifiedConstraint), out);
187 CFArrayAppendValue((CFMutableArrayRef)result, modifiedConstraint);
188 CFReleaseNull(modifiedConstraint); /* constraint now owned by array */
189 }
190 }
191
192 out:
193 if (errSecSuccess == status && modifiedTrustSettings) {
194 *modifiedTrustSettings = CFRetainSafe(result);
195 }
196 CFReleaseNull(result);
197 return status;
198 }
199
200 OSStatus SecTrustStoreSetTrustSettings(SecTrustStoreRef ts,
201 SecCertificateRef certificate,
202 CFTypeRef trustSettingsDictOrArray) {
203 __block OSStatus result;
204 __block CFTypeRef validatedTrustSettings = NULL;
205
206 Boolean isSelfSigned = false;
207 require_noerr_quiet(result = SecCertificateIsSelfSigned(certificate, &isSelfSigned), out);
208 require_noerr_quiet(result = validateTrustSettings(isSelfSigned, trustSettingsDictOrArray, &validatedTrustSettings), out);
209
210 os_activity_initiate("SecTrustStoreSetTrustSettings", OS_ACTIVITY_FLAG_DEFAULT, ^{
211 result = SecOSStatusWith(^bool (CFErrorRef *error) {
212 return TRUSTD_XPC(sec_trust_store_set_trust_settings, string_cert_cftype_to_error, ts, certificate, validatedTrustSettings, error);
213 });
214 });
215
216 out:
217 CFReleaseNull(validatedTrustSettings);
218 return result;
219 }
220
221 OSStatus SecTrustStoreRemoveCertificate(SecTrustStoreRef ts,
222 SecCertificateRef certificate)
223 {
224 CFDataRef digest;
225 __block OSStatus status = errSecParam;
226
227 os_activity_t activity = os_activity_create("SecTrustStoreRemoveCertificate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
228 os_activity_scope(activity);
229 require(ts, errOut);
230 require(digest = SecCertificateGetSHA1Digest(certificate), errOut);
231 require(gTrustd || ts == (SecTrustStoreRef)kSecTrustStoreUserName, errOut);
232
233 status = SecOSStatusWith(^bool (CFErrorRef *error) {
234 return TRUSTD_XPC(sec_trust_store_remove_certificate, string_data_to_bool_error, ts, digest, error);
235 });
236
237 errOut:
238 os_release(activity);
239 return status;
240 }
241
242 OSStatus SecTrustStoreGetSettingsVersionNumber(SecTrustSettingsVersionNumber* p_settings_version_number)
243 {
244 if (NULL == p_settings_version_number) {
245 return errSecParam;
246 }
247
248 OSStatus status = errSecSuccess;
249 CFErrorRef error = nil;
250 uint64_t versionNumber = SecTrustGetTrustStoreVersionNumber(&error);
251 *p_settings_version_number = (SecTrustSettingsVersionNumber)versionNumber;
252
253 if (error) {
254 status = (OSStatus)CFErrorGetCode(error);
255 }
256 CFReleaseSafe(error);
257 return status;
258 }
259
260 OSStatus SecTrustStoreGetSettingsAssetVersionNumber(SecTrustSettingsAssetVersionNumber* p_settings_asset_version_number)
261 {
262 if (NULL == p_settings_asset_version_number) {
263 return errSecParam;
264 }
265
266 OSStatus status = errSecSuccess;
267 CFErrorRef error = nil;
268 uint64_t versionNumber = SecTrustGetAssetVersionNumber(&error);
269 *p_settings_asset_version_number = (SecTrustSettingsAssetVersionNumber)versionNumber;
270
271 if (error) {
272 status = (OSStatus)CFErrorGetCode(error);
273 }
274 CFReleaseSafe(error);
275 return status;
276 }
277
278 static bool string_to_array_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error)
279 {
280 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
281 return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError);
282 }, ^bool(xpc_object_t response, CFErrorRef *blockError) {
283 if (trustStoreContents) {
284 *trustStoreContents = SecXPCDictionaryCopyArray(response, kSecXPCKeyResult, blockError);
285 if (!*trustStoreContents) return false;
286 }
287 return true;
288 });
289 }
290
291 OSStatus SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents)
292 {
293 __block CFArrayRef results = NULL;
294 OSStatus status = errSecParam;
295
296 os_activity_t activity = os_activity_create("SecTrustStoreCopyAll", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
297 os_activity_scope(activity);
298 require(ts, errOut);
299
300 status = SecOSStatusWith(^bool (CFErrorRef *error) {
301 return TRUSTD_XPC(sec_trust_store_copy_all, string_to_array_error, ts, &results, error);
302 });
303
304 *trustStoreContents = results;
305
306 errOut:
307 os_release(activity);
308 return status;
309 }
310
311 static bool string_data_to_array_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFDataRef digest, CFArrayRef *usageConstraints, CFErrorRef *error)
312 {
313 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) {
314 return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) &&
315 SecXPCDictionarySetData(message, kSecXPCKeyDigest, digest, blockError);
316 }, ^bool(xpc_object_t response, CFErrorRef *blockError) {
317 return SecXPCDictionaryCopyArrayOptional(response, kSecXPCKeyResult, usageConstraints, blockError);
318 });
319 }
320
321 OSStatus SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, SecCertificateRef certificate, CFArrayRef *usageConstraints)
322 {
323 CFDataRef digest;
324 __block CFArrayRef results = NULL;
325 OSStatus status = errSecParam;
326
327 os_activity_t activity = os_activity_create("SecTrustStoreCopyUsageConstraints", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
328 os_activity_scope(activity);
329 require(ts, errOut);
330 require(certificate, errOut);
331 require(digest = SecCertificateGetSHA1Digest(certificate), errOut);
332 require(usageConstraints, errOut);
333
334 status = SecOSStatusWith(^bool (CFErrorRef *error) {
335 return TRUSTD_XPC(sec_trust_store_copy_usage_constraints, string_data_to_array_error, ts, digest, &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 /* MARK: CT Enforcement Exceptions */
348
349 const CFStringRef kSecCTExceptionsCAsKey = CFSTR("DisabledForCAs");
350 const CFStringRef kSecCTExceptionsDomainsKey = CFSTR("DisabledForDomains");
351 const CFStringRef kSecCTExceptionsHashAlgorithmKey = CFSTR("HashAlgorithm");
352 const CFStringRef kSecCTExceptionsSPKIHashKey = CFSTR("SubjectPublicKeyInfoHash");
353
354 bool SecTrustStoreSetCTExceptions(CFStringRef applicationIdentifier, CFDictionaryRef exceptions, CFErrorRef *error) {
355 #if !TARGET_OS_BRIDGE
356 if (applicationIdentifier && gTrustd && gTrustd->sec_trust_store_set_ct_exceptions) {
357 return gTrustd->sec_trust_store_set_ct_exceptions(applicationIdentifier, exceptions, error);
358 } else if (gTrustd && gTrustd->sec_trust_store_set_ct_exceptions) {
359 /* When calling from the TrustTests, we need to pass the appID for the tests. Ordinarily,
360 * this is done by trustd using the client's entitlements. */
361 return gTrustd->sec_trust_store_set_ct_exceptions(CFSTR("com.apple.trusttests"), exceptions, error);
362 }
363
364 os_activity_t activity = os_activity_create("SecTrustStoreSetCTExceptions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
365 os_activity_scope(activity);
366
367 __block bool result = false;
368 securityd_send_sync_and_do(kSecXPCOpSetCTExceptions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) {
369 SecXPCDictionarySetPListOptional(message, kSecTrustExceptionsKey, exceptions, block_error);
370 SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error);
371 return true;
372 }, ^bool(xpc_object_t response, CFErrorRef *block_error) {
373 result = SecXPCDictionaryGetBool(response, kSecXPCKeyResult, block_error);
374 return true;
375 });
376
377 os_release(activity);
378 return result;
379 #else // TARGET_OS_BRIDGE
380 return SecError(errSecReadOnly, error, CFSTR("SecTrustStoreSetCTExceptions not supported on bridgeOS"));
381 #endif // TARGET_OS_BRIDGE
382 }
383
384 CFDictionaryRef SecTrustStoreCopyCTExceptions(CFStringRef applicationIdentifier, CFErrorRef *error) {
385 #if !TARGET_OS_BRIDGE
386 do_if_registered(sec_trust_store_copy_ct_exceptions, applicationIdentifier, error);
387
388 os_activity_t activity = os_activity_create("SecTrustStoreCopyCTExceptions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
389 os_activity_scope(activity);
390
391 __block CFDictionaryRef result = NULL;
392 securityd_send_sync_and_do(kSecXPCOpCopyCTExceptions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) {
393 SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error);
394 return true;
395 }, ^bool(xpc_object_t response, CFErrorRef *block_error) {
396 (void)SecXPCDictionaryCopyDictionaryOptional(response, kSecTrustExceptionsKey, &result, block_error);
397 return true;
398 });
399
400 os_release(activity);
401 return result;
402 #else // TARGET_OS_BRIDGE
403 SecError(errSecReadOnly, error, CFSTR("SecTrustStoreCopyCTExceptions not supported on bridgeOS"));
404 return NULL;
405 #endif // TARGET_OS_BRIDGE
406 }