2 * Copyright (c) 2018 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <AssertMacros.h>
26 #import <XCTest/XCTest.h>
27 #include <Security/SecCertificatePriv.h>
28 #include <Security/SecPolicyPriv.h>
29 #include <Security/SecTrustPriv.h>
30 #include "OSX/utilities/SecCFWrappers.h"
31 #include <Security/SecTrustSettings.h>
32 #include <Security/SecTrustSettingsPriv.h>
33 #include <Security/SecFramework.h>
34 #include "trust/trustd/OTATrustUtilities.h"
37 #import <OCMock/OCMock.h>
41 #include <Security/SecTrustStore.h>
43 #include <Security/SecKeychain.h>
47 #import <MobileAsset/MAAsset.h>
48 #import <MobileAsset/MAAssetQuery.h>
51 #import "TrustEvaluationTestCase.h"
52 #import "CTTests_data.h"
53 #include "../TestMacroConversions.h"
55 @interface CTTests : TrustEvaluationTestCase
59 @implementation CTTests
61 + (id) CF_RETURNS_RETAINED SecCertificateCreateFromResource:(NSString *)name {
62 NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:name withExtension:@".cer" subdirectory:@"si-82-sectrust-ct-data"];
63 NSData *certData = [NSData dataWithContentsOfURL:url];
64 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData);
65 return (__bridge id)cert;
68 + (NSData *)DataFromResource:(NSString *)name {
69 NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:name withExtension:@".bin" subdirectory:@"si-82-sectrust-ct-data"];
70 return [NSData dataWithContentsOfURL:url];
73 - (NSDictionary *)eval_ct_trust:(NSArray *)certs
75 ocspResponses:(NSArray *)ocsps
76 anchors:(NSArray *)anchors
77 trustedCTLogs:(NSArray *)trustedLogs
78 hostname:(NSString *)hostname
79 verifyDate:(NSDate *)date {
81 /* Create the trust object */
82 TestTrustEvaluation *trust = nil;
83 SecPolicyRef policy = SecPolicyCreateBasicX509(); // <rdar://problem/50066309> Need to generate new certs for CTTests
84 XCTAssertNotNil(trust = [[TestTrustEvaluation alloc] initWithCertificates:certs policies:@[(__bridge id)policy]],
85 "create trust failed");
86 CFReleaseNull(policy);
87 if (!trust) { return nil; }
89 /* Set the optional properties */
90 if (scts) { trust.presentedSCTs = scts; }
91 if (ocsps) { trust.ocspResponses = ocsps; }
92 if (anchors) { trust.anchors = anchors; }
93 if (trustedLogs) { trust.trustedCTLogs = trustedLogs; }
94 if (date) { trust.verifyDate = date; }
98 XCTAssert([trust evaluate:&error], "failed trust evaluation: %@", error);
99 return trust.resultDictionary;
102 static NSArray *anchors = nil;
103 static NSDate *date_20150307 = nil;
104 static NSDate *date_20160422 = nil;
105 static NSArray *trustedCTLogs = nil;
109 SecCertificateRef anchor1 = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"CA_alpha"];
110 SecCertificateRef anchor2 = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"CA_beta"];
111 anchors = @[ (__bridge id)anchor1, (__bridge id)anchor2];
112 CFReleaseNull(anchor1);
113 CFReleaseNull(anchor2);
114 date_20150307 = [NSDate dateWithTimeIntervalSinceReferenceDate:447450000.0]; // March 7, 2015 at 11:40:00 AM PST
115 date_20160422 = [NSDate dateWithTimeIntervalSinceReferenceDate:483050000.0]; // April 22, 2016 at 1:33:20 PM PDT
117 NSURL *trustedLogsURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"CTlogs"
118 withExtension:@"plist"
119 subdirectory:@"si-82-sectrust-ct-data"];
120 trustedCTLogs = [NSArray arrayWithContentsOfURL:trustedLogsURL];
122 #if !TARGET_OS_BRIDGE
123 /* Mock a successful mobile asset check-in so that we enforce CT */
124 UpdateOTACheckInDate();
128 - (void)testOneEmbeddedSCT {
129 NSDictionary *results = nil;
130 SecCertificateRef certF = nil;
131 isnt(certF = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverF"], NULL, "create certF");
132 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certF] sCTs:nil ocspResponses:nil anchors:anchors
133 trustedCTLogs:trustedCTLogs hostname:nil verifyDate:date_20150307]);
134 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
135 XCTAssertNil(results[(__bridge NSString*)kSecTrustExtendedValidation], "got EV result when no EV expected");
136 CFReleaseNull(certF);
139 - (void)testOnePresentedSCT {
140 NSDictionary *results = nil;
141 SecCertificateRef certD = nil;
142 NSData *proofD = nil;
143 isnt(certD = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverD"], NULL, "create certD");
144 XCTAssertNotNil(proofD = [CTTests DataFromResource:@"serverD_proof"], "create proofD");
145 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certD] sCTs:@[proofD] ocspResponses:nil anchors:anchors
146 trustedCTLogs:trustedCTLogs hostname:nil verifyDate:date_20150307]);
147 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
148 XCTAssertNil(results[(__bridge NSString*)kSecTrustExtendedValidation], "got EV result when no EV expected");
149 CFReleaseNull(certD);
152 - (void)testTooFewEmbeddedSCTsForLifetime {
153 NSDictionary *results = nil;
154 SecCertificateRef leaf = nil, subCA = nil, root = nil;
155 isnt(leaf = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"www_digicert_com_2015"], NULL, "create leaf");
156 isnt(subCA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"digicert_sha2_ev_server_ca"], NULL, "create subCA");
157 isnt(root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"digicert_ev_root_ca"], NULL, "create root");
158 NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCA];
159 XCTAssertNotNil(results = [self eval_ct_trust:certs
160 sCTs:nil ocspResponses:nil anchors:@[(__bridge id)root]
161 trustedCTLogs:nil hostname:@"www.digicert.com" verifyDate:date_20150307]);
162 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
163 XCTAssertNil(results[(__bridge NSString*)kSecTrustExtendedValidation], "got EV result when no EV expected");
165 CFReleaseNull(subCA);
169 - (void)testInvalidOCSPResponse {
170 NSDictionary *results = nil;
171 SecCertificateRef certA = nil;
172 NSData *proofA_1 = nil, *invalid_ocsp = nil;
173 isnt(certA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverA"], NULL, "create certA");
174 XCTAssertNotNil(proofA_1 = [CTTests DataFromResource:@"serverA_proof_Alfa_3"], "create proofA_1");
175 XCTAssertNotNil(invalid_ocsp = [CTTests DataFromResource:@"invalid_ocsp_response"], "create invalid ocsp response");
176 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:@[proofA_1] ocspResponses:@[invalid_ocsp] anchors:anchors
177 trustedCTLogs:trustedCTLogs hostname:nil verifyDate:date_20150307]);
178 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
179 XCTAssertNil(results[(__bridge NSString*)kSecTrustExtendedValidation], "got EV result when no EV expected");
180 CFReleaseNull(certA);
183 - (void)testOCSPResponseWithBadHash {
184 NSDictionary *results = nil;
185 SecCertificateRef certA = nil;
186 NSData *proofA_1 = nil, *invalid_ocsp = nil;
187 isnt(certA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverA"], NULL, "create certA");
188 XCTAssertNotNil(proofA_1 = [CTTests DataFromResource:@"serverA_proof_Alfa_3"], "create proofA_1");
189 XCTAssertNotNil(invalid_ocsp = [CTTests DataFromResource:@"bad_hash_ocsp_response"], "create ocsp response with bad hash");
190 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:@[proofA_1] ocspResponses:@[invalid_ocsp] anchors:anchors
191 trustedCTLogs:trustedCTLogs hostname:nil verifyDate:date_20150307]);
192 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
193 XCTAssertNil(results[(__bridge NSString*)kSecTrustExtendedValidation], "got EV result when no EV expected");
194 CFReleaseNull(certA);
197 - (void)testValidOCSPResponse {
198 NSDictionary *results = nil;
199 SecCertificateRef certA = nil;
200 NSData *proofA_1 = nil, *valid_ocsp = nil;
201 isnt(certA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverA"], NULL, "create certA");
202 XCTAssertNotNil(proofA_1 = [CTTests DataFromResource:@"serverA_proof_Alfa_3"], "create proofA_1");
203 XCTAssertNotNil(valid_ocsp = [CTTests DataFromResource:@"valid_ocsp_response"], "create invalid ocsp response");
204 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:@[proofA_1] ocspResponses:@[valid_ocsp] anchors:anchors
205 trustedCTLogs:trustedCTLogs hostname:nil verifyDate:date_20150307]);
206 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
207 XCTAssertNil(results[(__bridge NSString*)kSecTrustExtendedValidation], "got EV result when no EV expected");
208 CFReleaseNull(certA);
211 - (void)testTwoPresentedSCTs {
212 NSDictionary *results = nil;
213 SecCertificateRef certA = nil;
214 NSData *proofA_1 = nil, *proofA_2 = nil;
215 isnt(certA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverA"], NULL, "create certA");
216 XCTAssertNotNil(proofA_1 = [CTTests DataFromResource:@"serverA_proof_Alfa_3"], "create proofA_1");
217 XCTAssertNotNil(proofA_2 = [CTTests DataFromResource:@"serverA_proof_Bravo_3"], "create proofA_2");
218 NSArray *scts = @[proofA_1, proofA_2];
219 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:scts ocspResponses:nil anchors:anchors
220 trustedCTLogs:trustedCTLogs hostname:nil verifyDate:date_20150307]);
221 XCTAssertEqualObjects(results[(__bridge NSString*)kSecTrustCertificateTransparency], @YES, "expected CT result");
222 XCTAssertNil(results[(__bridge NSString*)kSecTrustExtendedValidation], "got EV result when no EV expected");
223 CFReleaseNull(certA);
226 - (void)testThreeEmbeddedSCTs {
227 NSDictionary *results = nil;
228 SecCertificateRef leaf = nil, subCA = nil, root = nil;
229 isnt(leaf = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"www_digicert_com_2016"], NULL, "create leaf");
230 isnt(subCA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"digicert_sha2_ev_server_ca"], NULL, "create subCA");
231 isnt(root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"digicert_ev_root_ca"], NULL, "create subCA");
232 NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCA];
233 XCTAssertNotNil(results = [self eval_ct_trust:certs
234 sCTs:nil ocspResponses:nil anchors:@[(__bridge id)root]
235 trustedCTLogs:nil hostname:@"www.digicert.com" verifyDate:date_20160422]);
237 /* BridgeOS doesn't have a root store or CT log list so default CT behavior (without input logs as above) is failed CT validation. */
238 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
240 XCTAssertEqualObjects(results[(__bridge NSString*)kSecTrustCertificateTransparency], @YES, "expected CT result");
243 /* WatchOS doesn't require OCSP for EV flag, so even though the OCSP responder no longer responds for this cert, it is EV on watchOS. */
244 XCTAssertEqualObjects(results[(__bridge NSString*)kSecTrustExtendedValidation], @YES, "expected EV result");
246 XCTAssertNil(results[(__bridge NSString*)kSecTrustExtendedValidation], "got EV result when no EV expected");
249 CFReleaseNull(subCA);
253 - (void)testOtherCTCerts {
254 SecCertificateRef cfCert = NULL;
255 NSDictionary *results = nil;
257 #define TEST_CASE(x) \
259 isnt(cfCert = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@#x], NULL, "create cfCert from " #x); \
260 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)cfCert] \
261 sCTs:nil ocspResponses:nil anchors:anchors \
262 trustedCTLogs:trustedCTLogs hostname:nil verifyDate:date_20150307]); \
263 XCTAssertEqualObjects(results[(__bridge NSString*)kSecTrustCertificateTransparency], @YES, "expected CT result"); \
264 XCTAssertNil(results[(__bridge NSString*)kSecTrustExtendedValidation], "got EV result when no EV expected"); \
265 CFReleaseNull(cfCert); \
269 TEST_CASE(server_1601);
270 TEST_CASE(server_1603);
271 TEST_CASE(server_1604);
272 TEST_CASE(server_1701);
273 TEST_CASE(server_1704);
274 TEST_CASE(server_1705);
275 TEST_CASE(server_1801);
276 TEST_CASE(server_1804);
277 TEST_CASE(server_1805);
278 TEST_CASE(server_2001);
283 - (void)testLogListParsing {
284 NSDictionary *results = nil;
285 SecCertificateRef certF = nil;
286 isnt(certF = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverF"], NULL, "create certF");
289 NSArray *testLogList = @[];
290 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certF] sCTs:nil ocspResponses:nil anchors:anchors
291 trustedCTLogs:testLogList hostname:nil verifyDate:date_20150307]);
292 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
294 /* Log not a dictionary */
295 testLogList = @[@[]];
296 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certF] sCTs:nil ocspResponses:nil anchors:anchors
297 trustedCTLogs:testLogList hostname:nil verifyDate:date_20150307]);
298 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
300 /* Log list missing "key" key */
301 testLogList = @[@{@"test":@"test"}];
302 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certF] sCTs:nil ocspResponses:nil anchors:anchors
303 trustedCTLogs:testLogList hostname:nil verifyDate:date_20150307]);
304 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
306 /* Value for "key" isn't a data object */
307 testLogList = @[@{@"key":@"test"}];
308 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certF] sCTs:nil ocspResponses:nil anchors:anchors
309 trustedCTLogs:testLogList hostname:nil verifyDate:date_20150307]);
310 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
312 CFReleaseNull(certF);
315 - (void) testPrecertsFail {
316 SecCertificateRef precert = NULL, system_root = NULL;
317 SecTrustRef trust = NULL;
318 NSArray *precert_anchors = nil;
319 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:561540800.0]; // October 18, 2018 at 12:33:20 AM PDT
320 CFErrorRef error = NULL;
322 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
323 errOut, fail("failed to create system root"));
324 require_action(precert = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"precert"],
325 errOut, fail("failed to create precert"));
327 precert_anchors = @[(__bridge id)system_root];
328 require_noerr_action(SecTrustCreateWithCertificates(precert, NULL, &trust), errOut, fail("failed to create trust object"));
329 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)precert_anchors), errOut, fail("failed to set anchor certificate"));
330 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
332 is(SecTrustEvaluateWithError(trust, &error), false, "SECURITY: trust evaluation of precert succeeded");
334 is(CFErrorGetCode(error), errSecUnknownCriticalExtensionFlag, "got wrong error code for precert, got %ld, expected %d",
335 (long)CFErrorGetCode(error), (int)errSecUnknownCriticalExtensionFlag);
337 fail("expected trust evaluation to fail and it did not.");
342 CFReleaseNull(system_root);
343 CFReleaseNull(precert);
344 CFReleaseNull(error);
347 + (NSArray <NSDictionary *>*)setShardedTrustedLogs:(NSArray <NSDictionary *>*)trustedLogs startTime:(CFAbsoluteTime)startTime endTime:(CFAbsoluteTime)endTime {
348 NSMutableArray <NSDictionary *>* shardedLogs = [trustedLogs mutableCopy];
349 [trustedLogs enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
350 NSMutableDictionary *shardedLogData = [obj mutableCopy];
351 shardedLogData[@"start_inclusive"] = [NSDate dateWithTimeIntervalSinceReferenceDate:startTime];
352 shardedLogData[@"end_exclusive"] = [NSDate dateWithTimeIntervalSinceReferenceDate:endTime];
353 [shardedLogs replaceObjectAtIndex:idx withObject:shardedLogData];
358 - (void)testShardedLogs {
359 NSDictionary *results = nil;
360 SecCertificateRef certA = nil;
361 NSData *proofA_1 = nil, *proofA_2 = nil;
362 isnt(certA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverA"], NULL, "create certA");
363 XCTAssertNotNil(proofA_1 = [CTTests DataFromResource:@"serverA_proof_Alfa_3"], "create proofA_1");
364 XCTAssertNotNil(proofA_2 = [CTTests DataFromResource:@"serverA_proof_Bravo_3"], "create proofA_2");
365 NSArray *scts = @[proofA_1, proofA_2];
367 /* Certificate expiry within temporal shard window */
368 NSArray <NSDictionary *> *shardedCTLogs= [CTTests setShardedTrustedLogs:trustedCTLogs startTime:0.0 endTime:CFAbsoluteTimeGetCurrent()];
369 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:scts ocspResponses:nil anchors:anchors
370 trustedCTLogs:shardedCTLogs hostname:nil verifyDate:date_20150307]);
371 XCTAssertEqualObjects(results[(__bridge NSString*)kSecTrustCertificateTransparency], @YES, "expected CT result");
373 /* Certificate expiry before temporal shard window */
374 shardedCTLogs= [CTTests setShardedTrustedLogs:trustedCTLogs startTime:CFAbsoluteTimeGetCurrent() endTime:(CFAbsoluteTimeGetCurrent() + 24*3600)];
375 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:scts ocspResponses:nil anchors:anchors
376 trustedCTLogs:shardedCTLogs hostname:nil verifyDate:date_20150307]);
377 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
379 /* Certificate expiry after temporal shard window */
380 shardedCTLogs= [CTTests setShardedTrustedLogs:trustedCTLogs startTime:0.0 endTime:(24*3600)];
381 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:scts ocspResponses:nil anchors:anchors
382 trustedCTLogs:shardedCTLogs hostname:nil verifyDate:date_20150307]);
383 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
385 CFReleaseNull(certA);
388 + (NSArray <NSDictionary *>*)setReadOnlyTrustedLogs:(NSArray <NSDictionary *>*)trustedLogs readOnlyTime:(CFAbsoluteTime)readOnlyTime
390 NSMutableArray <NSDictionary *>*readOnlyLogs = [trustedLogs mutableCopy];
391 [trustedLogs enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
392 NSMutableDictionary *logData = [obj mutableCopy];
393 logData[@"frozen"] = [NSDate dateWithTimeIntervalSinceReferenceDate:readOnlyTime];
394 [readOnlyLogs replaceObjectAtIndex:idx withObject:logData];
399 - (void)testReadOnlyLogs {
400 NSDictionary *results = nil;
401 SecCertificateRef certA = nil;
402 NSData *proofA_1 = nil, *proofA_2 = nil;
403 isnt(certA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverA"], NULL, "create certA");
404 XCTAssertNotNil(proofA_1 = [CTTests DataFromResource:@"serverA_proof_Alfa_3"], "create proofA_1");
405 XCTAssertNotNil(proofA_2 = [CTTests DataFromResource:@"serverA_proof_Bravo_3"], "create proofA_2");
406 NSArray *scts = @[proofA_1, proofA_2];
408 /* SCTs before read-only date */
409 NSArray <NSDictionary *> *readOnlyCTLogs = [CTTests setReadOnlyTrustedLogs:trustedCTLogs readOnlyTime:CFAbsoluteTimeGetCurrent()];
410 XCTAssertNotNil(readOnlyCTLogs);
411 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:scts ocspResponses:nil anchors:anchors
412 trustedCTLogs:readOnlyCTLogs hostname:nil verifyDate:date_20150307]);
413 XCTAssertEqualObjects(results[(__bridge NSString*)kSecTrustCertificateTransparency], @YES, "expected CT result");
415 /* SCTs after read-only date */
416 readOnlyCTLogs = [CTTests setReadOnlyTrustedLogs:trustedCTLogs readOnlyTime:0.0];
417 XCTAssertNotNil(readOnlyCTLogs);
418 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:scts ocspResponses:nil anchors:anchors
419 trustedCTLogs:readOnlyCTLogs hostname:nil verifyDate:date_20150307]);
420 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
422 CFReleaseNull(certA);
425 + (NSArray <NSDictionary *>*)setRetiredTrustedLogs:(NSArray <NSDictionary *>*)trustedLogs retirementTime:(CFAbsoluteTime)retirementTime indexSet:(NSIndexSet *)indexSet
427 __block NSMutableArray <NSDictionary *>*retiredLogs = [trustedLogs mutableCopy];
428 [trustedLogs enumerateObjectsAtIndexes:indexSet options:0.0 usingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
429 NSMutableDictionary *logData = [obj mutableCopy];
430 logData[@"expiry"] = [NSDate dateWithTimeIntervalSinceReferenceDate:retirementTime];
431 [retiredLogs replaceObjectAtIndex:idx withObject:logData];
436 - (void)testRetiredLogs {
437 NSDictionary *results = nil;
438 SecCertificateRef certA = nil, server1601 = nil;
439 NSData *proofA_1 = nil, *proofA_2 = nil;
440 isnt(certA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"serverA"], NULL, "create certA");
441 isnt(server1601 = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"server_1601"], NULL, "create server1601");
442 XCTAssertNotNil(proofA_1 = [CTTests DataFromResource:@"serverA_proof_Alfa_3"], "create proofA_1");
443 XCTAssertNotNil(proofA_2 = [CTTests DataFromResource:@"serverA_proof_Bravo_3"], "create proofA_2");
444 NSArray *scts = @[proofA_1, proofA_2];
446 NSArray <NSDictionary *> *retiredCTLogs = [CTTests setRetiredTrustedLogs:trustedCTLogs
447 retirementTime:CFAbsoluteTimeGetCurrent()
448 indexSet:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, trustedCTLogs.count)]];
449 /* presented SCTs from retired logs */
450 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)certA] sCTs:scts ocspResponses:nil anchors:anchors
451 trustedCTLogs:retiredCTLogs hostname:nil verifyDate:date_20150307]);
452 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
454 /* all embedded SCTs from retired logs */
455 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)server1601] sCTs:nil ocspResponses:nil anchors:anchors
456 trustedCTLogs:retiredCTLogs hostname:nil verifyDate:date_20150307]);
457 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
459 /* one embedded SCTs from retired log, before log retirement date (one once or currently qualified SCT) */
460 retiredCTLogs = [CTTests setRetiredTrustedLogs:trustedCTLogs
461 retirementTime:CFAbsoluteTimeGetCurrent()
462 indexSet:[NSIndexSet indexSetWithIndex:0]];
463 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)server1601] sCTs:nil ocspResponses:nil anchors:anchors
464 trustedCTLogs:retiredCTLogs hostname:nil verifyDate:date_20150307]);
465 XCTAssertEqualObjects(results[(__bridge NSString*)kSecTrustCertificateTransparency], @YES, "expected CT result");
467 /* one embedded SCT from retired log, after retirement date */
468 retiredCTLogs = [CTTests setRetiredTrustedLogs:trustedCTLogs
470 indexSet:[NSIndexSet indexSetWithIndex:0]];
471 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)server1601] sCTs:nil ocspResponses:nil anchors:anchors
472 trustedCTLogs:retiredCTLogs hostname:nil verifyDate:date_20150307]);
473 XCTAssertNil(results[(__bridge NSString*)kSecTrustCertificateTransparency], "got CT result when no CT expected");
475 /* one embedded SCT before retirement date, one embedded SCT before read-only date */
476 retiredCTLogs = [CTTests setReadOnlyTrustedLogs:trustedCTLogs readOnlyTime:CFAbsoluteTimeGetCurrent()];
477 retiredCTLogs = [CTTests setRetiredTrustedLogs:retiredCTLogs retirementTime:CFAbsoluteTimeGetCurrent() indexSet:[NSIndexSet indexSetWithIndex:0]];
478 XCTAssertNotNil(results = [self eval_ct_trust:@[(__bridge id)server1601] sCTs:nil ocspResponses:nil anchors:anchors
479 trustedCTLogs:retiredCTLogs hostname:nil verifyDate:date_20150307]);
480 XCTAssertEqualObjects(results[(__bridge NSString*)kSecTrustCertificateTransparency], @YES, "expected CT result");
482 CFReleaseNull(certA);
483 CFReleaseNull(server1601);
486 //TODO: add more tests
487 // <rdar://problem/23849697> Expand unit tests for CT
489 // -other signing algorithms
491 // -future timestamps
492 // -SCT signature doesn't verify
493 // -OCSP-delivered SCTs
494 // -unknown logs (embedded, TLS, and OCSP)
495 // -two SCTs from the same log (different timestamps)
500 // MARK: CT Enforcement Exceptions tests
501 @interface CTExceptionsTests : TrustEvaluationTestCase
504 @implementation CTExceptionsTests
505 #if !TARGET_OS_BRIDGE // bridgeOS doesn't permit CT exceptions
508 NSURL *trustedLogsURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"CTlogs"
509 withExtension:@"plist"
510 subdirectory:@"si-82-sectrust-ct-data"];
511 trustedCTLogs = [NSArray arrayWithContentsOfURL:trustedLogsURL];
512 NSData *rootHash = [NSData dataWithBytes:_system_root_hash length:sizeof(_system_root_hash)];
513 CFPreferencesSetAppValue(CFSTR("TestCTRequiredSystemRoot"), (__bridge CFDataRef)rootHash, CFSTR("com.apple.security"));
514 CFPreferencesAppSynchronize(CFSTR("com.apple.security"));
517 - (void)testSetCTExceptions {
518 CFErrorRef error = NULL;
519 const CFStringRef TrustTestsAppID = CFSTR("com.apple.trusttests");
520 const CFStringRef AnotherAppID = CFSTR("com.apple.security.not-this-one");
521 CFDictionaryRef copiedExceptions = NULL;
523 /* Verify no exceptions set */
524 is(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, NULL), NULL, "no exceptions set");
525 if (copiedExceptions) {
526 /* If we're starting out with exceptions set, a lot of the following will also fail, so just skip them */
527 CFReleaseNull(copiedExceptions);
531 /* Set exceptions with specified AppID */
532 NSDictionary *exceptions1 = @{
533 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@"test.apple.com", @".test.apple.com"],
535 ok(SecTrustStoreSetCTExceptions(TrustTestsAppID, (__bridge CFDictionaryRef)exceptions1, &error),
536 "failed to set exceptions for TrustTests: %@", error);
538 /* Copy all exceptions (with only one set) */
539 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, &error),
540 "failed to copy all exceptions: %@", error);
541 ok([exceptions1 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
542 "got the wrong exceptions back");
543 CFReleaseNull(copiedExceptions);
545 /* Copy this app's exceptions */
546 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(TrustTestsAppID, &error),
547 "failed to copy TrustTests' exceptions: %@", error);
548 ok([exceptions1 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
549 "got the wrong exceptions back");
550 CFReleaseNull(copiedExceptions);
552 /* Copy a different app's exceptions */
553 is(copiedExceptions = SecTrustStoreCopyCTExceptions(AnotherAppID, &error), NULL,
554 "failed to copy different app's exceptions: %@", error);
555 CFReleaseNull(copiedExceptions);
557 /* Set different exceptions with implied AppID */
558 CFDataRef leafHash = SecSHA256DigestCreate(NULL, _system_after_leafSPKI, sizeof(_system_after_leafSPKI));
559 NSDictionary *leafException = @{
560 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
561 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)leafHash,
563 NSDictionary *exceptions2 = @{
564 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@".test.apple.com"],
565 (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ]
567 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions2, &error),
568 "failed to set exceptions for this app: %@", error);
570 /* Ensure exceptions are replaced for TrustTests */
571 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(TrustTestsAppID, &error),
572 "failed to copy TrustTests' exceptions: %@", error);
573 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
574 "got the wrong exceptions back");
575 CFReleaseNull(copiedExceptions);
577 /* Set exceptions with a different AppID */
578 CFDataRef rootHash = SecSHA256DigestCreate(NULL, _system_rootSPKI, sizeof(_system_rootSPKI));
579 NSDictionary *rootExceptions = @{
580 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
581 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)rootHash,
583 NSDictionary *exceptions3 = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ rootExceptions ] };
584 ok(SecTrustStoreSetCTExceptions(AnotherAppID, (__bridge CFDictionaryRef)exceptions3, &error),
585 "failed to set exceptions for different app: %@", error);
587 /* Copy only one of the app's exceptions */
588 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(TrustTestsAppID, &error),
589 "failed to copy TrustTests' exceptions: %@", error);
590 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
591 "got the wrong exceptions back");
592 CFReleaseNull(copiedExceptions);
594 /* Set empty exceptions */
595 NSDictionary *empty = @{};
596 ok(SecTrustStoreSetCTExceptions(TrustTestsAppID, (__bridge CFDictionaryRef)empty, &error),
597 "failed to set empty exceptions");
599 /* Copy exceptiosn to ensure no change */
600 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(TrustTestsAppID, &error),
601 "failed to copy TrustTests' exceptions: %@", error);
602 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
603 "got the wrong exceptions back");
604 CFReleaseNull(copiedExceptions);
606 /* Copy all exceptions */
607 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, &error),
608 "failed to copy all exceptions: %@", error);
609 is(CFDictionaryGetCount(copiedExceptions), 2, "Got the wrong number of all exceptions");
610 NSDictionary *nsCopiedExceptions = CFBridgingRelease(copiedExceptions);
611 NSArray *domainExceptions = nsCopiedExceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey];
612 NSArray *caExceptions = nsCopiedExceptions[(__bridge NSString*)kSecCTExceptionsCAsKey];
613 ok(domainExceptions && caExceptions, "Got both domain and CA exceptions");
614 ok([domainExceptions count] == 1, "Got 1 domain exception");
615 ok([caExceptions count] == 2, "Got 2 CA exceptions");
616 ok([domainExceptions[0] isEqualToString:@".test.apple.com"], "domain exception is .test.apple.com");
617 ok([caExceptions containsObject:leafException] && [caExceptions containsObject:rootExceptions], "got expected leaf and root CA exceptions");
619 /* Reset other app's exceptions */
620 ok(SecTrustStoreSetCTExceptions(AnotherAppID, NULL, &error),
621 "failed to reset exceptions for different app: %@", error);
622 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, &error),
623 "failed to copy all exceptions: %@", error);
624 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
625 "got the wrong exceptions back");
626 CFReleaseNull(copiedExceptions);
628 #define check_errSecParam \
630 is(CFErrorGetCode(error), errSecParam, "bad input produced unxpected error code: %ld", (long)CFErrorGetCode(error)); \
632 fail("expected failure to set NULL exceptions"); \
635 /* Set exceptions with bad inputs */
636 NSDictionary *badExceptions = @{
637 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@"test.apple.com", @".test.apple.com"],
638 @"not a key": @"not a value",
640 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
641 "set exceptions with unknown key");
644 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey:@"test.apple.com" };
645 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
646 "set exceptions with bad value");
649 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey: @[ @{} ] };
650 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
651 "set exceptions with bad array value");
654 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @"test.apple.com" ] };
655 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
656 "set exceptions with bad array value");
659 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
660 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
661 @"not-a-key" : (__bridge NSData*)rootHash,
663 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
664 "set exceptions with bad CA dictionary value");
667 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
668 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
670 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
671 "set exceptions with bad CA dictionary value");
674 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
675 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
676 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)rootHash,
677 @"not-a-key":@"not-a-value"
679 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
680 "set exceptions with bad CA dictionary value");
683 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey: @[ @".com" ] };
684 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
685 "set exceptions with TLD value");
687 #undef check_errSecParam
689 /* Remove exceptions using empty arrays */
690 NSDictionary *emptyArrays = @{
691 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[],
692 (__bridge NSString*)kSecCTExceptionsCAsKey : @[]
694 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)emptyArrays, &error),
695 "failed to set empty array exceptions for this app: %@", error);
696 is(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, NULL), NULL, "no exceptions set");
698 CFReleaseNull(leafHash);
699 CFReleaseNull(rootHash);
702 #define evalTrustExpectingError(errCode, ...) \
703 is(SecTrustEvaluateWithError(trust, &error), false, __VA_ARGS__); \
705 is(CFErrorGetCode(error), errCode, "got wrong error code, got %ld, expected %d", \
706 (long)CFErrorGetCode(error), (int)errCode); \
708 fail("expected trust evaluation to fail and it did not."); \
710 CFReleaseNull(error);
712 - (void) testSpecificDomainExceptions {
713 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
714 SecTrustRef trust = NULL;
715 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
716 NSArray *exceptions_anchors = nil;
717 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
718 CFErrorRef error = nil;
719 NSDictionary *exceptions = nil;
721 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
722 errOut, fail("failed to create system root"));
723 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
724 errOut, fail("failed to create system server cert issued after flag day"));
725 require_action(system_server_after_with_CT = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after_scts"],
726 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
728 exceptions_anchors = @[ (__bridge id)system_root ];
729 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
730 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)exceptions_anchors), errOut, fail("failed to set anchors"));
731 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
732 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
734 /* superdomain exception without CT fails */
735 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"test.apple.com"] };
736 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
737 evalTrustExpectingError(errSecVerifyActionFailed, "superdomain exception unexpectedly succeeded");
739 /* subdomain exceptions without CT fails */
740 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"one.ct.test.apple.com"] };
741 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
742 SecTrustSetNeedsEvaluation(trust);
743 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded")
745 /* no match without CT fails */
746 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"example.com"] };
747 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
748 SecTrustSetNeedsEvaluation(trust);
749 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
751 /* matching domain without CT succeeds */
752 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com"] };
753 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
754 SecTrustSetNeedsEvaluation(trust);
755 is(SecTrustEvaluateWithError(trust, &error), true, "exact match domain exception did not apply");
757 /* matching domain with CT succeeds */
758 CFReleaseNull(trust);
759 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
760 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)exceptions_anchors), errOut, fail("failed to set anchors"));
761 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
762 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
763 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
765 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
768 CFReleaseNull(system_root);
769 CFReleaseNull(system_server_after);
770 CFReleaseNull(system_server_after_with_CT);
771 CFReleaseNull(trust);
772 CFReleaseNull(policy);
773 CFReleaseNull(error);
776 - (void) testSubdomainExceptions {
777 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
778 SecTrustRef trust = NULL;
779 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
780 NSArray *exceptions_anchors = nil;
781 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
782 CFErrorRef error = nil;
783 NSDictionary *exceptions = nil;
785 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
786 errOut, fail("failed to create system root"));
787 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
788 errOut, fail("failed to create system server cert issued after flag day"));
789 require_action(system_server_after_with_CT = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after_scts"],
790 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
792 exceptions_anchors = @[ (__bridge id)system_root ];
793 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
794 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)exceptions_anchors), errOut, fail("failed to set anchors"));
795 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
796 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
798 /* superdomain exception without CT succeeds */
799 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".test.apple.com"] };
800 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
801 is(SecTrustEvaluateWithError(trust, &error), true, "superdomain exception did not apply");
803 /* exact domain exception without CT succeeds */
804 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".ct.test.apple.com"] };
805 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
806 SecTrustSetNeedsEvaluation(trust);
807 is(SecTrustEvaluateWithError(trust, &error), true, "exact domain exception did not apply");
809 /* no match without CT fails */
810 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".example.com"] };
811 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
812 SecTrustSetNeedsEvaluation(trust);
813 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
815 /* subdomain without CT fails */
816 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".one.ct.test.apple.com"] };
817 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
818 SecTrustSetNeedsEvaluation(trust);
819 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded");
821 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
824 CFReleaseNull(system_root);
825 CFReleaseNull(system_server_after);
826 CFReleaseNull(system_server_after_with_CT);
827 CFReleaseNull(trust);
828 CFReleaseNull(policy);
829 CFReleaseNull(error);
832 - (void) testMixedDomainExceptions {
833 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
834 SecTrustRef trust = NULL;
835 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
836 NSArray *exceptions_anchors = nil;
837 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
838 CFErrorRef error = nil;
839 NSDictionary *exceptions = nil;
841 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
842 errOut, fail("failed to create system root"));
843 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
844 errOut, fail("failed to create system server cert issued after flag day"));
845 require_action(system_server_after_with_CT = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after_scts"],
846 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
848 exceptions_anchors = @[ (__bridge id)system_root ];
849 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
850 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)exceptions_anchors), errOut, fail("failed to set anchors"));
851 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
852 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
854 /* specific domain exception without CT succeeds */
855 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".example.com" ] };
856 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
857 is(SecTrustEvaluateWithError(trust, &error), true, "one of exact domain exception did not apply");
859 /* super domain exception without CT succeeds */
860 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".apple.com", @"example.com" ] };
861 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
862 SecTrustSetNeedsEvaluation(trust);
863 is(SecTrustEvaluateWithError(trust, &error), true, "one of superdomain exception did not apply");
865 /* both super domain and specific domain exceptions without CT succeeds */
866 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".apple.com" ] };
867 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
868 SecTrustSetNeedsEvaluation(trust);
869 is(SecTrustEvaluateWithError(trust, &error), true, "both domain exception did not apply");
871 /* neither specific domain nor super domain exceptions without CT fails */
872 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"apple.com", @".example.com" ] };
873 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
874 SecTrustSetNeedsEvaluation(trust);
875 evalTrustExpectingError(errSecVerifyActionFailed, "no match domain unexpectedly succeeded");
877 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
880 CFReleaseNull(system_root);
881 CFReleaseNull(system_server_after);
882 CFReleaseNull(system_server_after_with_CT);
883 CFReleaseNull(trust);
884 CFReleaseNull(policy);
885 CFReleaseNull(error);
888 - (void) test_ct_leaf_exceptions {
889 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
890 SecTrustRef trust = NULL;
891 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
892 NSArray *exceptions_anchors = nil;
893 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
894 CFErrorRef error = nil;
895 NSDictionary *leafException = nil, *exceptions = nil;
896 NSData *leafHash = nil;
898 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
899 errOut, fail("failed to create system root"));
900 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
901 errOut, fail("failed to create system server cert issued after flag day"));
902 require_action(system_server_after_with_CT = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after_scts"],
903 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
905 exceptions_anchors = @[ (__bridge id)system_root ];
906 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
907 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)exceptions_anchors), errOut, fail("failed to set anchors"));
908 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
909 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
911 /* set exception on leaf cert without CT */
912 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after));
913 leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
914 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : leafHash,
916 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ] };
917 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
918 "failed to set exceptions: %@", error);
919 is(SecTrustEvaluateWithError(trust, &error), true, "leaf public key exception did not apply");
921 /* set exception on leaf cert with CT */
922 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after_with_CT));
923 leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
924 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : leafHash,
926 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ] };
927 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
928 "failed to set exceptions: %@", error);
929 SecTrustSetNeedsEvaluation(trust);
930 evalTrustExpectingError(errSecVerifyActionFailed, "leaf cert with no public key exceptions succeeded");
932 /* matching public key with CT succeeds */
933 CFReleaseNull(trust);
934 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
935 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)exceptions_anchors), errOut, fail("failed to set anchors"));
936 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
937 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
938 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
940 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
943 CFReleaseNull(system_root);
944 CFReleaseNull(system_server_after);
945 CFReleaseNull(system_server_after_with_CT);
946 CFReleaseNull(trust);
947 CFReleaseNull(policy);
948 CFReleaseNull(error);
951 - (void) test_ct_unconstrained_ca_exceptions {
952 SecCertificateRef root = NULL, subca = NULL;
953 SecCertificateRef server_matching = NULL, server_matching_with_CT = NULL, server_partial = NULL, server_no_match = NULL, server_no_org = NULL;
954 SecTrustRef trust = NULL;
955 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
956 NSArray *exceptions_anchors = nil, *certs = nil;
957 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
958 CFErrorRef error = nil;
959 NSDictionary *caException = nil, *exceptions = nil;
960 NSData *caHash = nil;
962 require_action(root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
963 errOut, fail("failed to create system root"));
964 require_action(subca = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_unconstrained_subca"],
965 errOut, fail("failed to create subca"));
966 require_action(server_matching = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_matching_orgs"],
967 errOut, fail("failed to create server cert with matching orgs"));
968 require_action(server_matching_with_CT = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_matching_orgs_scts"],
969 errOut, fail("failed to create server cert with matching orgs and scts"));
970 require_action(server_partial = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_partial_orgs"],
971 errOut, fail("failed to create server cert with partial orgs"));
972 require_action(server_no_match = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_nonmatching_orgs"],
973 errOut, fail("failed to create server cert with non-matching orgs"));
974 require_action(server_no_org = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_no_orgs"],
975 errOut, fail("failed to create server cert with no orgs"));
977 exceptions_anchors = @[ (__bridge id)root ];
979 #define createTrust(certs) \
980 CFReleaseNull(trust); \
981 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
982 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)exceptions_anchors), errOut, fail("failed to set anchors")); \
983 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
984 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
986 /* Set exception on the subCA */
987 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(subca));
988 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
989 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
991 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ caException ] };
992 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
993 "failed to set exceptions: %@", error);
995 /* Verify that non-CT cert with Orgs matching subCA passes */
996 certs = @[ (__bridge id)server_matching, (__bridge id)subca];
998 is(SecTrustEvaluateWithError(trust, &error), true, "matching org subca exception did not apply: %@", error);
1000 /* Verify that CT cert with Orgs matching subCA passes */
1001 certs = @[ (__bridge id)server_matching_with_CT, (__bridge id)subca];
1003 is(SecTrustEvaluateWithError(trust, &error), true, "CT matching org subca exception did not apply: %@", error);
1005 /* Verify that non-CT cert with partial Org match fails */
1006 certs = @[ (__bridge id)server_partial, (__bridge id)subca];
1008 evalTrustExpectingError(errSecVerifyActionFailed, "partial matching org leaf succeeded");
1010 /* Verify that a non-CT cert with non-matching Org fails */
1011 certs = @[ (__bridge id)server_no_match, (__bridge id)subca];
1013 evalTrustExpectingError(errSecVerifyActionFailed, "non-matching org leaf succeeded");
1015 /* Verify that a non-CT cert with no Org fails */
1016 certs = @[ (__bridge id)server_no_org, (__bridge id)subca];
1018 evalTrustExpectingError(errSecVerifyActionFailed, "no org leaf succeeded");
1020 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1025 CFReleaseNull(root);
1026 CFReleaseNull(subca);
1027 CFReleaseNull(server_matching);
1028 CFReleaseNull(server_matching_with_CT);
1029 CFReleaseNull(server_partial);
1030 CFReleaseNull(server_no_match);
1031 CFReleaseNull(server_no_org);
1032 CFReleaseNull(trust);
1033 CFReleaseNull(policy);
1034 CFReleaseNull(error);
1037 - (void) test_ct_constrained_ca_exceptions {
1038 SecCertificateRef root = NULL, org_constrained_subca = NULL;
1039 SecCertificateRef constraint_pass_server = NULL, constraint_pass_server_ct = NULL, constraint_fail_server = NULL;
1040 SecCertificateRef dn_constrained_subca = NULL, dn_constrained_server = NULL, dn_constrained_server_mismatch = NULL;
1041 SecCertificateRef dns_constrained_subca = NULL, dns_constrained_server = NULL, dns_constrained_server_mismatch = NULL;
1042 SecTrustRef trust = NULL;
1043 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1044 NSArray *exceptions_anchors = nil, *certs = nil;
1045 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1046 CFErrorRef error = nil;
1047 NSDictionary *caException = nil, *exceptions = nil;
1048 NSMutableArray *caExceptions = [NSMutableArray array];
1049 NSData *caHash = nil;
1051 require_action(root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1052 errOut, fail("failed to create system root"));
1053 require_action(org_constrained_subca = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_subca"],
1054 errOut, fail("failed to create org-constrained subca"));
1055 require_action(constraint_pass_server = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_server"],
1056 errOut, fail("failed to create constrained non-CT leaf"));
1057 require_action(constraint_pass_server_ct = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_server_scts"],
1058 errOut, fail("failed to create constrained CT leaf"));
1059 require_action(constraint_fail_server= (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_fail_server"],
1060 errOut, fail("failed to create constraint failure leaf"));
1061 require_action(dn_constrained_subca = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_no_org_subca"],
1062 errOut, fail("failed to create dn-constrained subca"));
1063 require_action(dn_constrained_server = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_no_org_server"],
1064 errOut, fail("failed to create dn-constrained leaf"));
1065 require_action(dn_constrained_server_mismatch = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_no_org_server_mismatch"],
1066 errOut, fail("failed to create dn-constrained leaf with mismatched orgs"));
1067 require_action(dns_constrained_subca = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_no_dn_subca"],
1068 errOut, fail("failed to create dns-constrained subca"));
1069 require_action(dns_constrained_server = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_no_dn_server"],
1070 errOut, fail("failed to create dns-constrained leaf"));
1071 require_action(dns_constrained_server_mismatch = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_constrained_no_dn_server_mismatch"],
1072 errOut, fail("failed to create dns-constrained leaf with mismatched orgs"));
1074 exceptions_anchors = @[ (__bridge id)root ];
1076 /* Set exception on the subCAs */
1077 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(org_constrained_subca));
1078 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1079 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1081 [caExceptions addObject:caException];
1083 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dn_constrained_subca));
1084 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1085 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1087 [caExceptions addObject:caException];
1089 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dns_constrained_subca));
1090 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1091 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1093 [caExceptions addObject:caException];
1094 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : caExceptions };
1095 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1096 "failed to set exceptions: %@", error);
1098 #define createTrust(certs) \
1099 CFReleaseNull(trust); \
1100 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
1101 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)exceptions_anchors), errOut, fail("failed to set anchors")); \
1102 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
1103 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1105 /* Verify org-constrained non-CT leaf passes */
1106 certs = @[ (__bridge id)constraint_pass_server, (__bridge id)org_constrained_subca ];
1108 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1110 /* Verify org-constrained CT leaf passes */
1111 certs = @[ (__bridge id)constraint_pass_server_ct, (__bridge id)org_constrained_subca ];
1113 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1115 /* Verify org-constrained non-CT leaf with wrong org fails */
1116 certs = @[ (__bridge id)constraint_fail_server, (__bridge id)org_constrained_subca ];
1118 evalTrustExpectingError(errSecInvalidName, "leaf failing name constraints succeeded");
1120 /* Verify dn-constrained (but not with org) non-CT leaf with matching orgs succeeds */
1121 certs = @[ (__bridge id)dn_constrained_server, (__bridge id)dn_constrained_subca ];
1123 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1125 /* Verify dn-constrained (but not with org) non-CT leaf without matching orgs fails */
1126 certs = @[ (__bridge id)dn_constrained_server_mismatch, (__bridge id)dn_constrained_subca ];
1128 evalTrustExpectingError(errSecVerifyActionFailed, "dn name constraints with no org succeeded");
1130 /* Verify dns-constrained (no DN constraints) non-CT leaf with matching orgs succeeds */
1131 certs = @[ (__bridge id)dns_constrained_server, (__bridge id)dns_constrained_subca ];
1133 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1135 /* Verify dns-constrained (no DN constraints) non-CT leaf without matching orgs fails*/
1136 certs = @[ (__bridge id)dns_constrained_server_mismatch, (__bridge id)dns_constrained_subca ];
1138 evalTrustExpectingError(errSecVerifyActionFailed, "dns name constraints with no DN constraint succeeded");
1140 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1145 CFReleaseNull(root);
1146 CFReleaseNull(org_constrained_subca);
1147 CFReleaseNull(constraint_pass_server);
1148 CFReleaseNull(constraint_pass_server_ct);
1149 CFReleaseNull(constraint_fail_server);
1150 CFReleaseNull(dn_constrained_subca);
1151 CFReleaseNull(dn_constrained_server);
1152 CFReleaseNull(dn_constrained_server_mismatch);
1153 CFReleaseNull(dns_constrained_subca);
1154 CFReleaseNull(dns_constrained_server);
1155 CFReleaseNull(dns_constrained_server_mismatch);
1156 CFReleaseNull(trust);
1157 CFReleaseNull(policy);
1158 CFReleaseNull(error);
1161 #else // TARGET_OS_BRIDGE
1162 - (void)testSkipTests
1166 #endif // TARGET_OS_BRIDGE
1170 // MARK: CT Enforcement tests
1172 @interface CTEnforcementTests : TrustEvaluationTestCase
1175 static NSArray *keychainCerts = nil;
1177 @implementation CTEnforcementTests
1180 NSURL *trustedLogsURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"CTlogs"
1181 withExtension:@"plist"
1182 subdirectory:@"si-82-sectrust-ct-data"];
1183 trustedCTLogs = [NSArray arrayWithContentsOfURL:trustedLogsURL];
1185 // set test root to be a fake system root
1186 SecCertificateRef system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"];
1187 NSData *rootHash = [NSData dataWithBytes:_system_root_hash length:sizeof(_system_root_hash)];
1188 CFPreferencesSetAppValue(CFSTR("TestCTRequiredSystemRoot"), (__bridge CFDataRef)rootHash, CFSTR("com.apple.security"));
1189 CFPreferencesAppSynchronize(CFSTR("com.apple.security"));
1190 CFReleaseNull(system_root);
1193 #if !TARGET_OS_BRIDGE
1194 /* Skip tests on bridgeOS where we don't do MobileAsset updates */
1195 - (void)testNoMACheckIn {
1196 SecCertificateRef system_root = NULL, system_server_after = NULL;
1197 SecTrustRef trust = NULL;
1198 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1199 NSArray *enforce_anchors = nil;
1200 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1202 /* Mock a failing MobileAsset so we don't enforce via MobileAsset */
1203 id mockFailedMA = OCMClassMock([MAAsset class]);
1204 OCMStub([mockFailedMA startCatalogDownload:[OCMArg any]
1205 options:[OCMArg any]
1206 then:([OCMArg invokeBlockWithArgs:OCMOCK_VALUE((NSInteger){MADownloadFailed}), nil])]);
1207 SecOTAPKIResetCurrentAssetVersion(NULL);
1209 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1210 errOut, fail("failed to create system root"));
1211 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1212 errOut, fail("failed to create system server cert issued after flag day"));
1214 enforce_anchors = @[ (__bridge id)system_root ];
1215 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1216 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1217 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1219 // Out-of-date asset, test system cert after date without CT passes
1220 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with out-of-date asset");
1223 CFReleaseNull(system_root);
1224 CFReleaseNull(system_server_after);
1225 CFReleaseNull(policy);
1226 CFReleaseNull(trust);
1229 - (void)testKillSwitch {
1230 SecCertificateRef system_root = NULL, system_server_after = NULL;
1231 SecTrustRef trust = NULL;
1232 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1233 NSArray *enforce_anchors = nil;
1234 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1236 /* Mock setting a kill switch */
1237 UpdateKillSwitch((__bridge NSString *)kOTAPKIKillSwitchCT, true);
1239 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1240 errOut, fail("failed to create system root"));
1241 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1242 errOut, fail("failed to create system server cert issued after flag day"));
1244 enforce_anchors = @[ (__bridge id)system_root ];
1245 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1246 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1247 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1249 // CT kill switch enabled so test system cert after date without CT passes
1250 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with out-of-date asset");
1252 /* Remove the kill switch */
1253 UpdateKillSwitch((__bridge NSString *)kOTAPKIKillSwitchCT, false);
1256 CFReleaseNull(system_root);
1257 CFReleaseNull(system_server_after);
1258 CFReleaseNull(policy);
1259 CFReleaseNull(trust);
1262 - (void) testWithMACheckIn {
1263 SecCertificateRef system_root = NULL, system_server_after = NULL;
1264 SecTrustRef trust = NULL;
1265 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1266 NSArray *enforce_anchors = nil;
1267 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1268 CFErrorRef error = nil;
1270 /* Mock a successful mobile asset check-in so that we enforce CT */
1271 XCTAssertTrue(UpdateOTACheckInDate(), "failed to set check-in date as now");
1273 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1274 errOut, fail("failed to create system root"));
1275 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1276 errOut, fail("failed to create system server cert issued after flag day"));
1278 enforce_anchors = @[ (__bridge id)system_root ];
1279 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1280 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1281 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1283 // test system cert after date without CT fails (with check-in)
1284 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag-date non-CT cert with in-date asset succeeded");
1286 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
1287 (long)CFErrorGetCode(error), (int)errSecVerifyActionFailed);
1289 fail("expected trust evaluation to fail and it did not.");
1293 CFReleaseNull(system_root);
1294 CFReleaseNull(system_server_after);
1295 CFReleaseNull(policy);
1296 CFReleaseNull(trust);
1297 CFReleaseNull(error);
1299 #endif // !TARGET_OS_BRIDGE
1301 - (void)testWithTrustedLogs {
1302 SecCertificateRef system_root = NULL, system_server_after = NULL;
1303 SecTrustRef trust = NULL;
1304 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1305 NSArray *enforce_anchors = nil;
1306 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1307 CFErrorRef error = nil;
1309 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1310 errOut, fail("failed to create system root"));
1311 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1312 errOut, fail("failed to create system server cert issued after flag day"));
1314 enforce_anchors = @[ (__bridge id)system_root ];
1315 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1316 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1317 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1319 // set trusted logs to trigger enforcing behavior
1320 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1322 // test system cert after date without CT fails (with trusted logs)
1323 #if !TARGET_OS_BRIDGE
1324 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag-date non-CT cert with trusted logs succeeded");
1326 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
1327 (long)CFErrorGetCode(error), (int)errSecVerifyActionFailed);
1329 fail("expected trust evaluation to fail and it did not.");
1332 /* BridgeOS doesn't enforce */
1333 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert with trusted logs failed");
1337 CFReleaseNull(system_root);
1338 CFReleaseNull(system_server_after);
1339 CFReleaseNull(policy);
1340 CFReleaseNull(trust);
1341 CFReleaseNull(error);
1344 - (void)testExpiredCert {
1345 SecCertificateRef system_root = NULL, system_server_after = NULL;
1346 SecTrustRef trust = NULL;
1347 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1348 NSArray *enforce_anchors = nil;
1349 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:570000000.0]; // January 24, 2019 at 12:20:00 AM EST
1350 CFErrorRef error = nil;
1352 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1353 errOut, fail("failed to create system root"));
1354 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1355 errOut, fail("failed to create system server cert issued after flag day"));
1357 enforce_anchors = @[ (__bridge id)system_root ];
1358 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1359 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1360 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1362 // set trusted logs to trigger enforcing behavior
1363 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1365 // test expired system cert after date without CT passes with only expired error
1366 ok(SecTrustIsExpiredOnly(trust), "expired non-CT cert had non-expiration errors");
1369 CFReleaseNull(system_root);
1370 CFReleaseNull(system_server_after);
1371 CFReleaseNull(policy);
1372 CFReleaseNull(trust);
1373 CFReleaseNull(error);
1376 - (void)testTrustExceptions {
1377 SecCertificateRef system_root = NULL, system_server_after = NULL;
1378 SecTrustRef trust = NULL;
1379 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1380 NSArray *enforce_anchors = nil;
1381 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1382 CFErrorRef error = nil;
1383 CFDataRef exceptions = nil;
1385 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1386 errOut, fail("failed to create system root"));
1387 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1388 errOut, fail("failed to create system server cert issued after flag day"));
1390 enforce_anchors = @[ (__bridge id)system_root ];
1391 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1392 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1393 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1395 // set trusted logs to trigger enforcing behavior
1396 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1398 // test system cert after date without CT fails (with check-in)
1399 #if !TARGET_OS_BRIDGE
1400 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag-date non-CT cert with trusted logs succeeded");
1402 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
1403 (long)CFErrorGetCode(error), (int)errSecVerifyActionFailed);
1405 fail("expected trust evaluation to fail and it did not.");
1408 /* BridgeOS doesn't enforce */
1409 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert with trusted logs failed");
1412 // test exceptions for failing cert passes
1413 exceptions = SecTrustCopyExceptions(trust);
1414 ok(SecTrustSetExceptions(trust, exceptions), "failed to set exceptions for failing non-CT cert");
1415 CFReleaseNull(exceptions);
1416 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with exceptions set");
1417 SecTrustSetExceptions(trust, NULL);
1420 CFReleaseNull(system_root);
1421 CFReleaseNull(system_server_after);
1422 CFReleaseNull(policy);
1423 CFReleaseNull(trust);
1424 CFReleaseNull(error);
1425 CFReleaseNull(exceptions);
1428 - (void) testCATrustSettings {
1429 SecCertificateRef system_root = NULL, system_server_after = NULL;
1430 SecTrustRef trust = NULL;
1431 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1432 NSArray *enforce_anchors = nil;
1433 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1434 CFErrorRef error = nil;
1435 id persistentRef = nil;
1437 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1438 errOut, fail("failed to create system root"));
1439 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1440 errOut, fail("failed to create system server cert issued after flag day"));
1442 enforce_anchors = @[ (__bridge id)system_root ];
1443 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1444 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1446 // set trusted logs to trigger enforcing behavior
1447 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1449 // test system cert + enterprise anchor after date without CT fails
1450 #if !TARGET_OS_BRIDGE
1451 persistentRef = [self addTrustSettingsForCert:system_root];
1452 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag date non-CT cert with enterprise root trust succeeded");
1454 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
1455 (long)CFErrorGetCode(error), (int)errSecVerifyActionFailed);
1457 fail("expected trust evaluation to fail and it did not.");
1459 [self removeTrustSettingsForCert:system_root persistentRef:persistentRef];
1461 /* BridgeOS doesn't enforce (and doesn't use trust settings) */
1462 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1463 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert with trusted logs failed");
1467 CFReleaseNull(system_root);
1468 CFReleaseNull(system_server_after);
1469 CFReleaseNull(policy);
1470 CFReleaseNull(trust);
1471 CFReleaseNull(error);
1474 - (void) testAppSystem {
1475 SecCertificateRef system_root = NULL, system_server_after = NULL;
1476 SecTrustRef trust = NULL;
1477 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1478 NSArray *enforce_anchors = nil;
1479 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1480 CFErrorRef error = nil;
1482 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1483 errOut, fail("failed to create system root"));
1484 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1485 errOut, fail("failed to create system server cert issued after flag day"));
1487 enforce_anchors = @[ (__bridge id)system_root ];
1488 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1489 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1490 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1492 // set trusted logs to trigger enforcing behavior
1493 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1495 // test app anchor for failing cert passes
1496 enforce_anchors = @[ (__bridge id)system_server_after ];
1497 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1498 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert app anchor");
1500 CFReleaseNull(system_root);
1501 CFReleaseNull(system_server_after);
1502 CFReleaseNull(policy);
1503 CFReleaseNull(trust);
1504 CFReleaseNull(error);
1507 #if !TARGET_OS_BRIDGE
1508 /* bridgeOS doens't have trust settings */
1509 - (void) testLeafTrustSettings {
1510 SecCertificateRef system_root = NULL, system_server_after = NULL;
1511 SecTrustRef trust = NULL;
1512 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1513 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1514 CFErrorRef error = nil;
1515 id persistentRef = nil;
1517 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1518 errOut, fail("failed to create system root"));
1519 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1520 errOut, fail("failed to create system server cert issued after flag day"));
1522 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1523 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1525 // set trusted logs to trigger enforcing behavior
1526 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1528 // test trust settings for failing cert passes
1529 persistentRef = [self addTrustSettingsForCert:system_server_after];
1530 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert enterprise anchor");
1531 [self removeTrustSettingsForCert:system_server_after persistentRef:persistentRef];
1534 CFReleaseNull(system_root);
1535 CFReleaseNull(system_server_after);
1536 CFReleaseNull(policy);
1537 CFReleaseNull(trust);
1538 CFReleaseNull(error);
1540 #endif // !TARGET_OS_BRIDGE
1542 - (void) testEAPPolicy {
1543 SecCertificateRef system_root = NULL, system_server_after = NULL;
1544 SecTrustRef trust = NULL;
1545 SecPolicyRef policy = SecPolicyCreateEAP(true, NULL);
1546 NSArray *enforce_anchors = nil;
1547 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1549 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1550 errOut, fail("failed to create system root"));
1551 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1552 errOut, fail("failed to create system server cert issued after flag day"));
1554 enforce_anchors = @[ (__bridge id)system_root ];
1555 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1556 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1557 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1559 // set trusted logs to trigger enforcing behavior
1560 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1562 // EAP, test system cert after date without CT passes
1563 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with EAP cert");
1566 CFReleaseNull(system_root);
1567 CFReleaseNull(system_server_after);
1568 CFReleaseNull(policy);
1569 CFReleaseNull(trust);
1572 // Test pinning policy name
1573 - (void) testPinningPolicy {
1574 SecCertificateRef system_root = NULL, system_server_after = NULL;
1575 SecTrustRef trust = NULL;
1576 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1577 NSArray *enforce_anchors = nil;
1578 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1580 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1581 errOut, fail("failed to create system root"));
1582 require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"],
1583 errOut, fail("failed to create system server cert issued after flag day"));
1585 enforce_anchors = @[ (__bridge id)system_root ];
1586 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1587 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1588 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1591 require_noerr_action(SecTrustSetPinningPolicyName(trust, CFSTR("a-policy-name")), errOut, fail("failed to set policy name"));
1593 // set trusted logs to trigger enforcing behavior
1594 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1596 // pinning policy, test system cert after date without CT passes
1597 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with EAP cert");
1600 CFReleaseNull(system_root);
1601 CFReleaseNull(system_server_after);
1602 CFReleaseNull(policy);
1603 CFReleaseNull(trust);
1606 // test system cert after date with CT passes
1607 - (void) testAfterWithCT {
1608 SecCertificateRef system_root = NULL, system_server_after_with_CT = NULL;
1609 SecTrustRef trust = NULL;
1610 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1611 NSArray *enforce_anchors = nil;
1612 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1614 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1615 errOut, fail("failed to create system root"));
1616 require_action(system_server_after_with_CT = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after_scts"],
1617 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1619 enforce_anchors = @[ (__bridge id)system_root ];
1620 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
1621 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1622 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1623 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1624 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date CT cert failed");
1627 CFReleaseNull(system_root);
1628 CFReleaseNull(system_server_after_with_CT);
1629 CFReleaseNull(policy);
1630 CFReleaseNull(trust);
1633 // test system cert before date without CT passes
1634 - (void) testBefore {
1635 SecCertificateRef system_root = NULL, system_server_before = NULL;
1636 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1637 SecTrustRef trust = NULL;
1638 NSArray *enforce_anchors = nil;
1639 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1641 require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"],
1642 errOut, fail("failed to create system root"));
1643 require_action(system_server_before = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_before"],
1644 errOut, fail("failed to create system server cert issued before flag day"));
1646 enforce_anchors = @[ (__bridge id)system_root ];
1647 require_noerr_action(SecTrustCreateWithCertificates(system_server_before, policy, &trust), errOut, fail("failed to create trust"));
1648 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1649 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1650 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1651 ok(SecTrustEvaluateWithError(trust, NULL), "system pre-flag-date non-CT cert failed");
1654 CFReleaseNull(system_root);
1655 CFReleaseNull(system_server_before);
1656 CFReleaseNull(policy);
1657 CFReleaseNull(trust);
1660 #if !TARGET_OS_BRIDGE
1661 // test enterprise (non-public) after date without CT passes, except on bridgeOS which doesn't have trust settings
1662 - (void) testEnterpriseCA {
1663 SecCertificateRef user_root = NULL, user_server_after = NULL;
1664 SecTrustRef trust = NULL;
1665 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1666 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1667 id persistentRef = nil;
1669 require_action(user_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_user_root"],
1670 errOut, fail("failed to create user root"));
1671 require_action(user_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_user_server_after"],
1672 errOut, fail("failed to create user server cert issued after flag day"));
1674 persistentRef = [self addTrustSettingsForCert:user_root];
1675 require_noerr_action(SecTrustCreateWithCertificates(user_server_after, policy, &trust), errOut, fail("failed to create trust"));
1676 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1677 require_noerr_action(SecTrustSetTrustedLogs(trust,(__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1678 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with enterprise anchor");
1679 [self removeTrustSettingsForCert:user_root persistentRef:persistentRef];
1682 CFReleaseNull(user_root);
1683 CFReleaseNull(user_server_after);
1684 CFReleaseNull(policy);
1685 CFReleaseNull(trust);
1687 #endif // !TARGET_OS_BRIDGE
1689 // test app anchor (non-public) after date without CT passes
1690 - (void) testAppCA {
1691 SecCertificateRef user_root = NULL, user_server_after = NULL;
1692 SecTrustRef trust = NULL;
1693 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1694 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1695 NSArray *enforce_anchors = nil;
1697 require_action(user_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_user_root"],
1698 errOut, fail("failed to create user root"));
1699 require_action(user_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_user_server_after"],
1700 errOut, fail("failed to create user server cert issued after flag day"));
1702 enforce_anchors = @[ (__bridge id)user_root ];
1703 require_noerr_action(SecTrustCreateWithCertificates(user_server_after, policy, &trust), errOut, fail("failed to create trust"));
1704 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors"));
1705 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1706 require_noerr_action(SecTrustSetTrustedLogs(trust,(__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1707 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with enterprise anchor");
1710 CFReleaseNull(user_root);
1711 CFReleaseNull(user_server_after);
1712 CFReleaseNull(policy);
1713 CFReleaseNull(trust);
1716 // test apple anchor after date without CT passes
1717 - (void) testAppleAnchor {
1718 SecCertificateRef appleServerAuthCA = NULL, apple_server_after = NULL;
1719 SecTrustRef trust = NULL;
1720 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("bbasile-test.scv.apple.com"));
1721 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1722 NSArray *certs = nil;
1724 require_action(appleServerAuthCA = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_apple_ca"],
1725 errOut, fail("failed to create apple server auth CA"));
1726 require_action(apple_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_apple_server_after"],
1727 errOut, fail("failed to create apple server cert issued after flag day"));
1729 certs = @[ (__bridge id)apple_server_after, (__bridge id)appleServerAuthCA ];
1730 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
1731 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1732 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1733 ok(SecTrustEvaluateWithError(trust, NULL), "apple post-flag-date non-CT cert failed");
1736 CFReleaseNull(appleServerAuthCA);
1737 CFReleaseNull(apple_server_after);
1738 CFReleaseNull(policy);
1739 CFReleaseNull(trust);
1742 // test apple subCA after date without CT fails
1743 - (void) testAppleSubCAException {
1744 SecCertificateRef geoTrustRoot = NULL, appleISTCA8G1 = NULL, deprecatedSSLServer = NULL;
1745 SecTrustRef trust = NULL;
1746 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("bbasile-test.scv.apple.com"));
1747 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:576000000.0]; // April 3, 2019 at 9:00:00 AM PDT
1748 NSArray *certs = nil, *enforcement_anchors = nil;
1750 require_action(geoTrustRoot = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"GeoTrustPrimaryCAG2"],
1751 errOut, fail("failed to create geotrust root"));
1752 require_action(appleISTCA8G1 = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"AppleISTCA8G1"],
1753 errOut, fail("failed to create apple IST CA"));
1754 require_action(deprecatedSSLServer = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"deprecatedSSLServer"],
1755 errOut, fail("failed to create deprecated SSL Server cert"));
1757 certs = @[ (__bridge id)deprecatedSSLServer, (__bridge id)appleISTCA8G1 ];
1758 enforcement_anchors = @[ (__bridge id)geoTrustRoot ];
1759 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
1760 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1761 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforcement_anchors), errOut, fail("failed to set anchors"));
1762 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1763 #if !TARGET_OS_BRIDGE
1764 XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "apple public post-flag-date non-CT cert passed");
1768 CFReleaseNull(geoTrustRoot);
1769 CFReleaseNull(appleISTCA8G1);
1770 CFReleaseNull(deprecatedSSLServer);
1771 CFReleaseNull(policy);
1772 CFReleaseNull(trust);
1775 - (void) testBasejumper {
1776 SecCertificateRef baltimoreRoot = NULL, appleISTCA2 = NULL, deprecatedSSLServer = NULL;
1777 SecTrustRef trust = NULL;
1778 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("basejumper.apple.com"));
1779 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:576000000.0]; // April 3, 2019 at 9:00:00 AM PDT
1780 NSArray *certs = nil, *enforcement_anchors = nil;
1782 require_action(baltimoreRoot = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"BaltimoreCyberTrustRoot"],
1783 errOut, fail("failed to create geotrust root"));
1784 require_action(appleISTCA2 = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"AppleISTCA2_Baltimore"],
1785 errOut, fail("failed to create apple IST CA"));
1786 require_action(deprecatedSSLServer = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"basejumper"],
1787 errOut, fail("failed to create deprecated SSL Server cert"));
1789 certs = @[ (__bridge id)deprecatedSSLServer, (__bridge id)appleISTCA2 ];
1790 enforcement_anchors = @[ (__bridge id)baltimoreRoot ];
1791 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
1792 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1793 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforcement_anchors), errOut, fail("failed to set anchors"));
1794 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1795 XCTAssert(SecTrustEvaluateWithError(trust, NULL), "non-CT basejumper cert failed");
1797 #if !TARGET_OS_BRIDGE
1798 // bridgeOS doesn't ever enforce CT
1799 // Test with generic CT allowlist disable
1800 CFPreferencesSetAppValue(CFSTR("DisableCTAllowlist"), kCFBooleanTrue, CFSTR("com.apple.security"));
1801 CFPreferencesAppSynchronize(CFSTR("com.apple.security"));
1802 SecTrustSetNeedsEvaluation(trust);
1803 XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "non-CT basejumper succeeded with allowlist disabled");
1804 CFPreferencesSetAppValue(CFSTR("DisableCTAllowlist"), kCFBooleanFalse, CFSTR("com.apple.security"));
1805 CFPreferencesAppSynchronize(CFSTR("com.apple.security"));
1807 // Test with Apple allowlist disable
1808 CFPreferencesSetAppValue(CFSTR("DisableCTAllowlistApple"), kCFBooleanTrue, CFSTR("com.apple.security"));
1809 CFPreferencesAppSynchronize(CFSTR("com.apple.security"));
1810 SecTrustSetNeedsEvaluation(trust);
1811 XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "non-CT basejumper succeeded with Apple allowlist disabled");
1812 CFPreferencesSetAppValue(CFSTR("DisableCTAllowlistApple"), kCFBooleanFalse, CFSTR("com.apple.security"));
1813 CFPreferencesAppSynchronize(CFSTR("com.apple.security"));
1814 #endif // !TARGET_OS_BRIDGE
1817 CFReleaseNull(baltimoreRoot);
1818 CFReleaseNull(appleISTCA2);
1819 CFReleaseNull(deprecatedSSLServer);
1820 CFReleaseNull(policy);
1821 CFReleaseNull(trust);
1824 // test google subCA after date without CT fails
1825 - (void) testGoogleSubCAException {
1826 SecCertificateRef globalSignRoot = NULL, googleIAG3 = NULL, google = NULL;
1827 SecTrustRef trust = NULL;
1828 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("www.google.com"));
1829 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1830 NSArray *certs = nil, *enforcement_anchors = nil;
1832 require_action(globalSignRoot = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"GlobalSignRootCAR2"],
1833 errOut, fail("failed to create geotrust root"));
1834 require_action(googleIAG3 = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"GoogleIAG3"],
1835 errOut, fail("failed to create apple IST CA"));
1836 require_action(google = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"google"],
1837 errOut, fail("failed to create livability cert"));
1839 certs = @[ (__bridge id)google, (__bridge id)googleIAG3 ];
1840 enforcement_anchors = @[ (__bridge id)globalSignRoot ];
1841 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
1842 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1843 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforcement_anchors), errOut, fail("failed to set anchors"));
1844 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1845 #if !TARGET_OS_BRIDGE
1846 XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "google public post-flag-date non-CT cert passed");
1850 CFReleaseNull(globalSignRoot);
1851 CFReleaseNull(googleIAG3);
1852 CFReleaseNull(google);
1853 CFReleaseNull(policy);
1854 CFReleaseNull(trust);
1857 // If pinning is disabled, pinned hostnames should continue to be exempt from CT
1858 - (void) testSystemwidePinningDisable {
1859 SecCertificateRef baltimoreRoot = NULL, appleISTCA2 = NULL, pinnedNonCT = NULL;
1860 SecTrustRef trust = NULL;
1861 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("iphonesubmissions.apple.com"));
1862 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:580000000.0]; // May 19, 2019 at 4:06:40 PM PDT
1863 NSArray *certs = nil, *enforcement_anchors = nil;
1864 NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.apple.security"];
1866 require_action(baltimoreRoot = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"BaltimoreCyberTrustRoot"],
1867 errOut, fail("failed to create geotrust root"));
1868 require_action(appleISTCA2 = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"AppleISTCA2_Baltimore"],
1869 errOut, fail("failed to create apple IST CA"));
1870 require_action(pinnedNonCT = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"iphonesubmissions"],
1871 errOut, fail("failed to create deprecated SSL Server cert"));
1873 certs = @[ (__bridge id)pinnedNonCT, (__bridge id)appleISTCA2 ];
1874 enforcement_anchors = @[ (__bridge id)baltimoreRoot ];
1875 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
1876 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1877 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforcement_anchors), errOut, fail("failed to set anchors"));
1878 require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs"));
1879 XCTAssert(SecTrustEvaluateWithError(trust, NULL), "pinned non-CT cert failed");
1881 // Test with pinning disabled
1882 [defaults setBool:YES forKey:@"AppleServerAuthenticationNoPinning"];
1883 [defaults synchronize];
1884 SecTrustSetNeedsEvaluation(trust);
1885 XCTAssert(SecTrustEvaluateWithError(trust, NULL), "pinned non-CT failed with pinning disabled");
1886 [defaults setBool:NO forKey:@"AppleServerAuthenticationNoPinning"];
1887 [defaults synchronize];
1890 CFReleaseNull(baltimoreRoot);
1891 CFReleaseNull(appleISTCA2);
1892 CFReleaseNull(pinnedNonCT);
1893 CFReleaseNull(policy);
1894 CFReleaseNull(trust);