5 * Copyright (c) 2014 Apple Inc. All Rights Reserved.
9 #include <AssertMacros.h>
10 #include <CoreFoundation/CoreFoundation.h>
11 #include <Security/SecCertificatePriv.h>
12 #include <Security/SecTrustPriv.h>
13 #include <Security/SecPolicyPriv.h>
16 #include <utilities/SecCFWrappers.h>
17 #include <Security/SecTrustSettings.h>
18 #include <Security/SecTrustSettingsPriv.h>
19 #include <Security/SecFramework.h>
22 #include <Security/SecTrustStore.h>
24 #include <Security/SecKeychain.h>
27 #include "shared_regressions.h"
28 #include "si-82-sectrust-ct.h"
30 //define this if you want to print clock time of SecTrustEvaluate call.
31 //define PRINT_SECTRUST_EVALUATE_TIME
33 static bool isCFTrue(CFTypeRef cf)
35 return (cf == kCFBooleanTrue);
38 static void test_ct_trust(CFArrayRef certs, CFArrayRef scts, CFTypeRef ocspresponses, CFArrayRef anchors,
39 CFArrayRef trustedLogs, CFStringRef hostname, CFDateRef date,
40 bool ct_expected, bool ev_expected, bool ct_whitelist_expected,
41 const char *test_name)
43 CFArrayRef policies=NULL;
44 SecPolicyRef policy=NULL;
45 SecTrustRef trust=NULL;
46 SecTrustResultType trustResult;
47 CFDictionaryRef results=NULL;
48 CFArrayRef properties=NULL;
52 isnt(policy = SecPolicyCreateSSL(true, hostname), NULL, "create policy");
53 isnt(policies = CFArrayCreate(kCFAllocatorDefault, (const void **)&policy, 1, &kCFTypeArrayCallBacks), NULL, "create policies");
54 ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust");
56 assert(trust); // silence analyzer
58 ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors");
62 #pragma clang diagnostic push
63 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
64 ok_status(SecTrustSetSignedCertificateTimestamps(trust, scts), "set standalone SCTs");
65 #pragma clang diagnostic pop
69 ok_status(SecTrustSetTrustedLogs(trust, trustedLogs), "set trusted logs");
73 ok_status(SecTrustSetOCSPResponse(trust, ocspresponses), "set ocsp responses");
76 if (!date) { goto errOut; }
77 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
78 #ifdef PRINT_SECTRUST_EVALUATE_TIME
81 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
82 #ifdef PRINT_SECTRUST_EVALUATE_TIME
83 clock_t t1 = clock() - t0;
85 ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)",
88 results = SecTrustCopyResult(trust);
90 CFTypeRef ct = CFDictionaryGetValue(results, kSecTrustCertificateTransparency);
91 CFTypeRef ev = CFDictionaryGetValue(results, kSecTrustExtendedValidation);
92 CFTypeRef ct_whitelist = CFDictionaryGetValue(results, kSecTrustCertificateTransparencyWhiteList);
95 ok((isCFTrue(ct) == ct_expected), "unexpected CT result (%s)", test_name);
96 ok((isCFTrue(ev) == ev_expected), "unexpected EV result (%s)", test_name);
97 ok((isCFTrue(ct_whitelist) == ct_whitelist_expected), "unexpected CT WhiteList result (%s)", test_name);
98 /* Note that the CT whitelist has been removed due to the expiration of all contents. */
100 #ifdef PRINT_SECTRUST_EVALUATE_TIME
101 printf("%s: %lu\n", test_name, t1);
104 properties = SecTrustCopyProperties(trust);
107 CFReleaseSafe(policy);
108 CFReleaseSafe(policies);
109 CFReleaseSafe(trust);
110 CFReleaseSafe(results);
111 CFReleaseSafe(properties);
114 #import <Foundation/Foundation.h>
117 SecCertificateRef SecCertificateCreateFromResource(NSString *name)
119 NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".cer" subdirectory:@"si-82-sectrust-ct-data"];
121 NSData *certData = [NSData dataWithContentsOfURL:url];
123 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData);
129 CFDataRef CFDataCreateFromResource(NSString *name)
131 NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".bin" subdirectory:@"si-82-sectrust-ct-data"];
133 NSData *binData = [[NSData alloc] initWithContentsOfURL:url];
135 return (__bridge_retained CFDataRef) binData;
138 static CFArrayRef CTTestsCopyTrustedLogs(void) {
139 CFArrayRef trustedLogs=NULL;
140 CFURLRef trustedLogsURL=NULL;
142 trustedLogsURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
145 CFSTR("si-82-sectrust-ct-data"));
146 isnt(trustedLogsURL, NULL, "trustedLogsURL");
147 trustedLogs = (CFArrayRef) CFPropertyListReadFromFile(trustedLogsURL);
148 isnt(trustedLogs, NULL, "trustedLogs");
150 CFReleaseNull(trustedLogsURL);
156 SecCertificateRef certA=NULL, certD=NULL, certF=NULL, certCA_alpha=NULL, certCA_beta=NULL;
157 CFDataRef proofD=NULL, proofA_1=NULL, proofA_2=NULL;
158 SecCertificateRef www_digicert_com_2015_cert=NULL, www_digicert_com_2016_cert=NULL, digicert_sha2_ev_server_ca=NULL;
159 SecCertificateRef www_paypal_com_cert=NULL, www_paypal_com_issuer_cert=NULL;
160 SecCertificateRef pilot_cert_3055998=NULL, pilot_cert_3055998_issuer=NULL;
161 SecCertificateRef whitelist_00008013=NULL, whitelist_5555bc4f=NULL, whitelist_aaaae152=NULL, whitelist_fff9b5f6=NULL;
162 SecCertificateRef whitelist_00008013_issuer=NULL, whitelist_5555bc4f_issuer=NULL, whitelist_fff9b5f6_issuer=NULL;
163 SecCertificateRef cfCert = NULL;
164 CFMutableArrayRef certs=NULL;
165 CFMutableArrayRef scts=NULL;
166 CFMutableArrayRef anchors=NULL;
167 CFDataRef valid_ocsp=NULL;
168 CFDataRef invalid_ocsp=NULL;
169 CFDataRef bad_hash_ocsp=NULL;
171 CFArrayRef trustedLogs= CTTestsCopyTrustedLogs();
173 isnt(certCA_alpha = SecCertificateCreateFromResource(@"CA_alpha"), NULL, "create ca-alpha cert");
174 isnt(certCA_beta = SecCertificateCreateFromResource(@"CA_beta"), NULL, "create ca-beta cert");
175 isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array");
176 CFArrayAppendValue(anchors, certCA_alpha);
177 CFArrayAppendValue(anchors, certCA_beta);
178 isnt(certA = SecCertificateCreateFromResource(@"serverA"), NULL, "create certA");
179 isnt(certD = SecCertificateCreateFromResource(@"serverD"), NULL, "create certD");
180 isnt(certF = SecCertificateCreateFromResource(@"serverF"), NULL, "create certF");
181 isnt(proofD = CFDataCreateFromResource(@"serverD_proof"), NULL, "creat proofD");
182 isnt(proofA_1 = CFDataCreateFromResource(@"serverA_proof_Alfa_3"), NULL, "creat proofA_1");
183 isnt(proofA_2 = CFDataCreateFromResource(@"serverA_proof_Bravo_3"), NULL, "creat proofA_2");
184 isnt(www_digicert_com_2015_cert = SecCertificateCreateFromResource(@"www_digicert_com_2015"), NULL, "create www.digicert.com 2015 cert");
185 isnt(www_digicert_com_2016_cert = SecCertificateCreateFromResource(@"www_digicert_com_2016"), NULL, "create www.digicert.com 2016 cert");
186 isnt(digicert_sha2_ev_server_ca = SecCertificateCreateFromResource(@"digicert_sha2_ev_server_ca"), NULL, "create digicert.com subCA cert");
187 isnt(www_paypal_com_cert = SecCertificateCreateFromResource(@"www_paypal_com"), NULL, "create www.paypal.com cert");
188 isnt(www_paypal_com_issuer_cert = SecCertificateCreateFromResource(@"www_paypal_com_issuer"), NULL, "create www.paypal.com issuer cert");
189 isnt(valid_ocsp = CFDataCreateFromResource(@"valid_ocsp_response"), NULL, "create valid_ocsp");
190 isnt(invalid_ocsp = CFDataCreateFromResource(@"invalid_ocsp_response"), NULL, "create invalid_ocsp");
191 isnt(bad_hash_ocsp = CFDataCreateFromResource(@"bad_hash_ocsp_response"), NULL, "create bad_hash_ocsp");
192 isnt(pilot_cert_3055998 = SecCertificateCreateFromResource(@"pilot_3055998"), NULL, "create pilot_cert_3055998 cert");
193 isnt(pilot_cert_3055998_issuer = SecCertificateCreateFromResource(@"pilot_3055998_issuer"), NULL, "create pilot_cert_3055998 issuer cert");
195 isnt(whitelist_00008013 = SecCertificateCreateFromResource(@"whitelist_00008013"), NULL, "create whitelist_00008013 cert");
196 isnt(whitelist_5555bc4f = SecCertificateCreateFromResource(@"whitelist_5555bc4f"), NULL, "create whitelist_5555bc4f cert");
197 isnt(whitelist_aaaae152 = SecCertificateCreateFromResource(@"whitelist_aaaae152"), NULL, "create whitelist_aaaae152 cert");
198 isnt(whitelist_fff9b5f6 = SecCertificateCreateFromResource(@"whitelist_fff9b5f6"), NULL, "create whitelist_fff9b5f6 cert");
199 isnt(whitelist_00008013_issuer = SecCertificateCreateFromResource(@"whitelist_00008013_issuer"), NULL, "create whitelist_00008013_issuer cert");
200 isnt(whitelist_5555bc4f_issuer = SecCertificateCreateFromResource(@"whitelist_5555bc4f_issuer"), NULL, "create whitelist_5555bc4f_issuer cert");
201 isnt(whitelist_fff9b5f6_issuer = SecCertificateCreateFromResource(@"whitelist_fff9b5f6_issuer"), NULL, "create whitelist_fff9b5f6_issuer cert");
203 CFCalendarRef cal = NULL;
205 CFDateRef date_20150307 = NULL; // Date for older set of tests.
206 CFDateRef date_20160422 = NULL; // Date for newer set of tests.
208 isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar");
209 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2015, 3, 7), "create verify absolute time 20150307");
210 isnt(date_20150307 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20150307");
211 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2016, 4, 22), "create verify absolute time 20160422");
212 isnt(date_20160422 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20160422");
215 /* Case 1: coreos-ct-test embedded SCT - only 1 SCT - so not CT qualified */
216 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
217 CFArrayAppendValue(certs, certF);
218 test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, NULL, date_20150307,
219 false, false, false, "coreos-ct-test 1");
220 CFReleaseNull(certs);
222 /* Case 2: coreos-ct-test standalone SCT - only 1 SCT - so not CT qualified */
223 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
224 CFArrayAppendValue(certs, certD);
225 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
226 CFArrayAppendValue(scts, proofD);
227 test_ct_trust(certs, scts, NULL, anchors, trustedLogs, NULL, date_20150307,
228 false, false, false, "coreos-ct-test 2");
229 CFReleaseNull(certs);
232 /* case 3: digicert : 2 embedded SCTs, but lifetime of cert is 24 month, so not CT qualified */
233 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
234 CFArrayAppendValue(certs, www_digicert_com_2015_cert);
235 CFArrayAppendValue(certs, digicert_sha2_ev_server_ca);
236 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.digicert.com"), date_20150307,
237 false, false, false, "digicert 2015");
238 CFReleaseNull(certs);
240 /* Case 4: coreos-ct-test standalone SCT - 2 SCTs - CT qualified */
241 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
242 CFArrayAppendValue(certs, certA);
243 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
244 CFArrayAppendValue(scts, proofA_1);
245 CFArrayAppendValue(scts, proofA_2);
246 test_ct_trust(certs, scts, NULL, anchors, trustedLogs, NULL, date_20150307,
247 true, false, false, "coreos-ct-test 3");
248 CFReleaseNull(certs);
251 /* Case 5: Test with an invalid OCSP response */
252 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
253 CFArrayAppendValue(certs, certA);
254 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
255 CFArrayAppendValue(scts, proofA_1);
256 test_ct_trust(certs, scts, invalid_ocsp, anchors, trustedLogs, NULL, date_20150307,
257 false, false, false, "coreos-ct-test 4");
258 CFReleaseNull(certs);
261 /* Case 6: Test with a valid OCSP response */
262 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
263 CFArrayAppendValue(certs, certA);
264 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
265 CFArrayAppendValue(scts, proofA_1);
266 test_ct_trust(certs, scts, valid_ocsp, anchors, trustedLogs, NULL, date_20150307,
267 false, false, false, "coreos-ct-test 5");
268 CFReleaseNull(certs);
271 /* Case 7: Test with a bad hash OCSP response */
272 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
273 CFArrayAppendValue(certs, certA);
274 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
275 CFArrayAppendValue(scts, proofA_1);
276 test_ct_trust(certs, scts, bad_hash_ocsp, anchors, trustedLogs, NULL, date_20150307,
277 false, false, false, "coreos-ct-test 6");
278 CFReleaseNull(certs);
281 /* case 8: Current (April 2016) www.digicert.com cert: 3 embedded SCTs, CT qualified */
282 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
283 CFArrayAppendValue(certs, www_digicert_com_2016_cert);
284 CFArrayAppendValue(certs, digicert_sha2_ev_server_ca);
285 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.digicert.com"), date_20160422,
286 true, true, false, "digicert 2016");
287 CFReleaseNull(certs);
291 #define TEST_CASE(x) \
293 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array for " #x); \
294 isnt(cfCert = SecCertificateCreateFromResource(@#x), NULL, "create cfCert from " #x); \
295 CFArrayAppendValue(certs, cfCert); \
296 test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, NULL, date_20150307, true, false, false, #x); \
297 CFReleaseNull(certs); \
298 CFReleaseNull(cfCert); \
302 TEST_CASE(server_1601);
303 TEST_CASE(server_1603);
304 TEST_CASE(server_1604);
305 TEST_CASE(server_1701);
306 TEST_CASE(server_1704);
307 TEST_CASE(server_1705);
308 TEST_CASE(server_1801);
309 TEST_CASE(server_1804);
310 TEST_CASE(server_1805);
311 TEST_CASE(server_2001);
314 CFReleaseSafe(certCA_alpha);
315 CFReleaseSafe(certCA_beta);
316 CFReleaseSafe(anchors);
317 CFReleaseSafe(certA);
318 CFReleaseSafe(certD);
319 CFReleaseSafe(certF);
320 CFReleaseSafe(proofD);
321 CFReleaseSafe(proofA_1);
322 CFReleaseSafe(proofA_2);
323 CFReleaseSafe(www_digicert_com_2015_cert);
324 CFReleaseSafe(www_digicert_com_2016_cert);
325 CFReleaseSafe(digicert_sha2_ev_server_ca);
326 CFReleaseSafe(www_paypal_com_cert);
327 CFReleaseSafe(www_paypal_com_issuer_cert);
328 CFReleaseSafe(pilot_cert_3055998);
329 CFReleaseSafe(pilot_cert_3055998_issuer);
330 CFReleaseSafe(whitelist_00008013);
331 CFReleaseSafe(whitelist_5555bc4f);
332 CFReleaseSafe(whitelist_aaaae152);
333 CFReleaseSafe(whitelist_fff9b5f6);
334 CFReleaseSafe(whitelist_00008013_issuer);
335 CFReleaseSafe(whitelist_5555bc4f_issuer);
336 CFReleaseSafe(whitelist_fff9b5f6_issuer);
337 CFReleaseSafe(trustedLogs);
338 CFReleaseSafe(valid_ocsp);
339 CFReleaseSafe(invalid_ocsp);
340 CFReleaseSafe(bad_hash_ocsp);
342 CFReleaseSafe(date_20150307);
343 CFReleaseSafe(date_20160422);
347 static void test_sct_serialization(void) {
348 SecCertificateRef certA = NULL, certCA_alpha = NULL, certCA_beta = NULL;
349 CFArrayRef trustedLogs= CTTestsCopyTrustedLogs();
350 SecTrustRef trust = NULL, deserializedTrust = NULL;
351 SecPolicyRef policy = SecPolicyCreateSSL(true, NULL);
352 NSData *proofA_1 = NULL, *proofA_2 = NULL;
353 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:447450000.0]; // March 7, 2015 at 11:40:00 AM PST
354 CFErrorRef error = NULL;
356 isnt(certA = SecCertificateCreateFromResource(@"serverA"), NULL, "create certA");
357 isnt(certCA_alpha = SecCertificateCreateFromResource(@"CA_alpha"), NULL, "create ca-alpha cert");
358 isnt(certCA_beta = SecCertificateCreateFromResource(@"CA_beta"), NULL, "create ca-beta cert");
360 NSArray *anchors = @[ (__bridge id)certCA_alpha, (__bridge id)certCA_beta ];
362 isnt(proofA_1 = CFBridgingRelease(CFDataCreateFromResource(@"serverA_proof_Alfa_3")), NULL, "creat proofA_1");
363 isnt(proofA_2 = CFBridgingRelease(CFDataCreateFromResource(@"serverA_proof_Bravo_3")), NULL, "creat proofA_2");
364 NSArray *scts = @[ proofA_1, proofA_2 ];
366 /* Make a SecTrustRef and then serialize it */
367 ok_status(SecTrustCreateWithCertificates(certA, policy, &trust), "failed to create trust object");
368 ok_status(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), "failed to set anchors");
369 ok_status(SecTrustSetTrustedLogs(trust, trustedLogs), "failed to set trusted logs");
370 ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "failed to set verify date");
372 #pragma clang diagnostic push
373 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
374 ok_status(SecTrustSetSignedCertificateTimestamps(trust, (__bridge CFArrayRef)scts), "failed to set SCTS");
375 #pragma clang diagnostic pop
377 NSData *serializedTrust = CFBridgingRelease(SecTrustSerialize(trust, &error));
378 isnt(serializedTrust, NULL, "failed to serialize trust: %@", error);
380 /* Evaluate it to make sure it's CT */
381 ok(SecTrustEvaluateWithError(trust, &error), "failed to evaluate trust: %@", error);
382 NSDictionary *results = CFBridgingRelease(SecTrustCopyResult(trust));
383 isnt(results[(__bridge NSString*)kSecTrustCertificateTransparency], NULL, "failed get CT result");
384 ok([results[(__bridge NSString*)kSecTrustCertificateTransparency] boolValue], "CT failed");
386 /* Make a new trust object by deserializing the previous trust object */
387 ok(deserializedTrust = SecTrustDeserialize((__bridge CFDataRef)serializedTrust, &error), "failed to deserialize trust: %@", error);
389 /* Evaluate the new one to make sure it's CT (because the SCTs were serialized) */
390 ok(SecTrustEvaluateWithError(deserializedTrust, &error), "failed to evaluate trust: %@", error);
391 results = CFBridgingRelease(SecTrustCopyResult(deserializedTrust));
392 isnt(results[(__bridge NSString*)kSecTrustCertificateTransparency], NULL, "failed get CT result");
393 ok([results[(__bridge NSString*)kSecTrustCertificateTransparency] boolValue], "CT failed");
395 CFReleaseNull(certA);
396 CFReleaseNull(certCA_alpha);
397 CFReleaseNull(certCA_beta);
398 CFReleaseNull(trustedLogs);
399 CFReleaseNull(policy);
400 CFReleaseNull(trust);
401 CFReleaseNull(deserializedTrust);
402 CFReleaseNull(error);
405 static void testSetCTExceptions(void) {
406 CFErrorRef error = NULL;
407 const CFStringRef SecurityTestsAppID = CFSTR("com.apple.security.regressions");
408 const CFStringRef AnotherAppID = CFSTR("com.apple.security.not-this-one");
409 CFDictionaryRef copiedExceptions = NULL;
411 /* Verify no exceptions set */
412 is(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, NULL), NULL, "no exceptions set");
413 if (copiedExceptions) {
414 /* If we're starting out with exceptions set, a lot of the following will also fail, so just skip them */
415 CFReleaseNull(copiedExceptions);
419 /* Set exceptions with specified AppID */
420 NSDictionary *exceptions1 = @{
421 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@"test.apple.com", @".test.apple.com"],
423 ok(SecTrustStoreSetCTExceptions(SecurityTestsAppID, (__bridge CFDictionaryRef)exceptions1, &error),
424 "failed to set exceptions for SecurityTests: %@", error);
426 /* Copy all exceptions (with only one set) */
427 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, &error),
428 "failed to copy all exceptions: %@", error);
429 ok([exceptions1 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
430 "got the wrong exceptions back");
431 CFReleaseNull(copiedExceptions);
433 /* Copy this app's exceptions */
434 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(SecurityTestsAppID, &error),
435 "failed to copy SecurityTests' exceptions: %@", error);
436 ok([exceptions1 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
437 "got the wrong exceptions back");
438 CFReleaseNull(copiedExceptions);
440 /* Copy a different app's exceptions */
441 is(copiedExceptions = SecTrustStoreCopyCTExceptions(AnotherAppID, &error), NULL,
442 "failed to copy different app's exceptions: %@", error);
443 CFReleaseNull(copiedExceptions);
445 /* Set different exceptions with implied AppID */
446 CFDataRef leafHash = SecSHA256DigestCreate(NULL, _system_after_leafSPKI, sizeof(_system_after_leafSPKI));
447 NSDictionary *leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
448 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)leafHash,
451 NSDictionary *exceptions2 = @{
452 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@".test.apple.com"],
453 (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ]
455 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions2, &error),
456 "failed to set exceptions for this app: %@", error);
458 /* Ensure exceptions are replaced for SecurityTests */
459 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(SecurityTestsAppID, &error),
460 "failed to copy SecurityTests' exceptions: %@", error);
461 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
462 "got the wrong exceptions back");
463 CFReleaseNull(copiedExceptions);
465 /* Set exceptions with a different AppID */
466 CFDataRef rootHash = SecSHA256DigestCreate(NULL, _system_rootSPKI, sizeof(_system_rootSPKI));
467 NSDictionary *rootExceptions = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
468 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)rootHash,
470 NSDictionary *exceptions3 = @{
471 (__bridge NSString*)kSecCTExceptionsCAsKey : @[ rootExceptions ]
473 ok(SecTrustStoreSetCTExceptions(AnotherAppID, (__bridge CFDictionaryRef)exceptions3, &error),
474 "failed to set exceptions for different app: %@", error);
476 /* Copy only one of the app's exceptions */
477 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(SecurityTestsAppID, &error),
478 "failed to copy SecurityTests' exceptions: %@", error);
479 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
480 "got the wrong exceptions back");
481 CFReleaseNull(copiedExceptions);
483 /* Set empty exceptions */
484 NSDictionary *empty = @{};
485 ok(SecTrustStoreSetCTExceptions(SecurityTestsAppID, (__bridge CFDictionaryRef)empty, &error),
486 "failed to set empty exceptions");
488 /* Copy exceptiosn to ensure no change */
489 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(SecurityTestsAppID, &error),
490 "failed to copy SecurityTests' exceptions: %@", error);
491 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
492 "got the wrong exceptions back");
493 CFReleaseNull(copiedExceptions);
495 /* Copy all exceptions */
496 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, &error),
497 "failed to copy all exceptions: %@", error);
498 is(CFDictionaryGetCount(copiedExceptions), 2, "Got the wrong number of all exceptions");
499 NSDictionary *nsCopiedExceptions = CFBridgingRelease(copiedExceptions);
500 NSArray *domainExceptions = nsCopiedExceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey];
501 NSArray *caExceptions = nsCopiedExceptions[(__bridge NSString*)kSecCTExceptionsCAsKey];
502 ok(domainExceptions && caExceptions, "Got both domain and CA exceptions");
503 ok([domainExceptions count] == 1, "Got 1 domain exception");
504 ok([caExceptions count] == 2, "Got 2 CA exceptions");
505 ok([domainExceptions[0] isEqualToString:@".test.apple.com"], "domain exception is .test.apple.com");
506 ok([caExceptions containsObject:leafException] && [caExceptions containsObject:rootExceptions], "got expected leaf and root CA exceptions");
508 /* Reset other app's exceptions */
509 ok(SecTrustStoreSetCTExceptions(AnotherAppID, NULL, &error),
510 "failed to reset exceptions for different app: %@", error);
511 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, &error),
512 "failed to copy all exceptions: %@", error);
513 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
514 "got the wrong exceptions back");
515 CFReleaseNull(copiedExceptions);
517 #define check_errSecParam \
519 is(CFErrorGetCode(error), errSecParam, "bad input produced unxpected error code: %ld", (long)CFErrorGetCode(error)); \
521 fail("expected failure to set NULL exceptions"); \
524 /* Set exceptions with bad inputs */
525 NSDictionary *badExceptions = @{
526 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@"test.apple.com", @".test.apple.com"],
527 @"not a key": @"not a value",
529 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
530 "set exceptions with unknown key");
533 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey:@"test.apple.com" };
534 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
535 "set exceptions with bad value");
538 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey: @[ @{} ] };
539 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
540 "set exceptions with bad array value");
543 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @"test.apple.com" ] };
544 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
545 "set exceptions with bad array value");
548 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
549 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
550 @"not-a-key" : (__bridge NSData*)rootHash,
552 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
553 "set exceptions with bad CA dictionary value");
556 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
557 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
559 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
560 "set exceptions with bad CA dictionary value");
563 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
564 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
565 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)rootHash,
566 @"not-a-key":@"not-a-value"
568 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
569 "set exceptions with bad CA dictionary value");
572 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey: @[ @".com" ] };
573 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
574 "set exceptions with TLD value");
576 #undef check_errSecParam
578 /* Remove exceptions using empty arrays */
579 NSDictionary *emptyArrays = @{
580 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[],
581 (__bridge NSString*)kSecCTExceptionsCAsKey : @[]
583 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)emptyArrays, &error),
584 "failed to set empty array exceptions for this app: %@", error);
585 is(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, NULL), NULL, "no exceptions set");
587 CFReleaseNull(leafHash);
588 CFReleaseNull(rootHash);
591 static void setup_for_user_trust(NSArray *in_certs, NSArray **deleteMeCertificates) {
593 /* Since we're putting trust settings in the admin domain,
594 * we need to add the certs to the system keychain. */
595 SecKeychainRef kcRef = NULL;
596 CFArrayRef certRef = NULL;
597 NSDictionary *attrs = nil;
598 NSMutableArray *persistenRefs = nil;
600 SecKeychainOpen("/Library/Keychains/System.keychain", &kcRef);
605 persistenRefs = [[NSMutableArray alloc] init];
607 for (id cert in in_certs) {
608 attrs = @{(__bridge NSString*)kSecValueRef: cert,
609 (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
610 (__bridge NSString*)kSecReturnPersistentRef: @YES};
611 if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
612 [persistenRefs addObject:(__bridge NSArray *)certRef];
613 CFReleaseNull(certRef);
616 CFReleaseNull(kcRef);
617 *deleteMeCertificates = persistenRefs;
621 static void cleanup_keychain(NSArray *deleteMeCertificates) {
623 if (!deleteMeCertificates) {
627 [deleteMeCertificates enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
628 SecItemDelete((CFDictionaryRef)@{ (__bridge NSString*)kSecValuePersistentRef: [obj objectAtIndex:0]});
633 static bool set_trust_settings_for_cert(SecCertificateRef cert) {
635 NSDictionary *settings = nil;
636 if (!SecCertificateIsSelfSignedCA(cert)) {
637 settings = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
640 require_noerr_string(SecTrustStoreSetTrustSettings(SecTrustStoreForDomain(kSecTrustStoreDomainUser), cert,
641 (__bridge CFDictionaryRef)settings),
642 errOut, "failed to set trust settings");
644 require_noerr_string(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin,
645 (__bridge CFDictionaryRef)settings),
646 errOut, "failed to set trust settings");
654 static bool remove_trust_settings_for_cert(SecCertificateRef cert) {
657 require_noerr_string(SecTrustStoreRemoveCertificate(SecTrustStoreForDomain(kSecTrustStoreDomainUser), cert),
658 errOut, "failed to remove trust settings");
660 require_noerr_string(SecTrustSettingsRemoveTrustSettings(cert, kSecTrustSettingsDomainAdmin),
661 errOut, "failed to remove trust settings");
668 static void test_enforcement(void) {
669 SecCertificateRef system_root = NULL, user_root = NULL;
670 SecCertificateRef system_server_before = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
671 SecCertificateRef user_server_after = NULL;
672 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
673 SecTrustRef trust = NULL;
674 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
675 NSArray *anchors = nil, *keychain_certs = nil;
676 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
677 NSDate *expiredDate = [NSDate dateWithTimeIntervalSinceReferenceDate:570000000.0]; // January 24, 2019 at 12:20:00 AM EST
678 CFErrorRef error = nil;
679 CFDataRef exceptions = nil;
681 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
682 errOut, fail("failed to create system root"));
683 require_action(user_root = SecCertificateCreateFromResource(@"enforcement_user_root"),
684 errOut, fail("failed to create user root"));
685 require_action(system_server_before = SecCertificateCreateFromResource(@"enforcement_system_server_before"),
686 errOut, fail("failed to create system server cert issued before flag day"));
687 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
688 errOut, fail("failed to create system server cert issued after flag day"));
689 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
690 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
691 require_action(user_server_after = SecCertificateCreateFromResource(@"enforcement_user_server_after"),
692 errOut, fail("failed to create user server cert issued after flag day"));
694 /* set up the user and system roots to be used with trust settings */
695 setup_for_user_trust(@[(__bridge id)system_root, (__bridge id)user_root, (__bridge id)system_server_after],
697 anchors = @[ (__bridge id)system_root ];
698 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
699 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
700 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
702 #if 0 // Disable this test until we can mock MobileAsset and force asset to be out-of-date
703 // Out-of-date asset, test system cert after date without CT passes
704 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with out-of-date asset");
707 // test system cert after date without CT fails
708 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
709 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag-date non-CT cert with in-date asset succeeded");
711 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
712 (long)CFErrorGetCode(error), errSecVerifyActionFailed);
714 fail("expected trust evaluation to fail and it did not.");
717 // test expired system cert after date without CT passes with only expiration error
718 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)expiredDate), errOut, fail("failed to set verify date"));
719 ok(SecTrustIsExpiredOnly(trust), "expired system post-flag-date non-CT cert had non-expiration errors");
720 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
722 // test exceptions for failing cert passes
723 exceptions = SecTrustCopyExceptions(trust);
724 ok(SecTrustSetExceptions(trust, exceptions), "failed to set exceptions for failing non-CT cert");
725 CFReleaseNull(exceptions);
726 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with exceptions set");
727 SecTrustSetExceptions(trust, NULL);
729 // test system cert + enterprise anchor after date without CT fails
730 #pragma clang diagnostic push
731 #pragma clang diagnostic ignored "-Wnonnull" /* required because of <rdar://32627101> */
732 require_noerr_action(SecTrustSetAnchorCertificates(trust, NULL), errOut, fail("failed to unset anchors"));
733 #pragma clang diagnostic pop
734 require_action(set_trust_settings_for_cert(system_root), errOut, fail("failed to set trust settings for system_root"));
735 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag date non-CT cert with enterprise root trust succeeded");
737 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
738 (long)CFErrorGetCode(error), errSecVerifyActionFailed);
740 fail("expected trust evaluation to fail and it did not.");
742 require_action(remove_trust_settings_for_cert(system_root), errOut, fail("failed to remove trust settings for system_root"));
744 // test app anchor for failing cert passes
745 anchors = @[ (__bridge id)system_server_after ];
746 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
747 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert app anchor");
749 // test trust settings for failing cert passes
750 #pragma clang diagnostic push
751 #pragma clang diagnostic ignored "-Wnonnull" /* required because of <rdar://32627101> */
752 require_noerr_action(SecTrustSetAnchorCertificates(trust, NULL), errOut, fail("failed to remove anchors"));
753 #pragma clang diagnostic pop
754 require_action(set_trust_settings_for_cert(system_server_after), errOut, fail("failed to set trust settings for system_server_after"));
755 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert enterprise anchor");
756 require_action(remove_trust_settings_for_cert(system_server_after), errOut, fail("failed to remove trust settings for system_server_after"));
758 // EAP, test system cert after date without CT passes
759 anchors = @[ (__bridge id)system_root ];
760 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
761 CFReleaseNull(policy);
762 policy = SecPolicyCreateEAP(true, NULL);
763 require_noerr_action(SecTrustSetPolicies(trust, policy), errOut, fail("failed to set EAP policy"));
764 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with EAP cert");
766 // Test pinning policy name
767 CFReleaseNull(policy);
768 policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
769 require_noerr_action(SecTrustSetPolicies(trust, policy), errOut, fail("failed to set SSL policy"));
770 require_noerr_action(SecTrustSetPinningPolicyName(trust, CFSTR("a-policy-name")), errOut, fail("failed to set policy name"));
771 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with pinning policy name");
772 CFReleaseNull(trust);
774 // test system cert after date with CT passes
775 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
776 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
777 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
778 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
779 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date CT cert failed");
780 CFReleaseNull(trust);
782 // test system cert before date without CT passes
783 require_noerr_action(SecTrustCreateWithCertificates(system_server_before, policy, &trust), errOut, fail("failed to create trust"));
784 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
785 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
786 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
787 ok(SecTrustEvaluateWithError(trust, NULL), "system pre-flag-date non-CT cert failed");
788 CFReleaseNull(trust);
790 // test enterprise (non-public) after date without CT passes
791 require_action(set_trust_settings_for_cert(user_root), errOut, fail("failed to set trust settings for user_root"));
792 require_noerr_action(SecTrustCreateWithCertificates(user_server_after, policy, &trust), errOut, fail("failed to create trust"));
793 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
794 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
795 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with enterprise anchor");
796 require_action(remove_trust_settings_for_cert(user_root), errOut, fail("failed to remove trust settings for user_root"));
798 // test app anchor (non-public) after date without CT passes
799 anchors = @[ (__bridge id)user_root ];
800 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
801 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with app anchor");
802 CFReleaseNull(trust);
803 CFReleaseNull(policy);
806 cleanup_keychain(keychain_certs);
807 CFReleaseNull(system_root);
808 CFReleaseNull(user_root);
809 CFReleaseNull(system_server_before);
810 CFReleaseNull(system_server_after);
811 CFReleaseNull(system_server_after_with_CT);
812 CFReleaseNull(user_server_after);
813 CFReleaseNull(trustedLogs);
814 CFReleaseNull(trust);
815 CFReleaseNull(policy);
818 static void test_apple_enforcement_exceptions(void) {
819 SecCertificateRef appleRoot = NULL, appleServerAuthCA = NULL, apple_server_after = NULL;
820 SecCertificateRef geoTrustRoot = NULL, appleISTCA8G1 = NULL, livability = NULL;
821 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
822 SecTrustRef trust = NULL;
823 SecPolicyRef policy = NULL;
824 NSArray *anchors = nil, *certs = nil;
825 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
827 require_action(appleRoot = SecCertificateCreateFromResource(@"enforcement_apple_root"),
828 errOut, fail("failed to create apple root"));
829 require_action(appleServerAuthCA = SecCertificateCreateFromResource(@"enforcement_apple_ca"),
830 errOut, fail("failed to create apple server auth CA"));
831 require_action(apple_server_after = SecCertificateCreateFromResource(@"enforcement_apple_server_after"),
832 errOut, fail("failed to create apple server cert issued after flag day"));
833 require_action(geoTrustRoot = SecCertificateCreateFromResource(@"GeoTrustPrimaryCAG2"),
834 errOut, fail("failed to create GeoTrust root"));
835 require_action(appleISTCA8G1 = SecCertificateCreateFromResource(@"AppleISTCA8G1"),
836 errOut, fail("failed to create apple IST CA"));
837 require_action(livability = SecCertificateCreateFromResource(@"livability"),
838 errOut, fail("failed to create livability cert"));
840 // test apple anchor after date without CT passes
841 policy = SecPolicyCreateSSL(true, CFSTR("bbasile-test.scv.apple.com"));
842 certs = @[ (__bridge id)apple_server_after, (__bridge id)appleServerAuthCA ];
843 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
844 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
845 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
846 ok(SecTrustEvaluateWithError(trust, NULL), "apple root post-flag-date non-CT cert failed");
847 CFReleaseNull(trust);
848 CFReleaseNull(policy);
850 // test apple ca after date without CT passes
851 policy = SecPolicyCreateSSL(true, CFSTR("livability.swe.apple.com"));
852 certs = @[ (__bridge id)livability, (__bridge id)appleISTCA8G1 ];
853 anchors = @[ (__bridge id)geoTrustRoot ];
854 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
855 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
856 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
857 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
858 ok(SecTrustEvaluateWithError(trust, NULL), "apple public post-flag-date non-CT cert failed");
861 CFReleaseNull(appleRoot);
862 CFReleaseNull(appleServerAuthCA);
863 CFReleaseNull(apple_server_after);
864 CFReleaseNull(geoTrustRoot);
865 CFReleaseNull(appleISTCA8G1);
866 CFReleaseNull(livability);
867 CFReleaseNull(trustedLogs);
868 CFReleaseNull(trust);
869 CFReleaseNull(policy);
872 static void test_google_enforcement_exception(void) {
873 SecCertificateRef globalSignRoot = NULL, googleIAG3 = NULL, google = NULL;
874 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
875 SecTrustRef trust = NULL;
876 SecPolicyRef policy = NULL;
877 NSArray *anchors = nil, *certs = nil;
878 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
880 require_action(globalSignRoot = SecCertificateCreateFromResource(@"GlobalSignRootCAR2"),
881 errOut, fail("failed to create GlobalSign root"));
882 require_action(googleIAG3 = SecCertificateCreateFromResource(@"GoogleIAG3"),
883 errOut, fail("failed to create Google IA CA"));
884 require_action(google = SecCertificateCreateFromResource(@"google"),
885 errOut, fail("failed to create google server cert"));
887 // test google ca after date without CT passes
888 policy = SecPolicyCreateSSL(true, CFSTR("www.google.com"));
889 certs = @[ (__bridge id)google, (__bridge id)googleIAG3];
890 anchors = @[ (__bridge id)globalSignRoot ];
891 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
892 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
893 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
894 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
895 ok(SecTrustEvaluateWithError(trust, NULL), "google public post-flag-date non-CT cert failed");
898 CFReleaseNull(globalSignRoot);
899 CFReleaseNull(googleIAG3);
900 CFReleaseNull(google);
901 CFReleaseNull(trustedLogs);
902 CFReleaseNull(trust);
903 CFReleaseNull(policy);
906 static void test_precerts_fail(void) {
907 SecCertificateRef precert = NULL, system_root = NULL;
908 SecTrustRef trust = NULL;
909 NSArray *anchors = nil;
910 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:561540800.0]; // October 18, 2018 at 12:33:20 AM PDT
911 CFErrorRef error = NULL;
913 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
914 errOut, fail("failed to create system root"));
915 require_action(precert = SecCertificateCreateFromResource(@"precert"),
916 errOut, fail("failed to create precert"));
918 anchors = @[(__bridge id)system_root];
919 require_noerr_action(SecTrustCreateWithCertificates(precert, NULL, &trust), errOut, fail("failed to create trust object"));
920 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchor certificate"));
921 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
923 is(SecTrustEvaluateWithError(trust, &error), false, "SECURITY: trust evaluation of precert succeeded");
925 is(CFErrorGetCode(error), errSecUnknownCriticalExtensionFlag, "got wrong error code for precert, got %ld, expected %d",
926 (long)CFErrorGetCode(error), errSecUnknownCriticalExtensionFlag);
928 fail("expected trust evaluation to fail and it did not.");
933 CFReleaseNull(system_root);
934 CFReleaseNull(precert);
935 CFReleaseNull(error);
938 #define evalTrustExpectingError(errCode, ...) \
939 is(SecTrustEvaluateWithError(trust, &error), false, __VA_ARGS__); \
941 is(CFErrorGetCode(error), errCode, "got wrong error code, got %ld, expected %d", \
942 (long)CFErrorGetCode(error), errCode); \
944 fail("expected trust evaluation to fail and it did not."); \
946 CFReleaseNull(error);
948 static void test_specific_domain_exceptions(void) {
949 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
950 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
951 SecTrustRef trust = NULL;
952 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
953 NSArray *anchors = nil;
954 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
955 CFErrorRef error = nil;
956 NSDictionary *exceptions = nil;
958 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
959 errOut, fail("failed to create system root"));
960 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
961 errOut, fail("failed to create system server cert issued after flag day"));
962 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
963 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
965 anchors = @[ (__bridge id)system_root ];
966 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
967 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
968 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
969 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
971 /* superdomain exception without CT fails */
972 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"test.apple.com"] };
973 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
974 evalTrustExpectingError(errSecVerifyActionFailed, "superdomain exception unexpectedly succeeded");
976 /* subdomain exceptions without CT fails */
977 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"one.ct.test.apple.com"] };
978 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
979 SecTrustSetNeedsEvaluation(trust);
980 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded")
982 /* no match without CT fails */
983 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"example.com"] };
984 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
985 SecTrustSetNeedsEvaluation(trust);
986 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
988 /* matching domain without CT succeeds */
989 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com"] };
990 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
991 SecTrustSetNeedsEvaluation(trust);
992 is(SecTrustEvaluateWithError(trust, &error), true, "exact match domain exception did not apply");
994 /* matching domain with CT succeeds */
995 CFReleaseNull(trust);
996 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
997 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
998 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
999 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1000 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
1002 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1005 CFReleaseNull(system_root);
1006 CFReleaseNull(system_server_after);
1007 CFReleaseNull(system_server_after_with_CT);
1008 CFReleaseNull(trust);
1009 CFReleaseNull(policy);
1010 CFReleaseNull(error);
1011 CFReleaseNull(trustedLogs);
1014 static void test_subdomain_exceptions(void) {
1015 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1016 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1017 SecTrustRef trust = NULL;
1018 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1019 NSArray *anchors = nil;
1020 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1021 CFErrorRef error = nil;
1022 NSDictionary *exceptions = nil;
1024 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1025 errOut, fail("failed to create system root"));
1026 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1027 errOut, fail("failed to create system server cert issued after flag day"));
1028 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1029 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1031 anchors = @[ (__bridge id)system_root ];
1032 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1033 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1034 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1035 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1037 /* superdomain exception without CT succeeds */
1038 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".test.apple.com"] };
1039 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1040 is(SecTrustEvaluateWithError(trust, &error), true, "superdomain exception did not apply");
1042 /* exact domain exception without CT succeeds */
1043 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".ct.test.apple.com"] };
1044 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1045 SecTrustSetNeedsEvaluation(trust);
1046 is(SecTrustEvaluateWithError(trust, &error), true, "exact domain exception did not apply");
1048 /* no match without CT fails */
1049 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".example.com"] };
1050 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1051 SecTrustSetNeedsEvaluation(trust);
1052 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
1054 /* subdomain without CT fails */
1055 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".one.ct.test.apple.com"] };
1056 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1057 SecTrustSetNeedsEvaluation(trust);
1058 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded");
1060 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1063 CFReleaseNull(system_root);
1064 CFReleaseNull(system_server_after);
1065 CFReleaseNull(system_server_after_with_CT);
1066 CFReleaseNull(trust);
1067 CFReleaseNull(policy);
1068 CFReleaseNull(error);
1069 CFReleaseNull(trustedLogs);
1072 static void test_mixed_domain_exceptions(void) {
1073 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1074 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1075 SecTrustRef trust = NULL;
1076 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1077 NSArray *anchors = nil;
1078 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1079 CFErrorRef error = nil;
1080 NSDictionary *exceptions = nil;
1082 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1083 errOut, fail("failed to create system root"));
1084 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1085 errOut, fail("failed to create system server cert issued after flag day"));
1086 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1087 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1089 anchors = @[ (__bridge id)system_root ];
1090 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1091 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1092 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1093 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1095 /* specific domain exception without CT succeeds */
1096 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".example.com" ] };
1097 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1098 is(SecTrustEvaluateWithError(trust, &error), true, "one of exact domain exception did not apply");
1100 /* super domain exception without CT succeeds */
1101 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".apple.com", @"example.com" ] };
1102 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1103 SecTrustSetNeedsEvaluation(trust);
1104 is(SecTrustEvaluateWithError(trust, &error), true, "one of superdomain exception did not apply");
1106 /* both super domain and specific domain exceptions without CT succeeds */
1107 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".apple.com" ] };
1108 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1109 SecTrustSetNeedsEvaluation(trust);
1110 is(SecTrustEvaluateWithError(trust, &error), true, "both domain exception did not apply");
1112 /* neither specific domain nor super domain exceptions without CT fails */
1113 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"apple.com", @".example.com" ] };
1114 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1115 SecTrustSetNeedsEvaluation(trust);
1116 evalTrustExpectingError(errSecVerifyActionFailed, "no match domain unexpectedly succeeded");
1118 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1121 CFReleaseNull(system_root);
1122 CFReleaseNull(system_server_after);
1123 CFReleaseNull(system_server_after_with_CT);
1124 CFReleaseNull(trust);
1125 CFReleaseNull(policy);
1126 CFReleaseNull(error);
1127 CFReleaseNull(trustedLogs);
1132 static void test_ct_domain_exceptions(void) {
1133 test_specific_domain_exceptions();
1134 test_subdomain_exceptions();
1135 test_mixed_domain_exceptions();
1138 static void test_ct_leaf_exceptions(void) {
1139 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1140 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1141 SecTrustRef trust = NULL;
1142 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1143 NSArray *anchors = nil;
1144 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1145 CFErrorRef error = nil;
1146 NSDictionary *leafException = nil, *exceptions = nil;
1147 NSData *leafHash = nil;
1149 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1150 errOut, fail("failed to create system root"));
1151 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1152 errOut, fail("failed to create system server cert issued after flag day"));
1153 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1154 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1156 anchors = @[ (__bridge id)system_root ];
1157 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1158 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1159 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1160 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1162 /* set exception on leaf cert without CT */
1163 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after));
1164 leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1165 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : leafHash,
1167 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ] };
1168 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1169 "failed to set exceptions: %@", error);
1170 is(SecTrustEvaluateWithError(trust, &error), true, "leaf public key exception did not apply");
1172 /* set exception on leaf cert with CT */
1173 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after_with_CT));
1174 leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1175 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : leafHash,
1177 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ] };
1178 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1179 "failed to set exceptions: %@", error);
1180 SecTrustSetNeedsEvaluation(trust);
1181 evalTrustExpectingError(errSecVerifyActionFailed, "leaf cert with no public key exceptions succeeded");
1183 /* matching public key with CT succeeds */
1184 CFReleaseNull(trust);
1185 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
1186 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1187 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1188 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1189 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
1191 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1194 CFReleaseNull(system_root);
1195 CFReleaseNull(system_server_after);
1196 CFReleaseNull(system_server_after_with_CT);
1197 CFReleaseNull(trustedLogs);
1198 CFReleaseNull(trust);
1199 CFReleaseNull(policy);
1200 CFReleaseNull(error);
1203 static void test_ct_unconstrained_ca_exceptions(void) {
1204 SecCertificateRef root = NULL, subca = NULL;
1205 SecCertificateRef server_matching = NULL, server_matching_with_CT = NULL, server_partial = NULL, server_no_match = NULL, server_no_org = NULL;
1206 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1207 SecTrustRef trust = NULL;
1208 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1209 NSArray *anchors = nil, *certs = nil;
1210 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1211 CFErrorRef error = nil;
1212 NSDictionary *caException = nil, *exceptions = nil;
1213 NSData *caHash = nil;
1215 require_action(root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1216 errOut, fail("failed to create system root"));
1217 require_action(subca = SecCertificateCreateFromResource(@"enforcement_system_unconstrained_subca"),
1218 errOut, fail("failed to create subca"));
1219 require_action(server_matching = SecCertificateCreateFromResource(@"enforcement_system_server_matching_orgs"),
1220 errOut, fail("failed to create server cert with matching orgs"));
1221 require_action(server_matching_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_matching_orgs_scts"),
1222 errOut, fail("failed to create server cert with matching orgs and scts"));
1223 require_action(server_partial = SecCertificateCreateFromResource(@"enforcement_system_server_partial_orgs"),
1224 errOut, fail("failed to create server cert with partial orgs"));
1225 require_action(server_no_match = SecCertificateCreateFromResource(@"enforcement_system_server_nonmatching_orgs"),
1226 errOut, fail("failed to create server cert with non-matching orgs"));
1227 require_action(server_no_org = SecCertificateCreateFromResource(@"enforcement_system_server_no_orgs"),
1228 errOut, fail("failed to create server cert with no orgs"));
1230 anchors = @[ (__bridge id)root ];
1232 #define createTrust(certs) \
1233 CFReleaseNull(trust); \
1234 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
1235 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors")); \
1236 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
1237 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
1239 /* Set exception on the subCA */
1240 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(subca));
1241 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1242 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1244 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ caException ] };
1245 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1246 "failed to set exceptions: %@", error);
1248 /* Verify that non-CT cert with Orgs matching subCA passes */
1249 certs = @[ (__bridge id)server_matching, (__bridge id)subca];
1251 is(SecTrustEvaluateWithError(trust, &error), true, "matching org subca exception did not apply: %@", error);
1253 /* Verify that CT cert with Orgs matching subCA passes */
1254 certs = @[ (__bridge id)server_matching_with_CT, (__bridge id)subca];
1256 is(SecTrustEvaluateWithError(trust, &error), true, "CT matching org subca exception did not apply: %@", error);
1258 /* Verify that non-CT cert with partial Org match fails */
1259 certs = @[ (__bridge id)server_partial, (__bridge id)subca];
1261 evalTrustExpectingError(errSecVerifyActionFailed, "partial matching org leaf succeeded");
1263 /* Verify that a non-CT cert with non-matching Org fails */
1264 certs = @[ (__bridge id)server_no_match, (__bridge id)subca];
1266 evalTrustExpectingError(errSecVerifyActionFailed, "non-matching org leaf succeeded");
1268 /* Verify that a non-CT cert with no Org fails */
1269 certs = @[ (__bridge id)server_no_org, (__bridge id)subca];
1271 evalTrustExpectingError(errSecVerifyActionFailed, "no org leaf succeeded");
1273 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1278 CFReleaseNull(root);
1279 CFReleaseNull(subca);
1280 CFReleaseNull(server_matching);
1281 CFReleaseNull(server_matching_with_CT);
1282 CFReleaseNull(server_partial);
1283 CFReleaseNull(server_no_match);
1284 CFReleaseNull(server_no_org);
1285 CFReleaseNull(trustedLogs);
1286 CFReleaseNull(trust);
1287 CFReleaseNull(policy);
1288 CFReleaseNull(error);
1291 static void test_ct_constrained_ca_exceptions(void) {
1292 SecCertificateRef root = NULL, org_constrained_subca = NULL;
1293 SecCertificateRef constraint_pass_server = NULL, constraint_pass_server_ct = NULL, constraint_fail_server = NULL;
1294 SecCertificateRef dn_constrained_subca = NULL, dn_constrained_server = NULL, dn_constrained_server_mismatch = NULL;
1295 SecCertificateRef dns_constrained_subca = NULL, dns_constrained_server = NULL, dns_constrained_server_mismatch = NULL;
1296 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1297 SecTrustRef trust = NULL;
1298 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1299 NSArray *anchors = nil, *certs = nil;
1300 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1301 CFErrorRef error = nil;
1302 NSDictionary *caException = nil, *exceptions = nil;
1303 NSMutableArray *caExceptions = [NSMutableArray array];
1304 NSData *caHash = nil;
1306 require_action(root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1307 errOut, fail("failed to create system root"));
1308 require_action(org_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_subca"),
1309 errOut, fail("failed to create org-constrained subca"));
1310 require_action(constraint_pass_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_server"),
1311 errOut, fail("failed to create constrained non-CT leaf"));
1312 require_action(constraint_pass_server_ct = SecCertificateCreateFromResource(@"enforcement_system_constrained_server_scts"),
1313 errOut, fail("failed to create constrained CT leaf"));
1314 require_action(constraint_fail_server= SecCertificateCreateFromResource(@"enforcement_system_constrained_fail_server"),
1315 errOut, fail("failed to create constraint failure leaf"));
1316 require_action(dn_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_subca"),
1317 errOut, fail("failed to create dn-constrained subca"));
1318 require_action(dn_constrained_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_server"),
1319 errOut, fail("failed to create dn-constrained leaf"));
1320 require_action(dn_constrained_server_mismatch = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_server_mismatch"),
1321 errOut, fail("failed to create dn-constrained leaf with mismatched orgs"));
1322 require_action(dns_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_subca"),
1323 errOut, fail("failed to create dns-constrained subca"));
1324 require_action(dns_constrained_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_server"),
1325 errOut, fail("failed to create dns-constrained leaf"));
1326 require_action(dns_constrained_server_mismatch = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_server_mismatch"),
1327 errOut, fail("failed to create dns-constrained leaf with mismatched orgs"));
1329 anchors = @[ (__bridge id)root ];
1331 /* Set exception on the subCAs */
1332 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(org_constrained_subca));
1333 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1334 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1336 [caExceptions addObject:caException];
1338 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dn_constrained_subca));
1339 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1340 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1342 [caExceptions addObject:caException];
1344 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dns_constrained_subca));
1345 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1346 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1348 [caExceptions addObject:caException];
1349 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : caExceptions };
1350 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1351 "failed to set exceptions: %@", error);
1353 #define createTrust(certs) \
1354 CFReleaseNull(trust); \
1355 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
1356 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors")); \
1357 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
1358 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
1360 /* Verify org-constrained non-CT leaf passes */
1361 certs = @[ (__bridge id)constraint_pass_server, (__bridge id)org_constrained_subca ];
1363 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1365 /* Verify org-constrained CT leaf passes */
1366 certs = @[ (__bridge id)constraint_pass_server_ct, (__bridge id)org_constrained_subca ];
1368 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1370 /* Verify org-constrained non-CT leaf with wrong org fails */
1371 certs = @[ (__bridge id)constraint_fail_server, (__bridge id)org_constrained_subca ];
1373 evalTrustExpectingError(errSecInvalidName, "leaf failing name constraints succeeded");
1375 /* Verify dn-constrained (but not with org) non-CT leaf with matching orgs succeeds */
1376 certs = @[ (__bridge id)dn_constrained_server, (__bridge id)dn_constrained_subca ];
1378 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1380 /* Verify dn-constrained (but not with org) non-CT leaf without matching orgs fails */
1381 certs = @[ (__bridge id)dn_constrained_server_mismatch, (__bridge id)dn_constrained_subca ];
1383 evalTrustExpectingError(errSecVerifyActionFailed, "dn name constraints with no org succeeded");
1385 /* Verify dns-constrained (no DN constraints) non-CT leaf with matching orgs succeeds */
1386 certs = @[ (__bridge id)dns_constrained_server, (__bridge id)dns_constrained_subca ];
1388 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1390 /* Verify dns-constrained (no DN constraints) non-CT leaf without matching orgs fails*/
1391 certs = @[ (__bridge id)dns_constrained_server_mismatch, (__bridge id)dns_constrained_subca ];
1393 evalTrustExpectingError(errSecVerifyActionFailed, "dns name constraints with no DN constraint succeeded");
1395 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1400 CFReleaseNull(root);
1401 CFReleaseNull(org_constrained_subca);
1402 CFReleaseNull(constraint_pass_server);
1403 CFReleaseNull(constraint_pass_server_ct);
1404 CFReleaseNull(constraint_fail_server);
1405 CFReleaseNull(dn_constrained_subca);
1406 CFReleaseNull(dn_constrained_server);
1407 CFReleaseNull(dn_constrained_server_mismatch);
1408 CFReleaseNull(dns_constrained_subca);
1409 CFReleaseNull(dns_constrained_server);
1410 CFReleaseNull(dns_constrained_server_mismatch);
1411 CFReleaseNull(trustedLogs);
1412 CFReleaseNull(trust);
1413 CFReleaseNull(policy);
1414 CFReleaseNull(error);
1417 static void test_ct_key_exceptions(void) {
1418 test_ct_leaf_exceptions();
1419 test_ct_unconstrained_ca_exceptions();
1420 test_ct_constrained_ca_exceptions();
1423 static void test_ct_exceptions(void) {
1424 test_ct_domain_exceptions();
1425 test_ct_key_exceptions();
1428 int si_82_sectrust_ct(int argc, char *const *argv)
1433 test_sct_serialization();
1434 testSetCTExceptions();
1436 test_apple_enforcement_exceptions();
1437 test_google_enforcement_exception();
1438 test_precerts_fail();
1439 test_ct_exceptions();