]> git.saurik.com Git - apple/security.git/blob - OSX/shared_regressions/si-82-sectrust-ct.m
Security-58286.270.3.0.1.tar.gz
[apple/security.git] / OSX / shared_regressions / si-82-sectrust-ct.m
1 /*
2 * si-82-sectrust-ct.c
3 * Security
4 *
5 * Copyright (c) 2014 Apple Inc. All Rights Reserved.
6 *
7 */
8
9 #include <AssertMacros.h>
10 #include <CoreFoundation/CoreFoundation.h>
11 #include <Security/SecCertificatePriv.h>
12 #include <Security/SecTrustPriv.h>
13 #include <Security/SecPolicyPriv.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <utilities/SecCFWrappers.h>
17 #include <Security/SecTrustSettings.h>
18 #include <Security/SecTrustSettingsPriv.h>
19 #include <Security/SecFramework.h>
20
21 #if TARGET_OS_IPHONE
22 #include <Security/SecTrustStore.h>
23 #else
24 #include <Security/SecKeychain.h>
25 #endif
26
27 #include "shared_regressions.h"
28 #include "si-82-sectrust-ct.h"
29
30 //define this if you want to print clock time of SecTrustEvaluate call.
31 //define PRINT_SECTRUST_EVALUATE_TIME
32
33 static bool isCFTrue(CFTypeRef cf)
34 {
35 return (cf == kCFBooleanTrue);
36 }
37
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)
42 {
43 CFArrayRef policies=NULL;
44 SecPolicyRef policy=NULL;
45 SecTrustRef trust=NULL;
46 SecTrustResultType trustResult;
47 CFDictionaryRef results=NULL;
48 CFArrayRef properties=NULL;
49
50
51
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");
55
56 assert(trust); // silence analyzer
57 if(anchors) {
58 ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors");
59 }
60
61 if(scts) {
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
66 }
67
68 if(trustedLogs) {
69 ok_status(SecTrustSetTrustedLogs(trust, trustedLogs), "set trusted logs");
70 }
71
72 if(ocspresponses) {
73 ok_status(SecTrustSetOCSPResponse(trust, ocspresponses), "set ocsp responses");
74 }
75
76 if (!date) { goto errOut; }
77 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
78 #ifdef PRINT_SECTRUST_EVALUATE_TIME
79 clock_t t0 = clock();
80 #endif
81 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
82 #ifdef PRINT_SECTRUST_EVALUATE_TIME
83 clock_t t1 = clock() - t0;
84 #endif
85 ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)",
86 (int)trustResult);
87
88 results = SecTrustCopyResult(trust);
89
90 CFTypeRef ct = CFDictionaryGetValue(results, kSecTrustCertificateTransparency);
91 CFTypeRef ev = CFDictionaryGetValue(results, kSecTrustExtendedValidation);
92 CFTypeRef ct_whitelist = CFDictionaryGetValue(results, kSecTrustCertificateTransparencyWhiteList);
93
94
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. */
99
100 #ifdef PRINT_SECTRUST_EVALUATE_TIME
101 printf("%s: %lu\n", test_name, t1);
102 #endif
103
104 properties = SecTrustCopyProperties(trust);
105
106 errOut:
107 CFReleaseSafe(policy);
108 CFReleaseSafe(policies);
109 CFReleaseSafe(trust);
110 CFReleaseSafe(results);
111 CFReleaseSafe(properties);
112 }
113
114 #import <Foundation/Foundation.h>
115
116 static
117 SecCertificateRef SecCertificateCreateFromResource(NSString *name)
118 {
119 NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".cer" subdirectory:@"si-82-sectrust-ct-data"];
120
121 NSData *certData = [NSData dataWithContentsOfURL:url];
122
123 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData);
124
125 return cert;
126 }
127
128 static
129 CFDataRef CFDataCreateFromResource(NSString *name)
130 {
131 NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".bin" subdirectory:@"si-82-sectrust-ct-data"];
132
133 NSData *binData = [[NSData alloc] initWithContentsOfURL:url];
134
135 return (__bridge_retained CFDataRef) binData;
136 }
137
138 static CFArrayRef CTTestsCopyTrustedLogs(void) {
139 CFArrayRef trustedLogs=NULL;
140 CFURLRef trustedLogsURL=NULL;
141
142 trustedLogsURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
143 CFSTR("CTlogs"),
144 CFSTR("plist"),
145 CFSTR("si-82-sectrust-ct-data"));
146 isnt(trustedLogsURL, NULL, "trustedLogsURL");
147 trustedLogs = (CFArrayRef) CFPropertyListReadFromFile(trustedLogsURL);
148 isnt(trustedLogs, NULL, "trustedLogs");
149
150 CFReleaseNull(trustedLogsURL);
151 return trustedLogs;
152 }
153
154 static void tests()
155 {
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 pilot_cert_3055998=NULL, pilot_cert_3055998_issuer=NULL;
160 SecCertificateRef whitelist_00008013=NULL, whitelist_5555bc4f=NULL, whitelist_aaaae152=NULL, whitelist_fff9b5f6=NULL;
161 SecCertificateRef whitelist_00008013_issuer=NULL, whitelist_5555bc4f_issuer=NULL, whitelist_fff9b5f6_issuer=NULL;
162 SecCertificateRef cfCert = NULL;
163 CFMutableArrayRef certs=NULL;
164 CFMutableArrayRef scts=NULL;
165 CFMutableArrayRef anchors=NULL;
166 CFDataRef valid_ocsp=NULL;
167 CFDataRef invalid_ocsp=NULL;
168 CFDataRef bad_hash_ocsp=NULL;
169
170 CFArrayRef trustedLogs= CTTestsCopyTrustedLogs();
171
172 isnt(certCA_alpha = SecCertificateCreateFromResource(@"CA_alpha"), NULL, "create ca-alpha cert");
173 isnt(certCA_beta = SecCertificateCreateFromResource(@"CA_beta"), NULL, "create ca-beta cert");
174 isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array");
175 CFArrayAppendValue(anchors, certCA_alpha);
176 CFArrayAppendValue(anchors, certCA_beta);
177 isnt(certA = SecCertificateCreateFromResource(@"serverA"), NULL, "create certA");
178 isnt(certD = SecCertificateCreateFromResource(@"serverD"), NULL, "create certD");
179 isnt(certF = SecCertificateCreateFromResource(@"serverF"), NULL, "create certF");
180 isnt(proofD = CFDataCreateFromResource(@"serverD_proof"), NULL, "creat proofD");
181 isnt(proofA_1 = CFDataCreateFromResource(@"serverA_proof_Alfa_3"), NULL, "creat proofA_1");
182 isnt(proofA_2 = CFDataCreateFromResource(@"serverA_proof_Bravo_3"), NULL, "creat proofA_2");
183 isnt(www_digicert_com_2015_cert = SecCertificateCreateFromResource(@"www_digicert_com_2015"), NULL, "create www.digicert.com 2015 cert");
184 isnt(www_digicert_com_2016_cert = SecCertificateCreateFromResource(@"www_digicert_com_2016"), NULL, "create www.digicert.com 2016 cert");
185 isnt(digicert_sha2_ev_server_ca = SecCertificateCreateFromResource(@"digicert_sha2_ev_server_ca"), NULL, "create digicert.com subCA cert");
186 isnt(valid_ocsp = CFDataCreateFromResource(@"valid_ocsp_response"), NULL, "create valid_ocsp");
187 isnt(invalid_ocsp = CFDataCreateFromResource(@"invalid_ocsp_response"), NULL, "create invalid_ocsp");
188 isnt(bad_hash_ocsp = CFDataCreateFromResource(@"bad_hash_ocsp_response"), NULL, "create bad_hash_ocsp");
189 isnt(pilot_cert_3055998 = SecCertificateCreateFromResource(@"pilot_3055998"), NULL, "create pilot_cert_3055998 cert");
190 isnt(pilot_cert_3055998_issuer = SecCertificateCreateFromResource(@"pilot_3055998_issuer"), NULL, "create pilot_cert_3055998 issuer cert");
191
192 isnt(whitelist_00008013 = SecCertificateCreateFromResource(@"whitelist_00008013"), NULL, "create whitelist_00008013 cert");
193 isnt(whitelist_5555bc4f = SecCertificateCreateFromResource(@"whitelist_5555bc4f"), NULL, "create whitelist_5555bc4f cert");
194 isnt(whitelist_aaaae152 = SecCertificateCreateFromResource(@"whitelist_aaaae152"), NULL, "create whitelist_aaaae152 cert");
195 isnt(whitelist_fff9b5f6 = SecCertificateCreateFromResource(@"whitelist_fff9b5f6"), NULL, "create whitelist_fff9b5f6 cert");
196 isnt(whitelist_00008013_issuer = SecCertificateCreateFromResource(@"whitelist_00008013_issuer"), NULL, "create whitelist_00008013_issuer cert");
197 isnt(whitelist_5555bc4f_issuer = SecCertificateCreateFromResource(@"whitelist_5555bc4f_issuer"), NULL, "create whitelist_5555bc4f_issuer cert");
198 isnt(whitelist_fff9b5f6_issuer = SecCertificateCreateFromResource(@"whitelist_fff9b5f6_issuer"), NULL, "create whitelist_fff9b5f6_issuer cert");
199
200 CFCalendarRef cal = NULL;
201 CFAbsoluteTime at;
202 CFDateRef date_20150307 = NULL; // Date for older set of tests.
203 CFDateRef date_20160422 = NULL; // Date for newer set of tests.
204
205 isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar");
206 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2015, 3, 7), "create verify absolute time 20150307");
207 isnt(date_20150307 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20150307");
208 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2016, 4, 22), "create verify absolute time 20160422");
209 isnt(date_20160422 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20160422");
210
211
212 /* Case 1: coreos-ct-test embedded SCT - only 1 SCT - so not CT qualified */
213 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
214 CFArrayAppendValue(certs, certF);
215 test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, NULL, date_20150307,
216 false, false, false, "coreos-ct-test 1");
217 CFReleaseNull(certs);
218
219 /* Case 2: coreos-ct-test standalone SCT - only 1 SCT - so not CT qualified */
220 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
221 CFArrayAppendValue(certs, certD);
222 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
223 CFArrayAppendValue(scts, proofD);
224 test_ct_trust(certs, scts, NULL, anchors, trustedLogs, NULL, date_20150307,
225 false, false, false, "coreos-ct-test 2");
226 CFReleaseNull(certs);
227 CFReleaseNull(scts);
228
229 /* case 3: digicert : 2 embedded SCTs, but lifetime of cert is 24 month, so not CT qualified */
230 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
231 CFArrayAppendValue(certs, www_digicert_com_2015_cert);
232 CFArrayAppendValue(certs, digicert_sha2_ev_server_ca);
233 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.digicert.com"), date_20150307,
234 false, false, false, "digicert 2015");
235 CFReleaseNull(certs);
236
237 /* Case 4: coreos-ct-test standalone SCT - 2 SCTs - CT qualified */
238 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
239 CFArrayAppendValue(certs, certA);
240 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
241 CFArrayAppendValue(scts, proofA_1);
242 CFArrayAppendValue(scts, proofA_2);
243 test_ct_trust(certs, scts, NULL, anchors, trustedLogs, NULL, date_20150307,
244 true, false, false, "coreos-ct-test 3");
245 CFReleaseNull(certs);
246 CFReleaseNull(scts);
247
248 /* Case 5: Test with an invalid OCSP response */
249 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
250 CFArrayAppendValue(certs, certA);
251 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
252 CFArrayAppendValue(scts, proofA_1);
253 test_ct_trust(certs, scts, invalid_ocsp, anchors, trustedLogs, NULL, date_20150307,
254 false, false, false, "coreos-ct-test 4");
255 CFReleaseNull(certs);
256 CFReleaseNull(scts);
257
258 /* Case 6: Test with a valid OCSP response */
259 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
260 CFArrayAppendValue(certs, certA);
261 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
262 CFArrayAppendValue(scts, proofA_1);
263 test_ct_trust(certs, scts, valid_ocsp, anchors, trustedLogs, NULL, date_20150307,
264 false, false, false, "coreos-ct-test 5");
265 CFReleaseNull(certs);
266 CFReleaseNull(scts);
267
268 /* Case 7: Test with a bad hash OCSP response */
269 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
270 CFArrayAppendValue(certs, certA);
271 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
272 CFArrayAppendValue(scts, proofA_1);
273 test_ct_trust(certs, scts, bad_hash_ocsp, anchors, trustedLogs, NULL, date_20150307,
274 false, false, false, "coreos-ct-test 6");
275 CFReleaseNull(certs);
276 CFReleaseNull(scts);
277
278 /* case 8: April 2016 www.digicert.com cert: 3 embedded SCTs, CT qualified, but OCSP doesn't respond */
279 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
280 CFArrayAppendValue(certs, www_digicert_com_2016_cert);
281 CFArrayAppendValue(certs, digicert_sha2_ev_server_ca);
282
283 /* WatchOS doesn't require OCSP for EV flag, so even though the OCSP responder no longer responds for this cert,
284 * it is EV on watchOS. */
285 #if TARGET_OS_WATCH
286 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.digicert.com"), date_20160422,
287 true, true, false, "digicert 2016");
288 #else
289 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.digicert.com"), date_20160422,
290 true, false, false, "digicert 2016");
291 #endif
292 CFReleaseNull(certs);
293
294
295
296 #define TEST_CASE(x) \
297 do { \
298 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array for " #x); \
299 isnt(cfCert = SecCertificateCreateFromResource(@#x), NULL, "create cfCert from " #x); \
300 CFArrayAppendValue(certs, cfCert); \
301 test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, NULL, date_20150307, true, false, false, #x); \
302 CFReleaseNull(certs); \
303 CFReleaseNull(cfCert); \
304 } while (0)
305
306
307 TEST_CASE(server_1601);
308 TEST_CASE(server_1603);
309 TEST_CASE(server_1604);
310 TEST_CASE(server_1701);
311 TEST_CASE(server_1704);
312 TEST_CASE(server_1705);
313 TEST_CASE(server_1801);
314 TEST_CASE(server_1804);
315 TEST_CASE(server_1805);
316 TEST_CASE(server_2001);
317
318
319 CFReleaseSafe(certCA_alpha);
320 CFReleaseSafe(certCA_beta);
321 CFReleaseSafe(anchors);
322 CFReleaseSafe(certA);
323 CFReleaseSafe(certD);
324 CFReleaseSafe(certF);
325 CFReleaseSafe(proofD);
326 CFReleaseSafe(proofA_1);
327 CFReleaseSafe(proofA_2);
328 CFReleaseSafe(www_digicert_com_2015_cert);
329 CFReleaseSafe(www_digicert_com_2016_cert);
330 CFReleaseSafe(digicert_sha2_ev_server_ca);
331 CFReleaseSafe(pilot_cert_3055998);
332 CFReleaseSafe(pilot_cert_3055998_issuer);
333 CFReleaseSafe(whitelist_00008013);
334 CFReleaseSafe(whitelist_5555bc4f);
335 CFReleaseSafe(whitelist_aaaae152);
336 CFReleaseSafe(whitelist_fff9b5f6);
337 CFReleaseSafe(whitelist_00008013_issuer);
338 CFReleaseSafe(whitelist_5555bc4f_issuer);
339 CFReleaseSafe(whitelist_fff9b5f6_issuer);
340 CFReleaseSafe(trustedLogs);
341 CFReleaseSafe(valid_ocsp);
342 CFReleaseSafe(invalid_ocsp);
343 CFReleaseSafe(bad_hash_ocsp);
344 CFReleaseSafe(cal);
345 CFReleaseSafe(date_20150307);
346 CFReleaseSafe(date_20160422);
347
348 }
349
350 static void test_sct_serialization(void) {
351 SecCertificateRef certA = NULL, certCA_alpha = NULL, certCA_beta = NULL;
352 CFArrayRef trustedLogs= CTTestsCopyTrustedLogs();
353 SecTrustRef trust = NULL, deserializedTrust = NULL;
354 SecPolicyRef policy = SecPolicyCreateSSL(true, NULL);
355 NSData *proofA_1 = NULL, *proofA_2 = NULL;
356 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:447450000.0]; // March 7, 2015 at 11:40:00 AM PST
357 CFErrorRef error = NULL;
358
359 isnt(certA = SecCertificateCreateFromResource(@"serverA"), NULL, "create certA");
360 isnt(certCA_alpha = SecCertificateCreateFromResource(@"CA_alpha"), NULL, "create ca-alpha cert");
361 isnt(certCA_beta = SecCertificateCreateFromResource(@"CA_beta"), NULL, "create ca-beta cert");
362
363 NSArray *anchors = @[ (__bridge id)certCA_alpha, (__bridge id)certCA_beta ];
364
365 isnt(proofA_1 = CFBridgingRelease(CFDataCreateFromResource(@"serverA_proof_Alfa_3")), NULL, "creat proofA_1");
366 isnt(proofA_2 = CFBridgingRelease(CFDataCreateFromResource(@"serverA_proof_Bravo_3")), NULL, "creat proofA_2");
367 NSArray *scts = @[ proofA_1, proofA_2 ];
368
369 /* Make a SecTrustRef and then serialize it */
370 ok_status(SecTrustCreateWithCertificates(certA, policy, &trust), "failed to create trust object");
371 ok_status(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), "failed to set anchors");
372 ok_status(SecTrustSetTrustedLogs(trust, trustedLogs), "failed to set trusted logs");
373 ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "failed to set verify date");
374
375 #pragma clang diagnostic push
376 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
377 ok_status(SecTrustSetSignedCertificateTimestamps(trust, (__bridge CFArrayRef)scts), "failed to set SCTS");
378 #pragma clang diagnostic pop
379
380 NSData *serializedTrust = CFBridgingRelease(SecTrustSerialize(trust, &error));
381 isnt(serializedTrust, NULL, "failed to serialize trust: %@", error);
382
383 /* Evaluate it to make sure it's CT */
384 ok(SecTrustEvaluateWithError(trust, &error), "failed to evaluate trust: %@", error);
385 NSDictionary *results = CFBridgingRelease(SecTrustCopyResult(trust));
386 isnt(results[(__bridge NSString*)kSecTrustCertificateTransparency], NULL, "failed get CT result");
387 ok([results[(__bridge NSString*)kSecTrustCertificateTransparency] boolValue], "CT failed");
388
389 /* Make a new trust object by deserializing the previous trust object */
390 ok(deserializedTrust = SecTrustDeserialize((__bridge CFDataRef)serializedTrust, &error), "failed to deserialize trust: %@", error);
391
392 /* Evaluate the new one to make sure it's CT (because the SCTs were serialized) */
393 ok(SecTrustEvaluateWithError(deserializedTrust, &error), "failed to evaluate trust: %@", error);
394 results = CFBridgingRelease(SecTrustCopyResult(deserializedTrust));
395 isnt(results[(__bridge NSString*)kSecTrustCertificateTransparency], NULL, "failed get CT result");
396 ok([results[(__bridge NSString*)kSecTrustCertificateTransparency] boolValue], "CT failed");
397
398 CFReleaseNull(certA);
399 CFReleaseNull(certCA_alpha);
400 CFReleaseNull(certCA_beta);
401 CFReleaseNull(trustedLogs);
402 CFReleaseNull(policy);
403 CFReleaseNull(trust);
404 CFReleaseNull(deserializedTrust);
405 CFReleaseNull(error);
406 }
407
408 static void testSetCTExceptions(void) {
409 CFErrorRef error = NULL;
410 const CFStringRef SecurityTestsAppID = CFSTR("com.apple.security.regressions");
411 const CFStringRef AnotherAppID = CFSTR("com.apple.security.not-this-one");
412 CFDictionaryRef copiedExceptions = NULL;
413
414 /* Verify no exceptions set */
415 is(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, NULL), NULL, "no exceptions set");
416 if (copiedExceptions) {
417 /* If we're starting out with exceptions set, a lot of the following will also fail, so just skip them */
418 CFReleaseNull(copiedExceptions);
419 return;
420 }
421
422 /* Set exceptions with specified AppID */
423 NSDictionary *exceptions1 = @{
424 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@"test.apple.com", @".test.apple.com"],
425 };
426 ok(SecTrustStoreSetCTExceptions(SecurityTestsAppID, (__bridge CFDictionaryRef)exceptions1, &error),
427 "failed to set exceptions for SecurityTests: %@", error);
428
429 /* Copy all exceptions (with only one set) */
430 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, &error),
431 "failed to copy all exceptions: %@", error);
432 ok([exceptions1 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
433 "got the wrong exceptions back");
434 CFReleaseNull(copiedExceptions);
435
436 /* Copy this app's exceptions */
437 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(SecurityTestsAppID, &error),
438 "failed to copy SecurityTests' exceptions: %@", error);
439 ok([exceptions1 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
440 "got the wrong exceptions back");
441 CFReleaseNull(copiedExceptions);
442
443 /* Copy a different app's exceptions */
444 is(copiedExceptions = SecTrustStoreCopyCTExceptions(AnotherAppID, &error), NULL,
445 "failed to copy different app's exceptions: %@", error);
446 CFReleaseNull(copiedExceptions);
447
448 /* Set different exceptions with implied AppID */
449 CFDataRef leafHash = SecSHA256DigestCreate(NULL, _system_after_leafSPKI, sizeof(_system_after_leafSPKI));
450 NSDictionary *leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
451 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)leafHash,
452 };
453
454 NSDictionary *exceptions2 = @{
455 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@".test.apple.com"],
456 (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ]
457 };
458 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions2, &error),
459 "failed to set exceptions for this app: %@", error);
460
461 /* Ensure exceptions are replaced for SecurityTests */
462 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(SecurityTestsAppID, &error),
463 "failed to copy SecurityTests' exceptions: %@", error);
464 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
465 "got the wrong exceptions back");
466 CFReleaseNull(copiedExceptions);
467
468 /* Set exceptions with a different AppID */
469 CFDataRef rootHash = SecSHA256DigestCreate(NULL, _system_rootSPKI, sizeof(_system_rootSPKI));
470 NSDictionary *rootExceptions = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
471 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)rootHash,
472 };
473 NSDictionary *exceptions3 = @{
474 (__bridge NSString*)kSecCTExceptionsCAsKey : @[ rootExceptions ]
475 };
476 ok(SecTrustStoreSetCTExceptions(AnotherAppID, (__bridge CFDictionaryRef)exceptions3, &error),
477 "failed to set exceptions for different app: %@", error);
478
479 /* Copy only one of the app's exceptions */
480 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(SecurityTestsAppID, &error),
481 "failed to copy SecurityTests' exceptions: %@", error);
482 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
483 "got the wrong exceptions back");
484 CFReleaseNull(copiedExceptions);
485
486 /* Set empty exceptions */
487 NSDictionary *empty = @{};
488 ok(SecTrustStoreSetCTExceptions(SecurityTestsAppID, (__bridge CFDictionaryRef)empty, &error),
489 "failed to set empty exceptions");
490
491 /* Copy exceptiosn to ensure no change */
492 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(SecurityTestsAppID, &error),
493 "failed to copy SecurityTests' exceptions: %@", error);
494 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
495 "got the wrong exceptions back");
496 CFReleaseNull(copiedExceptions);
497
498 /* Copy all exceptions */
499 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, &error),
500 "failed to copy all exceptions: %@", error);
501 is(CFDictionaryGetCount(copiedExceptions), 2, "Got the wrong number of all exceptions");
502 NSDictionary *nsCopiedExceptions = CFBridgingRelease(copiedExceptions);
503 NSArray *domainExceptions = nsCopiedExceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey];
504 NSArray *caExceptions = nsCopiedExceptions[(__bridge NSString*)kSecCTExceptionsCAsKey];
505 ok(domainExceptions && caExceptions, "Got both domain and CA exceptions");
506 ok([domainExceptions count] == 1, "Got 1 domain exception");
507 ok([caExceptions count] == 2, "Got 2 CA exceptions");
508 ok([domainExceptions[0] isEqualToString:@".test.apple.com"], "domain exception is .test.apple.com");
509 ok([caExceptions containsObject:leafException] && [caExceptions containsObject:rootExceptions], "got expected leaf and root CA exceptions");
510
511 /* Reset other app's exceptions */
512 ok(SecTrustStoreSetCTExceptions(AnotherAppID, NULL, &error),
513 "failed to reset exceptions for different app: %@", error);
514 ok(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, &error),
515 "failed to copy all exceptions: %@", error);
516 ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions],
517 "got the wrong exceptions back");
518 CFReleaseNull(copiedExceptions);
519
520 #define check_errSecParam \
521 if (error) { \
522 is(CFErrorGetCode(error), errSecParam, "bad input produced unxpected error code: %ld", (long)CFErrorGetCode(error)); \
523 } else { \
524 fail("expected failure to set NULL exceptions"); \
525 }
526
527 /* Set exceptions with bad inputs */
528 NSDictionary *badExceptions = @{
529 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@"test.apple.com", @".test.apple.com"],
530 @"not a key": @"not a value",
531 };
532 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
533 "set exceptions with unknown key");
534 check_errSecParam
535
536 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey:@"test.apple.com" };
537 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
538 "set exceptions with bad value");
539 check_errSecParam
540
541 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey: @[ @{} ] };
542 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
543 "set exceptions with bad array value");
544 check_errSecParam
545
546 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @"test.apple.com" ] };
547 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
548 "set exceptions with bad array value");
549 check_errSecParam
550
551 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
552 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
553 @"not-a-key" : (__bridge NSData*)rootHash,
554 }] };
555 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
556 "set exceptions with bad CA dictionary value");
557 check_errSecParam
558
559 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
560 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
561 }] };
562 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
563 "set exceptions with bad CA dictionary value");
564 check_errSecParam
565
566 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
567 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
568 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)rootHash,
569 @"not-a-key":@"not-a-value"
570 }] };
571 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
572 "set exceptions with bad CA dictionary value");
573 check_errSecParam
574
575 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey: @[ @".com" ] };
576 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
577 "set exceptions with TLD value");
578 check_errSecParam
579 #undef check_errSecParam
580
581 /* Remove exceptions using empty arrays */
582 NSDictionary *emptyArrays = @{
583 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[],
584 (__bridge NSString*)kSecCTExceptionsCAsKey : @[]
585 };
586 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)emptyArrays, &error),
587 "failed to set empty array exceptions for this app: %@", error);
588 is(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, NULL), NULL, "no exceptions set");
589
590 CFReleaseNull(leafHash);
591 CFReleaseNull(rootHash);
592 }
593
594 static void setup_for_user_trust(NSArray *in_certs, NSArray **deleteMeCertificates) {
595 #if TARGET_OS_OSX
596 /* Since we're putting trust settings in the admin domain,
597 * we need to add the certs to the system keychain. */
598 SecKeychainRef kcRef = NULL;
599 CFArrayRef certRef = NULL;
600 NSDictionary *attrs = nil;
601 NSMutableArray *persistenRefs = nil;
602
603 SecKeychainOpen("/Library/Keychains/System.keychain", &kcRef);
604 if (!kcRef) {
605 return;
606 }
607
608 persistenRefs = [[NSMutableArray alloc] init];
609
610 for (id cert in in_certs) {
611 attrs = @{(__bridge NSString*)kSecValueRef: cert,
612 (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
613 (__bridge NSString*)kSecReturnPersistentRef: @YES};
614 if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
615 [persistenRefs addObject:(__bridge NSArray *)certRef];
616 CFReleaseNull(certRef);
617 }
618
619 CFReleaseNull(kcRef);
620 *deleteMeCertificates = persistenRefs;
621 #endif
622 }
623
624 static void cleanup_keychain(NSArray *deleteMeCertificates) {
625 #if TARGET_OS_OSX
626 if (!deleteMeCertificates) {
627 return;
628 }
629
630 [deleteMeCertificates enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
631 SecItemDelete((CFDictionaryRef)@{ (__bridge NSString*)kSecValuePersistentRef: [obj objectAtIndex:0]});
632 }];
633 #endif
634 }
635
636 static bool set_trust_settings_for_cert(SecCertificateRef cert) {
637 bool ok = false;
638 NSDictionary *settings = nil;
639 if (!SecCertificateIsSelfSignedCA(cert)) {
640 settings = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
641 }
642 #if TARGET_OS_IPHONE
643 require_noerr_string(SecTrustStoreSetTrustSettings(SecTrustStoreForDomain(kSecTrustStoreDomainUser), cert,
644 (__bridge CFDictionaryRef)settings),
645 errOut, "failed to set trust settings");
646 #else
647 require_noerr_string(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin,
648 (__bridge CFDictionaryRef)settings),
649 errOut, "failed to set trust settings");
650 usleep(20000);
651 #endif
652 ok = true;
653 errOut:
654 return ok;
655 }
656
657 static bool remove_trust_settings_for_cert(SecCertificateRef cert) {
658 bool ok = false;
659 #if TARGET_OS_IPHONE
660 require_noerr_string(SecTrustStoreRemoveCertificate(SecTrustStoreForDomain(kSecTrustStoreDomainUser), cert),
661 errOut, "failed to remove trust settings");
662 #else
663 require_noerr_string(SecTrustSettingsRemoveTrustSettings(cert, kSecTrustSettingsDomainAdmin),
664 errOut, "failed to remove trust settings");
665 #endif
666 ok = true;
667 errOut:
668 return ok;
669 }
670
671 static void test_enforcement(void) {
672 SecCertificateRef system_root = NULL, user_root = NULL;
673 SecCertificateRef system_server_before = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
674 SecCertificateRef user_server_after = NULL;
675 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
676 SecTrustRef trust = NULL;
677 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
678 NSArray *anchors = nil, *keychain_certs = nil;
679 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
680 NSDate *expiredDate = [NSDate dateWithTimeIntervalSinceReferenceDate:570000000.0]; // January 24, 2019 at 12:20:00 AM EST
681 CFErrorRef error = nil;
682 CFDataRef exceptions = nil;
683
684 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
685 errOut, fail("failed to create system root"));
686 require_action(user_root = SecCertificateCreateFromResource(@"enforcement_user_root"),
687 errOut, fail("failed to create user root"));
688 require_action(system_server_before = SecCertificateCreateFromResource(@"enforcement_system_server_before"),
689 errOut, fail("failed to create system server cert issued before flag day"));
690 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
691 errOut, fail("failed to create system server cert issued after flag day"));
692 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
693 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
694 require_action(user_server_after = SecCertificateCreateFromResource(@"enforcement_user_server_after"),
695 errOut, fail("failed to create user server cert issued after flag day"));
696
697 /* set up the user and system roots to be used with trust settings */
698 setup_for_user_trust(@[(__bridge id)system_root, (__bridge id)user_root, (__bridge id)system_server_after],
699 &keychain_certs);
700 anchors = @[ (__bridge id)system_root ];
701 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
702 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
703 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
704
705 #if 0 // Disable this test until we can mock MobileAsset and force asset to be out-of-date
706 // Out-of-date asset, test system cert after date without CT passes
707 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with out-of-date asset");
708 #endif
709
710 // test system cert after date without CT fails
711 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
712 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag-date non-CT cert with in-date asset succeeded");
713 if (error) {
714 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
715 (long)CFErrorGetCode(error), errSecVerifyActionFailed);
716 } else {
717 fail("expected trust evaluation to fail and it did not.");
718 }
719
720 // test expired system cert after date without CT passes with only expiration error
721 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)expiredDate), errOut, fail("failed to set verify date"));
722 ok(SecTrustIsExpiredOnly(trust), "expired system post-flag-date non-CT cert had non-expiration errors");
723 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
724
725 // test exceptions for failing cert passes
726 exceptions = SecTrustCopyExceptions(trust);
727 ok(SecTrustSetExceptions(trust, exceptions), "failed to set exceptions for failing non-CT cert");
728 CFReleaseNull(exceptions);
729 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with exceptions set");
730 SecTrustSetExceptions(trust, NULL);
731
732 // test system cert + enterprise anchor after date without CT fails
733 #pragma clang diagnostic push
734 #pragma clang diagnostic ignored "-Wnonnull" /* required because of <rdar://32627101> */
735 require_noerr_action(SecTrustSetAnchorCertificates(trust, NULL), errOut, fail("failed to unset anchors"));
736 #pragma clang diagnostic pop
737 require_action(set_trust_settings_for_cert(system_root), errOut, fail("failed to set trust settings for system_root"));
738 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag date non-CT cert with enterprise root trust succeeded");
739 if (error) {
740 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
741 (long)CFErrorGetCode(error), errSecVerifyActionFailed);
742 } else {
743 fail("expected trust evaluation to fail and it did not.");
744 }
745 require_action(remove_trust_settings_for_cert(system_root), errOut, fail("failed to remove trust settings for system_root"));
746
747 // test app anchor for failing cert passes
748 anchors = @[ (__bridge id)system_server_after ];
749 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
750 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert app anchor");
751
752 // test trust settings for failing cert passes
753 #pragma clang diagnostic push
754 #pragma clang diagnostic ignored "-Wnonnull" /* required because of <rdar://32627101> */
755 require_noerr_action(SecTrustSetAnchorCertificates(trust, NULL), errOut, fail("failed to remove anchors"));
756 #pragma clang diagnostic pop
757 require_action(set_trust_settings_for_cert(system_server_after), errOut, fail("failed to set trust settings for system_server_after"));
758 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert enterprise anchor");
759 require_action(remove_trust_settings_for_cert(system_server_after), errOut, fail("failed to remove trust settings for system_server_after"));
760
761 // EAP, test system cert after date without CT passes
762 anchors = @[ (__bridge id)system_root ];
763 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
764 CFReleaseNull(policy);
765 policy = SecPolicyCreateEAP(true, NULL);
766 require_noerr_action(SecTrustSetPolicies(trust, policy), errOut, fail("failed to set EAP policy"));
767 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with EAP cert");
768
769 // Test pinning policy name
770 CFReleaseNull(policy);
771 policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
772 require_noerr_action(SecTrustSetPolicies(trust, policy), errOut, fail("failed to set SSL policy"));
773 require_noerr_action(SecTrustSetPinningPolicyName(trust, CFSTR("a-policy-name")), errOut, fail("failed to set policy name"));
774 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with pinning policy name");
775 CFReleaseNull(trust);
776
777 // test system cert after date with CT passes
778 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
779 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
780 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
781 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
782 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date CT cert failed");
783 CFReleaseNull(trust);
784
785 // test system cert before date without CT passes
786 require_noerr_action(SecTrustCreateWithCertificates(system_server_before, policy, &trust), errOut, fail("failed to create trust"));
787 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
788 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
789 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
790 ok(SecTrustEvaluateWithError(trust, NULL), "system pre-flag-date non-CT cert failed");
791 CFReleaseNull(trust);
792
793 // test enterprise (non-public) after date without CT passes
794 require_action(set_trust_settings_for_cert(user_root), errOut, fail("failed to set trust settings for user_root"));
795 require_noerr_action(SecTrustCreateWithCertificates(user_server_after, policy, &trust), errOut, fail("failed to create trust"));
796 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
797 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
798 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with enterprise anchor");
799 require_action(remove_trust_settings_for_cert(user_root), errOut, fail("failed to remove trust settings for user_root"));
800
801 // test app anchor (non-public) after date without CT passes
802 anchors = @[ (__bridge id)user_root ];
803 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
804 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with app anchor");
805 CFReleaseNull(trust);
806 CFReleaseNull(policy);
807
808 errOut:
809 cleanup_keychain(keychain_certs);
810 CFReleaseNull(system_root);
811 CFReleaseNull(user_root);
812 CFReleaseNull(system_server_before);
813 CFReleaseNull(system_server_after);
814 CFReleaseNull(system_server_after_with_CT);
815 CFReleaseNull(user_server_after);
816 CFReleaseNull(trustedLogs);
817 CFReleaseNull(trust);
818 CFReleaseNull(policy);
819 }
820
821 static void test_apple_enforcement_exceptions(void) {
822 SecCertificateRef appleRoot = NULL, appleServerAuthCA = NULL, apple_server_after = NULL;
823 SecCertificateRef geoTrustRoot = NULL, appleISTCA8G1 = NULL, deprecatedSSLServer = NULL;
824 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
825 SecTrustRef trust = NULL;
826 SecPolicyRef policy = NULL;
827 NSArray *anchors = nil, *certs = nil;
828 NSDate *date1 = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
829 NSDate *date2 = [NSDate dateWithTimeIntervalSinceReferenceDate:576000000.0]; // April 3, 2019 at 9:00:00 AM PDT
830
831 require_action(appleRoot = SecCertificateCreateFromResource(@"enforcement_apple_root"),
832 errOut, fail("failed to create apple root"));
833 require_action(appleServerAuthCA = SecCertificateCreateFromResource(@"enforcement_apple_ca"),
834 errOut, fail("failed to create apple server auth CA"));
835 require_action(apple_server_after = SecCertificateCreateFromResource(@"enforcement_apple_server_after"),
836 errOut, fail("failed to create apple server cert issued after flag day"));
837 require_action(geoTrustRoot = SecCertificateCreateFromResource(@"GeoTrustPrimaryCAG2"),
838 errOut, fail("failed to create GeoTrust root"));
839 require_action(appleISTCA8G1 = SecCertificateCreateFromResource(@"AppleISTCA8G1"),
840 errOut, fail("failed to create apple IST CA"));
841 require_action(deprecatedSSLServer = SecCertificateCreateFromResource(@"deprecatedSSLServer"),
842 errOut, fail("failed to create livability cert"));
843
844 // test apple anchor after date without CT passes
845 policy = SecPolicyCreateSSL(true, CFSTR("bbasile-test.scv.apple.com"));
846 certs = @[ (__bridge id)apple_server_after, (__bridge id)appleServerAuthCA ];
847 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
848 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date1), errOut, fail("failed to set verify date"));
849 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
850 ok(SecTrustEvaluateWithError(trust, NULL), "apple root post-flag-date non-CT cert failed");
851 CFReleaseNull(trust);
852 CFReleaseNull(policy);
853
854 // test apple ca after date without CT passes
855 policy = SecPolicyCreateSSL(true, CFSTR("bbasile-test.scv.apple.com"));
856 certs = @[ (__bridge id)deprecatedSSLServer, (__bridge id)appleISTCA8G1 ];
857 anchors = @[ (__bridge id)geoTrustRoot ];
858 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
859 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date2), errOut, fail("failed to set verify date"));
860 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
861 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
862 ok(SecTrustEvaluateWithError(trust, NULL), "apple public post-flag-date non-CT cert failed");
863
864 errOut:
865 CFReleaseNull(appleRoot);
866 CFReleaseNull(appleServerAuthCA);
867 CFReleaseNull(apple_server_after);
868 CFReleaseNull(geoTrustRoot);
869 CFReleaseNull(appleISTCA8G1);
870 CFReleaseNull(deprecatedSSLServer);
871 CFReleaseNull(trustedLogs);
872 CFReleaseNull(trust);
873 CFReleaseNull(policy);
874 }
875
876 static void test_google_enforcement_exception(void) {
877 SecCertificateRef globalSignRoot = NULL, googleIAG3 = NULL, google = NULL;
878 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
879 SecTrustRef trust = NULL;
880 SecPolicyRef policy = NULL;
881 NSArray *anchors = nil, *certs = nil;
882 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
883
884 require_action(globalSignRoot = SecCertificateCreateFromResource(@"GlobalSignRootCAR2"),
885 errOut, fail("failed to create GlobalSign root"));
886 require_action(googleIAG3 = SecCertificateCreateFromResource(@"GoogleIAG3"),
887 errOut, fail("failed to create Google IA CA"));
888 require_action(google = SecCertificateCreateFromResource(@"google"),
889 errOut, fail("failed to create google server cert"));
890
891 // test google ca after date without CT passes
892 policy = SecPolicyCreateSSL(true, CFSTR("www.google.com"));
893 certs = @[ (__bridge id)google, (__bridge id)googleIAG3];
894 anchors = @[ (__bridge id)globalSignRoot ];
895 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
896 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
897 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
898 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
899 ok(SecTrustEvaluateWithError(trust, NULL), "google public post-flag-date non-CT cert failed");
900
901 errOut:
902 CFReleaseNull(globalSignRoot);
903 CFReleaseNull(googleIAG3);
904 CFReleaseNull(google);
905 CFReleaseNull(trustedLogs);
906 CFReleaseNull(trust);
907 CFReleaseNull(policy);
908 }
909
910 static void test_precerts_fail(void) {
911 SecCertificateRef precert = NULL, system_root = NULL;
912 SecTrustRef trust = NULL;
913 NSArray *anchors = nil;
914 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:561540800.0]; // October 18, 2018 at 12:33:20 AM PDT
915 CFErrorRef error = NULL;
916
917 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
918 errOut, fail("failed to create system root"));
919 require_action(precert = SecCertificateCreateFromResource(@"precert"),
920 errOut, fail("failed to create precert"));
921
922 anchors = @[(__bridge id)system_root];
923 require_noerr_action(SecTrustCreateWithCertificates(precert, NULL, &trust), errOut, fail("failed to create trust object"));
924 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchor certificate"));
925 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
926
927 is(SecTrustEvaluateWithError(trust, &error), false, "SECURITY: trust evaluation of precert succeeded");
928 if (error) {
929 is(CFErrorGetCode(error), errSecUnknownCriticalExtensionFlag, "got wrong error code for precert, got %ld, expected %d",
930 (long)CFErrorGetCode(error), errSecUnknownCriticalExtensionFlag);
931 } else {
932 fail("expected trust evaluation to fail and it did not.");
933 }
934
935
936 errOut:
937 CFReleaseNull(system_root);
938 CFReleaseNull(precert);
939 CFReleaseNull(error);
940 }
941
942 #define evalTrustExpectingError(errCode, ...) \
943 is(SecTrustEvaluateWithError(trust, &error), false, __VA_ARGS__); \
944 if (error) { \
945 is(CFErrorGetCode(error), errCode, "got wrong error code, got %ld, expected %d", \
946 (long)CFErrorGetCode(error), errCode); \
947 } else { \
948 fail("expected trust evaluation to fail and it did not."); \
949 } \
950 CFReleaseNull(error);
951
952 static void test_specific_domain_exceptions(void) {
953 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
954 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
955 SecTrustRef trust = NULL;
956 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
957 NSArray *anchors = nil;
958 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
959 CFErrorRef error = nil;
960 NSDictionary *exceptions = nil;
961
962 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
963 errOut, fail("failed to create system root"));
964 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
965 errOut, fail("failed to create system server cert issued after flag day"));
966 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
967 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
968
969 anchors = @[ (__bridge id)system_root ];
970 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
971 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
972 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
973 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
974
975 /* superdomain exception without CT fails */
976 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"test.apple.com"] };
977 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
978 evalTrustExpectingError(errSecVerifyActionFailed, "superdomain exception unexpectedly succeeded");
979
980 /* subdomain exceptions without CT fails */
981 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"one.ct.test.apple.com"] };
982 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
983 SecTrustSetNeedsEvaluation(trust);
984 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded")
985
986 /* no match without CT fails */
987 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"example.com"] };
988 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
989 SecTrustSetNeedsEvaluation(trust);
990 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
991
992 /* matching domain without CT succeeds */
993 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com"] };
994 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
995 SecTrustSetNeedsEvaluation(trust);
996 is(SecTrustEvaluateWithError(trust, &error), true, "exact match domain exception did not apply");
997
998 /* matching domain with CT succeeds */
999 CFReleaseNull(trust);
1000 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
1001 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1002 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1003 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1004 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
1005
1006 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1007
1008 errOut:
1009 CFReleaseNull(system_root);
1010 CFReleaseNull(system_server_after);
1011 CFReleaseNull(system_server_after_with_CT);
1012 CFReleaseNull(trust);
1013 CFReleaseNull(policy);
1014 CFReleaseNull(error);
1015 CFReleaseNull(trustedLogs);
1016 }
1017
1018 static void test_subdomain_exceptions(void) {
1019 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1020 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1021 SecTrustRef trust = NULL;
1022 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1023 NSArray *anchors = nil;
1024 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1025 CFErrorRef error = nil;
1026 NSDictionary *exceptions = nil;
1027
1028 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1029 errOut, fail("failed to create system root"));
1030 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1031 errOut, fail("failed to create system server cert issued after flag day"));
1032 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1033 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1034
1035 anchors = @[ (__bridge id)system_root ];
1036 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1037 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1038 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1039 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1040
1041 /* superdomain exception without CT succeeds */
1042 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".test.apple.com"] };
1043 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1044 is(SecTrustEvaluateWithError(trust, &error), true, "superdomain exception did not apply");
1045
1046 /* exact domain exception without CT succeeds */
1047 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".ct.test.apple.com"] };
1048 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1049 SecTrustSetNeedsEvaluation(trust);
1050 is(SecTrustEvaluateWithError(trust, &error), true, "exact domain exception did not apply");
1051
1052 /* no match without CT fails */
1053 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".example.com"] };
1054 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1055 SecTrustSetNeedsEvaluation(trust);
1056 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
1057
1058 /* subdomain without CT fails */
1059 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".one.ct.test.apple.com"] };
1060 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1061 SecTrustSetNeedsEvaluation(trust);
1062 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded");
1063
1064 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1065
1066 errOut:
1067 CFReleaseNull(system_root);
1068 CFReleaseNull(system_server_after);
1069 CFReleaseNull(system_server_after_with_CT);
1070 CFReleaseNull(trust);
1071 CFReleaseNull(policy);
1072 CFReleaseNull(error);
1073 CFReleaseNull(trustedLogs);
1074 }
1075
1076 static void test_mixed_domain_exceptions(void) {
1077 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1078 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1079 SecTrustRef trust = NULL;
1080 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1081 NSArray *anchors = nil;
1082 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1083 CFErrorRef error = nil;
1084 NSDictionary *exceptions = nil;
1085
1086 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1087 errOut, fail("failed to create system root"));
1088 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1089 errOut, fail("failed to create system server cert issued after flag day"));
1090 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1091 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1092
1093 anchors = @[ (__bridge id)system_root ];
1094 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1095 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1096 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1097 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1098
1099 /* specific domain exception without CT succeeds */
1100 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".example.com" ] };
1101 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1102 is(SecTrustEvaluateWithError(trust, &error), true, "one of exact domain exception did not apply");
1103
1104 /* super domain exception without CT succeeds */
1105 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".apple.com", @"example.com" ] };
1106 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1107 SecTrustSetNeedsEvaluation(trust);
1108 is(SecTrustEvaluateWithError(trust, &error), true, "one of superdomain exception did not apply");
1109
1110 /* both super domain and specific domain exceptions without CT succeeds */
1111 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".apple.com" ] };
1112 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1113 SecTrustSetNeedsEvaluation(trust);
1114 is(SecTrustEvaluateWithError(trust, &error), true, "both domain exception did not apply");
1115
1116 /* neither specific domain nor super domain exceptions without CT fails */
1117 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"apple.com", @".example.com" ] };
1118 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1119 SecTrustSetNeedsEvaluation(trust);
1120 evalTrustExpectingError(errSecVerifyActionFailed, "no match domain unexpectedly succeeded");
1121
1122 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1123
1124 errOut:
1125 CFReleaseNull(system_root);
1126 CFReleaseNull(system_server_after);
1127 CFReleaseNull(system_server_after_with_CT);
1128 CFReleaseNull(trust);
1129 CFReleaseNull(policy);
1130 CFReleaseNull(error);
1131 CFReleaseNull(trustedLogs);
1132 }
1133
1134
1135
1136 static void test_ct_domain_exceptions(void) {
1137 test_specific_domain_exceptions();
1138 test_subdomain_exceptions();
1139 test_mixed_domain_exceptions();
1140 }
1141
1142 static void test_ct_leaf_exceptions(void) {
1143 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1144 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1145 SecTrustRef trust = NULL;
1146 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1147 NSArray *anchors = nil;
1148 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1149 CFErrorRef error = nil;
1150 NSDictionary *leafException = nil, *exceptions = nil;
1151 NSData *leafHash = nil;
1152
1153 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1154 errOut, fail("failed to create system root"));
1155 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1156 errOut, fail("failed to create system server cert issued after flag day"));
1157 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1158 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1159
1160 anchors = @[ (__bridge id)system_root ];
1161 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1162 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1163 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1164 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1165
1166 /* set exception on leaf cert without CT */
1167 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after));
1168 leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1169 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : leafHash,
1170 };
1171 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ] };
1172 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1173 "failed to set exceptions: %@", error);
1174 is(SecTrustEvaluateWithError(trust, &error), true, "leaf public key exception did not apply");
1175
1176 /* set exception on leaf cert with CT */
1177 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after_with_CT));
1178 leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1179 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : leafHash,
1180 };
1181 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ] };
1182 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1183 "failed to set exceptions: %@", error);
1184 SecTrustSetNeedsEvaluation(trust);
1185 evalTrustExpectingError(errSecVerifyActionFailed, "leaf cert with no public key exceptions succeeded");
1186
1187 /* matching public key with CT succeeds */
1188 CFReleaseNull(trust);
1189 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
1190 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1191 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1192 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1193 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
1194
1195 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1196
1197 errOut:
1198 CFReleaseNull(system_root);
1199 CFReleaseNull(system_server_after);
1200 CFReleaseNull(system_server_after_with_CT);
1201 CFReleaseNull(trustedLogs);
1202 CFReleaseNull(trust);
1203 CFReleaseNull(policy);
1204 CFReleaseNull(error);
1205 }
1206
1207 static void test_ct_unconstrained_ca_exceptions(void) {
1208 SecCertificateRef root = NULL, subca = NULL;
1209 SecCertificateRef server_matching = NULL, server_matching_with_CT = NULL, server_partial = NULL, server_no_match = NULL, server_no_org = NULL;
1210 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1211 SecTrustRef trust = NULL;
1212 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1213 NSArray *anchors = nil, *certs = nil;
1214 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1215 CFErrorRef error = nil;
1216 NSDictionary *caException = nil, *exceptions = nil;
1217 NSData *caHash = nil;
1218
1219 require_action(root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1220 errOut, fail("failed to create system root"));
1221 require_action(subca = SecCertificateCreateFromResource(@"enforcement_system_unconstrained_subca"),
1222 errOut, fail("failed to create subca"));
1223 require_action(server_matching = SecCertificateCreateFromResource(@"enforcement_system_server_matching_orgs"),
1224 errOut, fail("failed to create server cert with matching orgs"));
1225 require_action(server_matching_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_matching_orgs_scts"),
1226 errOut, fail("failed to create server cert with matching orgs and scts"));
1227 require_action(server_partial = SecCertificateCreateFromResource(@"enforcement_system_server_partial_orgs"),
1228 errOut, fail("failed to create server cert with partial orgs"));
1229 require_action(server_no_match = SecCertificateCreateFromResource(@"enforcement_system_server_nonmatching_orgs"),
1230 errOut, fail("failed to create server cert with non-matching orgs"));
1231 require_action(server_no_org = SecCertificateCreateFromResource(@"enforcement_system_server_no_orgs"),
1232 errOut, fail("failed to create server cert with no orgs"));
1233
1234 anchors = @[ (__bridge id)root ];
1235
1236 #define createTrust(certs) \
1237 CFReleaseNull(trust); \
1238 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
1239 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors")); \
1240 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
1241 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
1242
1243 /* Set exception on the subCA */
1244 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(subca));
1245 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1246 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1247 };
1248 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ caException ] };
1249 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1250 "failed to set exceptions: %@", error);
1251
1252 /* Verify that non-CT cert with Orgs matching subCA passes */
1253 certs = @[ (__bridge id)server_matching, (__bridge id)subca];
1254 createTrust(certs);
1255 is(SecTrustEvaluateWithError(trust, &error), true, "matching org subca exception did not apply: %@", error);
1256
1257 /* Verify that CT cert with Orgs matching subCA passes */
1258 certs = @[ (__bridge id)server_matching_with_CT, (__bridge id)subca];
1259 createTrust(certs);
1260 is(SecTrustEvaluateWithError(trust, &error), true, "CT matching org subca exception did not apply: %@", error);
1261
1262 /* Verify that non-CT cert with partial Org match fails */
1263 certs = @[ (__bridge id)server_partial, (__bridge id)subca];
1264 createTrust(certs);
1265 evalTrustExpectingError(errSecVerifyActionFailed, "partial matching org leaf succeeded");
1266
1267 /* Verify that a non-CT cert with non-matching Org fails */
1268 certs = @[ (__bridge id)server_no_match, (__bridge id)subca];
1269 createTrust(certs);
1270 evalTrustExpectingError(errSecVerifyActionFailed, "non-matching org leaf succeeded");
1271
1272 /* Verify that a non-CT cert with no Org fails */
1273 certs = @[ (__bridge id)server_no_org, (__bridge id)subca];
1274 createTrust(certs);
1275 evalTrustExpectingError(errSecVerifyActionFailed, "no org leaf succeeded");
1276
1277 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1278
1279 #undef createTrust
1280
1281 errOut:
1282 CFReleaseNull(root);
1283 CFReleaseNull(subca);
1284 CFReleaseNull(server_matching);
1285 CFReleaseNull(server_matching_with_CT);
1286 CFReleaseNull(server_partial);
1287 CFReleaseNull(server_no_match);
1288 CFReleaseNull(server_no_org);
1289 CFReleaseNull(trustedLogs);
1290 CFReleaseNull(trust);
1291 CFReleaseNull(policy);
1292 CFReleaseNull(error);
1293 }
1294
1295 static void test_ct_constrained_ca_exceptions(void) {
1296 SecCertificateRef root = NULL, org_constrained_subca = NULL;
1297 SecCertificateRef constraint_pass_server = NULL, constraint_pass_server_ct = NULL, constraint_fail_server = NULL;
1298 SecCertificateRef dn_constrained_subca = NULL, dn_constrained_server = NULL, dn_constrained_server_mismatch = NULL;
1299 SecCertificateRef dns_constrained_subca = NULL, dns_constrained_server = NULL, dns_constrained_server_mismatch = NULL;
1300 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1301 SecTrustRef trust = NULL;
1302 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1303 NSArray *anchors = nil, *certs = nil;
1304 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1305 CFErrorRef error = nil;
1306 NSDictionary *caException = nil, *exceptions = nil;
1307 NSMutableArray *caExceptions = [NSMutableArray array];
1308 NSData *caHash = nil;
1309
1310 require_action(root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1311 errOut, fail("failed to create system root"));
1312 require_action(org_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_subca"),
1313 errOut, fail("failed to create org-constrained subca"));
1314 require_action(constraint_pass_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_server"),
1315 errOut, fail("failed to create constrained non-CT leaf"));
1316 require_action(constraint_pass_server_ct = SecCertificateCreateFromResource(@"enforcement_system_constrained_server_scts"),
1317 errOut, fail("failed to create constrained CT leaf"));
1318 require_action(constraint_fail_server= SecCertificateCreateFromResource(@"enforcement_system_constrained_fail_server"),
1319 errOut, fail("failed to create constraint failure leaf"));
1320 require_action(dn_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_subca"),
1321 errOut, fail("failed to create dn-constrained subca"));
1322 require_action(dn_constrained_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_server"),
1323 errOut, fail("failed to create dn-constrained leaf"));
1324 require_action(dn_constrained_server_mismatch = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_server_mismatch"),
1325 errOut, fail("failed to create dn-constrained leaf with mismatched orgs"));
1326 require_action(dns_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_subca"),
1327 errOut, fail("failed to create dns-constrained subca"));
1328 require_action(dns_constrained_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_server"),
1329 errOut, fail("failed to create dns-constrained leaf"));
1330 require_action(dns_constrained_server_mismatch = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_server_mismatch"),
1331 errOut, fail("failed to create dns-constrained leaf with mismatched orgs"));
1332
1333 anchors = @[ (__bridge id)root ];
1334
1335 /* Set exception on the subCAs */
1336 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(org_constrained_subca));
1337 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1338 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1339 };
1340 [caExceptions addObject:caException];
1341
1342 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dn_constrained_subca));
1343 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1344 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1345 };
1346 [caExceptions addObject:caException];
1347
1348 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dns_constrained_subca));
1349 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1350 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1351 };
1352 [caExceptions addObject:caException];
1353 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : caExceptions };
1354 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1355 "failed to set exceptions: %@", error);
1356
1357 #define createTrust(certs) \
1358 CFReleaseNull(trust); \
1359 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
1360 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors")); \
1361 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
1362 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
1363
1364 /* Verify org-constrained non-CT leaf passes */
1365 certs = @[ (__bridge id)constraint_pass_server, (__bridge id)org_constrained_subca ];
1366 createTrust(certs);
1367 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1368
1369 /* Verify org-constrained CT leaf passes */
1370 certs = @[ (__bridge id)constraint_pass_server_ct, (__bridge id)org_constrained_subca ];
1371 createTrust(certs);
1372 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1373
1374 /* Verify org-constrained non-CT leaf with wrong org fails */
1375 certs = @[ (__bridge id)constraint_fail_server, (__bridge id)org_constrained_subca ];
1376 createTrust(certs);
1377 evalTrustExpectingError(errSecInvalidName, "leaf failing name constraints succeeded");
1378
1379 /* Verify dn-constrained (but not with org) non-CT leaf with matching orgs succeeds */
1380 certs = @[ (__bridge id)dn_constrained_server, (__bridge id)dn_constrained_subca ];
1381 createTrust(certs);
1382 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1383
1384 /* Verify dn-constrained (but not with org) non-CT leaf without matching orgs fails */
1385 certs = @[ (__bridge id)dn_constrained_server_mismatch, (__bridge id)dn_constrained_subca ];
1386 createTrust(certs);
1387 evalTrustExpectingError(errSecVerifyActionFailed, "dn name constraints with no org succeeded");
1388
1389 /* Verify dns-constrained (no DN constraints) non-CT leaf with matching orgs succeeds */
1390 certs = @[ (__bridge id)dns_constrained_server, (__bridge id)dns_constrained_subca ];
1391 createTrust(certs);
1392 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1393
1394 /* Verify dns-constrained (no DN constraints) non-CT leaf without matching orgs fails*/
1395 certs = @[ (__bridge id)dns_constrained_server_mismatch, (__bridge id)dns_constrained_subca ];
1396 createTrust(certs);
1397 evalTrustExpectingError(errSecVerifyActionFailed, "dns name constraints with no DN constraint succeeded");
1398
1399 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1400
1401 #undef createTrust
1402
1403 errOut:
1404 CFReleaseNull(root);
1405 CFReleaseNull(org_constrained_subca);
1406 CFReleaseNull(constraint_pass_server);
1407 CFReleaseNull(constraint_pass_server_ct);
1408 CFReleaseNull(constraint_fail_server);
1409 CFReleaseNull(dn_constrained_subca);
1410 CFReleaseNull(dn_constrained_server);
1411 CFReleaseNull(dn_constrained_server_mismatch);
1412 CFReleaseNull(dns_constrained_subca);
1413 CFReleaseNull(dns_constrained_server);
1414 CFReleaseNull(dns_constrained_server_mismatch);
1415 CFReleaseNull(trustedLogs);
1416 CFReleaseNull(trust);
1417 CFReleaseNull(policy);
1418 CFReleaseNull(error);
1419 }
1420
1421 static void test_ct_key_exceptions(void) {
1422 test_ct_leaf_exceptions();
1423 test_ct_unconstrained_ca_exceptions();
1424 test_ct_constrained_ca_exceptions();
1425 }
1426
1427 static void test_ct_exceptions(void) {
1428 test_ct_domain_exceptions();
1429 test_ct_key_exceptions();
1430 }
1431
1432 int si_82_sectrust_ct(int argc, char *const *argv)
1433 {
1434 plan_tests(431);
1435
1436 tests();
1437 test_sct_serialization();
1438 testSetCTExceptions();
1439 test_enforcement();
1440 test_apple_enforcement_exceptions();
1441 test_google_enforcement_exception();
1442 test_precerts_fail();
1443 test_ct_exceptions();
1444
1445 return 0;
1446 }