2 * Copyright (c) 2008-2010,2012,2016 Apple Inc. All Rights Reserved.
5 #include <Foundation/Foundation.h>
6 #include <Security/SecCertificate.h>
7 #include <Security/SecCertificatePriv.h>
8 #include <Security/SecItem.h>
9 #include <Security/SecItemPriv.h>
10 #include <Security/SecPolicy.h>
11 #include <Security/SecPolicyPriv.h>
12 #include <Security/SecTrust.h>
13 #include <Security/SecTrustSettings.h>
14 #include <Security/SecTrustSettingsPriv.h>
15 #include <Security/SecTrustPriv.h>
16 #include <utilities/SecCFRelease.h>
21 #include <Security/SecTrustStore.h>
23 #include <Security/SecKeychain.h>
26 #include "../TestMacroConversions.h"
27 #include "TrustSettingsTests_data.h"
28 #import "TrustEvaluationTestCase.h"
30 @interface TrustSettingsTests : TrustEvaluationTestCase
33 /* bridgeOS doesn't support trust settings */
37 #define setTS(cert, settings) \
39 ok_status(SecTrustStoreSetTrustSettings(defaultStore, cert, settings), \
40 "set trust settings"); \
43 /* Use admin store on OS X to avoid user prompts.
44 * Need a framework cert since we're interacting with keychain and trust settings.
45 * Sleep a little so trustd has time to get the KeychainEvent. */
46 #define setTS(cert, settings) \
48 SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \
49 ok_status(SecTrustSettingsSetTrustSettings(frameworkCert, kSecTrustSettingsDomainAdmin, \
50 settings), "set trust settings"); \
51 CFReleaseNull(frameworkCert); \
57 #define setTSFail(cert, settings) \
59 is(SecTrustStoreSetTrustSettings(defaultStore, cert, settings), errSecParam, \
60 "set trust settings"); \
63 #define setTSFail(cert, settings) \
65 SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \
66 is(SecTrustSettingsSetTrustSettings(frameworkCert, kSecTrustSettingsDomainAdmin, \
67 settings), errSecParam, "set trust settings"); \
68 CFReleaseNull(frameworkCert); \
73 #define removeTS(cert) \
75 ok_status(SecTrustStoreRemoveCertificate(defaultStore, cert), \
76 "remove trust settings"); \
79 #define removeTS(cert) \
81 SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \
82 ok_status(SecTrustSettingsRemoveTrustSettings(cert, kSecTrustSettingsDomainAdmin), \
83 "remove trust settings"); \
84 CFReleaseNull(frameworkCert); \
88 #define check_trust(certs, policy, valid_date, expected) \
90 SecTrustRef trust = NULL; \
91 SecTrustResultType trust_result; \
92 ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), \
93 "create trust with " #policy " policy"); \
94 ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)valid_date), \
95 "set trust verify date"); \
96 (void)SecTrustEvaluateWithError(trust, nil); \
97 ok_status(SecTrustGetTrustResult(trust, &trust_result), "get trust result"); \
98 is(trust_result, expected, \
99 "check trust result for " #policy " policy"); \
100 CFReleaseSafe(trust); \
103 static SecCertificateRef cert0 = NULL;
104 static SecCertificateRef cert1 = NULL;
105 static SecCertificateRef cert2 = NULL;
106 static SecCertificateRef cert3 = NULL;
107 static SecPolicyRef sslPolicy = NULL;
108 static SecPolicyRef smimePolicy = NULL;
109 static SecPolicyRef basicPolicy = NULL;
110 static CFArrayRef sslChain = NULL;
111 static CFArrayRef smimeChain = NULL;
112 static NSDate *verify_date = nil;
115 static SecTrustStoreRef defaultStore = NULL;
116 #define sslFrameworkPolicy sslPolicy
118 #define kSystemLoginKeychainPath "/Library/Keychains/System.keychain"
119 static NSMutableArray *deleteMeCertificates = NULL;
120 static SecPolicyRef sslFrameworkPolicy = NULL;
123 @implementation TrustSettingsTests
128 cert0 = SecCertificateCreateWithBytes(NULL, _trustSettingsRoot, sizeof(_trustSettingsRoot));
129 cert1 = SecCertificateCreateWithBytes(NULL, _trustSettingsInt, sizeof(_trustSettingsInt));
130 cert2 = SecCertificateCreateWithBytes(NULL, _trustSettingsSSLLeaf, sizeof(_trustSettingsSSLLeaf));
131 cert3 = SecCertificateCreateWithBytes(NULL, _trustSettingsSMIMELeaf, sizeof(_trustSettingsSMIMELeaf));
133 sslPolicy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com"));
134 smimePolicy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("username@apple.com"));
135 basicPolicy = SecPolicyCreateBasicX509();
137 const void *v_certs1[] = { cert2, cert1, cert0 };
138 sslChain = CFArrayCreate(NULL, v_certs1, sizeof(v_certs1)/sizeof(*v_certs1), &kCFTypeArrayCallBacks);
140 const void *v_certs2[] = { cert3, cert1, cert0 };
141 smimeChain = CFArrayCreate(NULL, v_certs2, sizeof(v_certs2)/sizeof(*v_certs2), &kCFTypeArrayCallBacks);
143 verify_date = [NSDate dateWithTimeIntervalSinceReferenceDate:482000000.0]; // Apr 10 2016
146 defaultStore = SecTrustStoreForDomain(kSecTrustStoreDomainUser);
148 /* We need a framework version of the policies in order to set policies in the trust settings */
149 sslFrameworkPolicy = SecFrameworkPolicyCreateSSL(true, CFSTR("testserver.apple.com"));
151 /* Since we're putting trust settings in the admin domain,
152 * we need to add the certs to the system keychain.
153 * Need a framework cert since we're interacting with keychain. */
154 SecKeychainRef kcRef = NULL;
155 CFArrayRef certRef = NULL;
156 NSDictionary *attrs = nil;
157 SecCertificateRef frameworkCert = NULL;
159 SecKeychainOpen(kSystemLoginKeychainPath, &kcRef);
164 deleteMeCertificates = [[NSMutableArray alloc] init];
166 frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert0);
167 attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert,
168 (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
169 (__bridge NSString*)kSecReturnPersistentRef: @YES};
170 if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
171 [deleteMeCertificates addObject:(__bridge NSArray *)certRef];
172 CFReleaseNull(certRef);
173 CFReleaseNull(frameworkCert);
175 frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert1);
176 attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert,
177 (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
178 (__bridge NSString*)kSecReturnPersistentRef: @YES};
179 if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
180 [deleteMeCertificates addObject:(__bridge NSArray *)certRef];
181 CFReleaseNull(certRef);
182 CFReleaseNull(frameworkCert);
184 frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert2);
185 attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert,
186 (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
187 (__bridge NSString*)kSecReturnPersistentRef: @YES};
188 if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
189 [deleteMeCertificates addObject:(__bridge NSArray *)certRef];
190 CFReleaseNull(certRef);
191 CFReleaseNull(frameworkCert);
193 frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert3);
194 attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert,
195 (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
196 (__bridge NSString*)kSecReturnPersistentRef: @YES};
197 if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
198 [deleteMeCertificates addObject:(__bridge NSArray *)certRef];
199 CFReleaseNull(certRef);
200 CFReleaseNull(frameworkCert);
202 CFReleaseNull(kcRef);
208 #if !TARGET_OS_IPHONE
209 [deleteMeCertificates enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
210 SecItemDelete((CFDictionaryRef)@{ (__bridge NSString*)kSecValuePersistentRef: [obj objectAtIndex:0]});
214 CFReleaseNull(cert0);
215 CFReleaseNull(cert1);
216 CFReleaseNull(cert2);
217 CFReleaseNull(cert3);
218 CFReleaseNull(sslPolicy);
219 CFReleaseNull(sslFrameworkPolicy);
220 CFReleaseNull(smimePolicy);
221 CFReleaseNull(basicPolicy);
222 CFReleaseNull(sslChain);
223 CFReleaseNull(smimeChain);
227 - (void)test_no_constraints
229 /* root with the default TrustRoot result succeeds */
231 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
234 /* intermediate with the default TrustRoot result fails */
235 setTSFail(cert1, NULL);
237 /* root with TrustRoot result succeeds */
238 NSDictionary *trustRoot = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
239 setTS(cert0, (__bridge CFDictionaryRef)trustRoot);
240 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
243 /* intermediate with TrustRoot fails to set */
244 setTSFail(cert1, (__bridge CFDictionaryRef)trustRoot);
246 /* root with TrustAsRoot fails to set */
247 NSDictionary *trustAsRoot = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
248 setTSFail(cert0, (__bridge CFDictionaryRef)trustAsRoot);
250 /* intermediate with TrustAsRoot result succeeds */
251 setTS(cert1, (__bridge CFDictionaryRef)trustAsRoot);
252 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
255 /* trusting the root but denying the intermediate fails */
256 NSDictionary *deny = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)};
258 setTS(cert1, (__bridge CFDictionaryRef)deny);
259 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultDeny);
263 /* the unspecified result gives us default behavior */
264 NSDictionary *unspecified = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)};
265 setTS(cert1, (__bridge CFDictionaryRef)unspecified);
266 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
269 /* trusting one leaf doesn't make other leaf trusted */
270 setTS(cert2, (__bridge CFDictionaryRef)trustAsRoot);
271 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
272 check_trust(smimeChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
276 - (void)test_policy_constraints
278 /* Trust only for SSL server. SSL server policy succeeds. */
279 NSDictionary *sslServerAllowed = @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy,
280 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) };
281 setTS(cert1, (__bridge CFDictionaryRef)sslServerAllowed);
282 check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
284 /* SSL client policy fails. */
285 SecPolicyRef sslClient = SecPolicyCreateSSL(false, NULL);
286 check_trust(sslChain, sslClient, verify_date, kSecTrustResultRecoverableTrustFailure);
287 CFReleaseNull(sslClient);
289 /* Basic policy fails */
290 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
294 - (void)test_policy_string_constraints
296 NSArray *hostnameAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy,
297 (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongname.apple.com"),
298 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) },
299 @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy,
300 (__bridge NSString*)kSecTrustSettingsPolicyString: @("testserver.apple.com"),
301 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) }
303 setTS(cert2, (__bridge CFArrayRef)hostnameAllowed);
304 /* evaluating against trusted hostname passes */
305 check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
307 /* evaluating against hostname not in trust settings is recoverable failure */
308 SecPolicyRef weirdnamePolicy = SecPolicyCreateSSL(true, CFSTR("weirdname.apple.com"));
309 check_trust(sslChain, weirdnamePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
310 CFReleaseNull(weirdnamePolicy);
312 /* evaluating against hostname denied by trust settings is denied */
313 SecPolicyRef wrongnamePolicy = SecPolicyCreateSSL(true, CFSTR("wrongname.apple.com"));
314 check_trust(sslChain, wrongnamePolicy, verify_date, kSecTrustResultDeny);
315 CFReleaseNull(wrongnamePolicy);
319 #define smimeFrameworkPolicy smimePolicy
321 SecPolicyRef smimeFrameworkPolicy= SecFrameworkPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("username@apple.com"));
324 NSArray *emailAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimeFrameworkPolicy,
325 (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongemail@apple.com"),
326 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) },
327 @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimeFrameworkPolicy,
328 (__bridge NSString*)kSecTrustSettingsPolicyString: @("username@apple.com"),
329 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) }
331 setTS(cert3, (__bridge CFArrayRef)emailAllowed);
332 /* evaluating against trusted email passes */
333 check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultProceed);
335 /* evaluating against hostname not in trust settings is recoverable failure */
336 SecPolicyRef weirdemailPolicy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("weirdemail@apple.com"));
337 check_trust(smimeChain, weirdemailPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
338 CFReleaseNull(weirdemailPolicy);
340 /* evaluating against hostname denied by trust settings is denied */
341 SecPolicyRef wrongemailPolicy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("wrongemail@apple.com"));
342 check_trust(smimeChain, wrongemailPolicy, verify_date, kSecTrustResultDeny);
343 CFReleaseNull(wrongemailPolicy);
347 CFReleaseNull(smimeFrameworkPolicy);
352 #include <Security/SecTrustedApplicationPriv.h>
353 - (void)test_application_constraints
355 SecTrustedApplicationRef thisApp = NULL, someOtherApp = NULL;
357 #pragma clang diagnostic push
358 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
359 ok_status(SecTrustedApplicationCreateFromPath("/AppleInternal/CoreOS/tests/Security/TrustTests", &thisApp),
360 "create TrustedApplicationRef for this app");
361 ok_status(SecTrustedApplicationCreateFromPath("/Applications/Safari.app", &someOtherApp),
362 "create TrustedApplicationRef for Safari");
363 #pragma clang diagnostic pop
365 NSDictionary *thisAppTS = @{ (__bridge NSString*)kSecTrustSettingsApplication: (__bridge id)thisApp,
366 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
368 NSDictionary *someOtherAppTS = @{ (__bridge NSString*)kSecTrustSettingsApplication: (__bridge id)someOtherApp,
369 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
371 /* This application Trust Setting succeeds */
372 setTS(cert0, (__bridge CFDictionaryRef)thisAppTS);
373 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
376 /* Some other application Trust Setting fails */
377 setTS(cert0, (__bridge CFDictionaryRef)someOtherAppTS);
378 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
381 CFReleaseNull(thisApp);
382 CFReleaseNull(someOtherApp);
384 #endif // TARGET_OS_OSX
386 - (void)test_key_usage_constraints {
387 /* any key usage succeeds */
388 NSDictionary *anyKeyUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseAny),
389 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
390 setTS(cert0, (__bridge CFDictionaryRef)anyKeyUse);
391 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
394 /* signCert key usage on an intermediate or root succeeds */
395 NSDictionary *signCertUseRoot = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseSignCert),
396 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
397 setTS(cert0, (__bridge CFDictionaryRef)signCertUseRoot);
398 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
401 NSDictionary *signCertUseInt = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseSignCert),
402 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
403 setTS(cert1, (__bridge CFDictionaryRef)signCertUseInt);
404 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
407 /* intermediate without signCert key usage fails */
408 NSDictionary *signatureUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseSignature),
409 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
410 setTS(cert1, (__bridge CFDictionaryRef)signatureUse);
411 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
414 /* brief interlude to create a bunch of SMIME policies with different key usages */
415 SecPolicyRef smimeSignature = SecPolicyCreateSMIME(kSecSignSMIMEUsage, CFSTR("username@apple.com"));
416 SecPolicyRef smimeDataEncrypt = SecPolicyCreateSMIME(kSecDataEncryptSMIMEUsage, CFSTR("username@apple.com"));
417 SecPolicyRef smimeKeyEncrypt = SecPolicyCreateSMIME(kSecKeyEncryptSMIMEUsage, CFSTR("username@apple.com"));
418 SecPolicyRef smimeKeyExchange = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, CFSTR("username@apple.com"));
419 SecPolicyRef smimeMultiple = SecPolicyCreateSMIME((kSecSignSMIMEUsage | kSecKeyEncryptSMIMEUsage),
420 CFSTR("username@apple.com"));
422 /* signature smime policy passes for signature use TS*/
423 setTS(cert3, (__bridge CFDictionaryRef)signatureUse);
424 check_trust(smimeChain, smimeSignature, verify_date, kSecTrustResultProceed);
426 /* any use policy fails for signature use TS */
427 check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
429 /* multiple use smime policy against signature use */
430 check_trust(smimeChain, smimeMultiple, verify_date, kSecTrustResultRecoverableTrustFailure);
433 /* key encrypt smime policy passes for key encrypt use */
434 NSDictionary *keyEncryptUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseEnDecryptKey),
435 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
436 setTS(cert3, (__bridge CFDictionaryRef)keyEncryptUse);
437 check_trust(smimeChain, smimeKeyEncrypt, verify_date, kSecTrustResultProceed);
440 /* multiple use smime policy against multiple uses */
441 NSDictionary *multipleUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseEnDecryptKey |
442 kSecTrustSettingsKeyUseSignature),
443 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
444 setTS(cert3, (__bridge CFDictionaryRef)multipleUse)
445 check_trust(smimeChain, smimeMultiple, verify_date, kSecTrustResultProceed);
447 /* signature smime policy against multiple uses */
448 check_trust(smimeChain, smimeSignature, verify_date, kSecTrustResultRecoverableTrustFailure);
450 /* any use smime policy against multiple uses */
451 check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
454 CFReleaseNull(smimeSignature);
455 CFReleaseNull(smimeDataEncrypt);
456 CFReleaseNull(smimeKeyEncrypt);
457 CFReleaseNull(smimeKeyExchange);
458 CFReleaseNull(smimeMultiple);
461 - (void)test_allowed_errors
465 /* allow expired errors */
466 NSDate *expired_date = [NSDate dateWithTimeIntervalSinceReferenceDate:520000000.0]; // Jun 24 2017
467 check_trust(sslChain, basicPolicy, expired_date, kSecTrustResultRecoverableTrustFailure);
469 NSDictionary *allowExpired = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147409654),
470 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)};
471 setTS(cert1, (__bridge CFDictionaryRef)allowExpired)
472 setTS(cert2, (__bridge CFDictionaryRef)allowExpired);
473 check_trust(sslChain, basicPolicy, expired_date, kSecTrustResultProceed);
477 /* allow hostname mismatch errors */
478 SecPolicyRef wrongNameSSL = NULL;
479 wrongNameSSL = SecPolicyCreateSSL(true, CFSTR("wrongname.apple.com"));
480 check_trust(sslChain, wrongNameSSL, verify_date, kSecTrustResultRecoverableTrustFailure);
482 NSDictionary *allowHostnameMismatch = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408896),
483 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) };
484 setTS(cert2, (__bridge CFDictionaryRef)allowHostnameMismatch);
485 sleep(1); // sleep a little extra so trustd gets trust settings event before evaluating leaf
486 check_trust(sslChain, wrongNameSSL, verify_date, kSecTrustResultProceed);
488 CFReleaseNull(wrongNameSSL);
490 /* allow email mismatch errors */
491 SecPolicyRef wrongNameSMIME = NULL;
492 wrongNameSMIME = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("test@apple.com"));
493 check_trust(smimeChain, wrongNameSMIME, verify_date, kSecTrustResultRecoverableTrustFailure);
495 NSDictionary *allowEmailMismatch = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408872),
496 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) };
497 setTS(cert3, (__bridge CFDictionaryRef)allowEmailMismatch);
498 sleep(1); // sleep a little extra so trustd gets trust settings event before evaluating leaf
499 check_trust(smimeChain, wrongNameSMIME, verify_date, kSecTrustResultProceed);
501 CFReleaseNull(wrongNameSMIME);
503 /* allowed error with a policy constraint */
504 NSDictionary *allowExpiredConstrained = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147409654),
505 (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy,
506 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)};
507 setTS(cert1, (__bridge CFDictionaryRef)allowExpiredConstrained)
508 setTS(cert2, (__bridge CFDictionaryRef)allowExpiredConstrained);
509 check_trust(sslChain, sslPolicy, expired_date, kSecTrustResultProceed);
510 check_trust(sslChain, basicPolicy, expired_date, kSecTrustResultRecoverableTrustFailure);
517 - (void)test_multiple_constraints
520 NSArray *denyAllBut = @[
521 @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy ,
522 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)},
523 @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) }
525 setTS(cert0, (__bridge CFArrayRef)denyAllBut);
526 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultDeny);
527 check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
531 NSArray *allowAllBut = @[
532 @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy ,
533 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)},
534 @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
536 setTS(cert0, (__bridge CFArrayRef)allowAllBut);
537 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
538 check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
542 #define basicFrameworkPolicy basicPolicy
544 SecPolicyRef basicFrameworkPolicy = SecFrameworkPolicyCreateBasicX509();
547 /* different results for specific policies */
548 NSArray *specifyPolicyResult = @[
549 @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy,
550 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)},
551 @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)basicFrameworkPolicy,
552 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
554 setTS(cert0, (__bridge CFArrayRef)specifyPolicyResult);
555 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
556 check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultDeny);
557 check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
560 /* different results for additional constraint with same policy */
561 NSArray *policyConstraintResult = @[
562 @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy,
563 (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongname.apple.com"),
564 (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408896),
565 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)},
566 @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy,
567 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) }
569 SecPolicyRef wrongNameSSL = NULL;
570 wrongNameSSL = SecPolicyCreateSSL(true, CFSTR("wrongname.apple.com"));
571 setTS(cert2, (__bridge CFArrayRef)policyConstraintResult);
572 sleep(1); // sleep a little extra so trustd gets trust settings event before evaluating leaf
573 check_trust(sslChain, wrongNameSSL, verify_date, kSecTrustResultProceed);
574 check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
576 CFReleaseNull(wrongNameSSL);
579 CFReleaseNull(basicFrameworkPolicy);
583 - (void)test_change_constraints
586 NSArray *allowAllBut = @[
587 @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy ,
588 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)},
589 @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
591 setTS(cert0, (__bridge CFArrayRef)allowAllBut);
592 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
593 check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
595 /* Don't clear trust settings. Just change them. */
597 /* root with the default TrustRoot result succeeds */
599 check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
600 check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
604 - (void)test_policy_name_pinning_constraints
606 /* need a new policy object for this test so we don't mess up the policy used by the other tests */
607 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com"));
609 #define frameworkPolicy policy
611 SecPolicyRef frameworkPolicy = SecFrameworkPolicyCreateSSL(true, CFSTR("testserver.apple.com"));
615 NSArray *allowAllBut = @[
616 @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)frameworkPolicy ,
617 (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)},
618 @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
620 setTS(cert0, (__bridge CFArrayRef)allowAllBut);
622 SecTrustRef trust = NULL;
623 ok_status(SecTrustCreateWithCertificates(sslChain, policy, &trust), "create trust with ssl policy");
624 ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verify_date), "set trust verify date");
625 ok_status(SecTrustSetPinningPolicyName(trust, CFSTR("not-a-db-policy-name")), "set policy name");
626 XCTAssertFalse(SecTrustEvaluateWithError(trust, nil), "evaluate trust");
627 CFReleaseSafe(trust);
628 CFReleaseNull(policy);
629 CFReleaseNull(frameworkPolicy);
635 - (void)testDistrustSystemRoot
637 // Users can distrust system roots
638 id systemRoot = [self SecCertificateCreateFromResource:@"DigiCertGlobalRootG3" subdirectory:@"si-20-sectrust-policies-data"];
639 NSDictionary *deny = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)};
640 id persistentRef = [self addTrustSettingsForCert:(__bridge SecCertificateRef)systemRoot trustSettings:deny];
641 TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[systemRoot] policies:nil];
642 [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; // January 6, 2020 at 2:40:00 AM PST
643 XCTAssertFalse([eval evaluate:nil]);
644 XCTAssertEqual(eval.trustResult, kSecTrustResultDeny);
645 [self removeTrustSettingsForCert:(__bridge SecCertificateRef)systemRoot persistentRef:persistentRef];
648 - (void)testDistrustAppleRoot
650 // Users cannot distrust the Apple Roots
651 id appleRoot = [self SecCertificateCreateFromResource:@"AppleRootCA" subdirectory:@"si-20-sectrust-policies-data"];
652 NSDictionary *deny = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)};
653 id persistentRef = [self addTrustSettingsForCert:(__bridge SecCertificateRef)appleRoot trustSettings:deny];
654 TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[appleRoot] policies:nil];
655 [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; // January 6, 2020 at 2:40:00 AM PST
656 XCTAssert([eval evaluate:nil]);
657 XCTAssertEqual(eval.trustResult, kSecTrustResultProceed);
658 [self removeTrustSettingsForCert:(__bridge SecCertificateRef)appleRoot persistentRef:persistentRef];
661 - (void)testFatalResultsNonOverride
663 id root = [self SecCertificateCreateFromPEMResource:@"ca-ki" subdirectory:@"si-88-sectrust-valid-data"];
664 id revokedLeaf = [self SecCertificateCreateFromPEMResource:@"leaf-ki-revoked1" subdirectory:@"si-88-sectrust-valid-data"];
665 TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[revokedLeaf, root] policies:nil];
666 [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:542400000.0]]; // March 10, 2018 at 10:40:00 AM PST
667 [eval setAnchors:@[root]];
668 XCTAssertFalse([eval evaluate:nil]);
669 XCTAssertEqual(eval.trustResult, kSecTrustResultFatalTrustFailure);
671 /* still fatal failure if trust settings on root */
672 id persistentRef = [self addTrustSettingsForCert:(__bridge SecCertificateRef)root];
673 [eval setNeedsEvaluation];
674 XCTAssertFalse([eval evaluate:nil]);
675 XCTAssertEqual(eval.trustResult, kSecTrustResultFatalTrustFailure);
676 [self removeTrustSettingsForCert:(__bridge SecCertificateRef)root persistentRef:persistentRef];
681 #else // TARGET_OS_BRIDGE
682 @implementation TrustSettingsTests
683 - (void)testSkipTests