]> git.saurik.com Git - apple/security.git/blob - OSX/shared_regressions/si-82-sectrust-ct.m
Security-58286.230.21.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 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;
170
171 CFArrayRef trustedLogs= CTTestsCopyTrustedLogs();
172
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");
194
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");
202
203 CFCalendarRef cal = NULL;
204 CFAbsoluteTime at;
205 CFDateRef date_20150307 = NULL; // Date for older set of tests.
206 CFDateRef date_20160422 = NULL; // Date for newer set of tests.
207
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");
213
214
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);
221
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);
230 CFReleaseNull(scts);
231
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);
239
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);
249 CFReleaseNull(scts);
250
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);
259 CFReleaseNull(scts);
260
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);
269 CFReleaseNull(scts);
270
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);
279 CFReleaseNull(scts);
280
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);
288
289
290
291 #define TEST_CASE(x) \
292 do { \
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); \
299 } while (0)
300
301
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);
312
313
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);
341 CFReleaseSafe(cal);
342 CFReleaseSafe(date_20150307);
343 CFReleaseSafe(date_20160422);
344
345 }
346
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;
355
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");
359
360 NSArray *anchors = @[ (__bridge id)certCA_alpha, (__bridge id)certCA_beta ];
361
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 ];
365
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");
371
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
376
377 NSData *serializedTrust = CFBridgingRelease(SecTrustSerialize(trust, &error));
378 isnt(serializedTrust, NULL, "failed to serialize trust: %@", error);
379
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");
385
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);
388
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");
394
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);
403 }
404
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;
410
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);
416 return;
417 }
418
419 /* Set exceptions with specified AppID */
420 NSDictionary *exceptions1 = @{
421 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@"test.apple.com", @".test.apple.com"],
422 };
423 ok(SecTrustStoreSetCTExceptions(SecurityTestsAppID, (__bridge CFDictionaryRef)exceptions1, &error),
424 "failed to set exceptions for SecurityTests: %@", error);
425
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);
432
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);
439
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);
444
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,
449 };
450
451 NSDictionary *exceptions2 = @{
452 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[@".test.apple.com"],
453 (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ]
454 };
455 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions2, &error),
456 "failed to set exceptions for this app: %@", error);
457
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);
464
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,
469 };
470 NSDictionary *exceptions3 = @{
471 (__bridge NSString*)kSecCTExceptionsCAsKey : @[ rootExceptions ]
472 };
473 ok(SecTrustStoreSetCTExceptions(AnotherAppID, (__bridge CFDictionaryRef)exceptions3, &error),
474 "failed to set exceptions for different app: %@", error);
475
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);
482
483 /* Set empty exceptions */
484 NSDictionary *empty = @{};
485 ok(SecTrustStoreSetCTExceptions(SecurityTestsAppID, (__bridge CFDictionaryRef)empty, &error),
486 "failed to set empty exceptions");
487
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);
494
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");
507
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);
516
517 #define check_errSecParam \
518 if (error) { \
519 is(CFErrorGetCode(error), errSecParam, "bad input produced unxpected error code: %ld", (long)CFErrorGetCode(error)); \
520 } else { \
521 fail("expected failure to set NULL exceptions"); \
522 }
523
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",
528 };
529 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
530 "set exceptions with unknown key");
531 check_errSecParam
532
533 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey:@"test.apple.com" };
534 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
535 "set exceptions with bad value");
536 check_errSecParam
537
538 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey: @[ @{} ] };
539 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
540 "set exceptions with bad array value");
541 check_errSecParam
542
543 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @"test.apple.com" ] };
544 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
545 "set exceptions with bad array value");
546 check_errSecParam
547
548 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
549 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
550 @"not-a-key" : (__bridge NSData*)rootHash,
551 }] };
552 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
553 "set exceptions with bad CA dictionary value");
554 check_errSecParam
555
556 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
557 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
558 }] };
559 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
560 "set exceptions with bad CA dictionary value");
561 check_errSecParam
562
563 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[ @{
564 (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
565 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : (__bridge NSData*)rootHash,
566 @"not-a-key":@"not-a-value"
567 }] };
568 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
569 "set exceptions with bad CA dictionary value");
570 check_errSecParam
571
572 badExceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey: @[ @".com" ] };
573 is(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)badExceptions, &error), false,
574 "set exceptions with TLD value");
575 check_errSecParam
576 #undef check_errSecParam
577
578 /* Remove exceptions using empty arrays */
579 NSDictionary *emptyArrays = @{
580 (__bridge NSString*)kSecCTExceptionsDomainsKey: @[],
581 (__bridge NSString*)kSecCTExceptionsCAsKey : @[]
582 };
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");
586
587 CFReleaseNull(leafHash);
588 CFReleaseNull(rootHash);
589 }
590
591 static void setup_for_user_trust(NSArray *in_certs, NSArray **deleteMeCertificates) {
592 #if TARGET_OS_OSX
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;
599
600 SecKeychainOpen("/Library/Keychains/System.keychain", &kcRef);
601 if (!kcRef) {
602 return;
603 }
604
605 persistenRefs = [[NSMutableArray alloc] init];
606
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);
614 }
615
616 CFReleaseNull(kcRef);
617 *deleteMeCertificates = persistenRefs;
618 #endif
619 }
620
621 static void cleanup_keychain(NSArray *deleteMeCertificates) {
622 #if TARGET_OS_OSX
623 if (!deleteMeCertificates) {
624 return;
625 }
626
627 [deleteMeCertificates enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
628 SecItemDelete((CFDictionaryRef)@{ (__bridge NSString*)kSecValuePersistentRef: [obj objectAtIndex:0]});
629 }];
630 #endif
631 }
632
633 static bool set_trust_settings_for_cert(SecCertificateRef cert) {
634 bool ok = false;
635 NSDictionary *settings = nil;
636 if (!SecCertificateIsSelfSignedCA(cert)) {
637 settings = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
638 }
639 #if TARGET_OS_IPHONE
640 require_noerr_string(SecTrustStoreSetTrustSettings(SecTrustStoreForDomain(kSecTrustStoreDomainUser), cert,
641 (__bridge CFDictionaryRef)settings),
642 errOut, "failed to set trust settings");
643 #else
644 require_noerr_string(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin,
645 (__bridge CFDictionaryRef)settings),
646 errOut, "failed to set trust settings");
647 usleep(20000);
648 #endif
649 ok = true;
650 errOut:
651 return ok;
652 }
653
654 static bool remove_trust_settings_for_cert(SecCertificateRef cert) {
655 bool ok = false;
656 #if TARGET_OS_IPHONE
657 require_noerr_string(SecTrustStoreRemoveCertificate(SecTrustStoreForDomain(kSecTrustStoreDomainUser), cert),
658 errOut, "failed to remove trust settings");
659 #else
660 require_noerr_string(SecTrustSettingsRemoveTrustSettings(cert, kSecTrustSettingsDomainAdmin),
661 errOut, "failed to remove trust settings");
662 #endif
663 ok = true;
664 errOut:
665 return ok;
666 }
667
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 CFErrorRef error = nil;
678 CFDataRef exceptions = nil;
679
680 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
681 errOut, fail("failed to create system root"));
682 require_action(user_root = SecCertificateCreateFromResource(@"enforcement_user_root"),
683 errOut, fail("failed to create user root"));
684 require_action(system_server_before = SecCertificateCreateFromResource(@"enforcement_system_server_before"),
685 errOut, fail("failed to create system server cert issued before flag day"));
686 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
687 errOut, fail("failed to create system server cert issued after flag day"));
688 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
689 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
690 require_action(user_server_after = SecCertificateCreateFromResource(@"enforcement_user_server_after"),
691 errOut, fail("failed to create user server cert issued after flag day"));
692
693 /* set up the user and system roots to be used with trust settings */
694 setup_for_user_trust(@[(__bridge id)system_root, (__bridge id)user_root, (__bridge id)system_server_after],
695 &keychain_certs);
696 anchors = @[ (__bridge id)system_root ];
697 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
698 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
699 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
700
701 #if 0 // Disable this test until we can mock MobileAsset and force asset to be out-of-date
702 // Out-of-date asset, test system cert after date without CT passes
703 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with out-of-date asset");
704 #endif
705
706 // test system cert after date without CT fails
707 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
708 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag-date non-CT cert with in-date asset succeeded");
709 if (error) {
710 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
711 (long)CFErrorGetCode(error), errSecVerifyActionFailed);
712 } else {
713 fail("expected trust evaluation to fail and it did not.");
714 }
715
716 // test exceptions for failing cert passes
717 exceptions = SecTrustCopyExceptions(trust);
718 ok(SecTrustSetExceptions(trust, exceptions), "failed to set exceptions for failing non-CT cert");
719 CFReleaseNull(exceptions);
720 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with exceptions set");
721 SecTrustSetExceptions(trust, NULL);
722
723 // test system cert + enterprise anchor after date without CT fails
724 #pragma clang diagnostic push
725 #pragma clang diagnostic ignored "-Wnonnull" /* required because of <rdar://32627101> */
726 require_noerr_action(SecTrustSetAnchorCertificates(trust, NULL), errOut, fail("failed to unset anchors"));
727 #pragma clang diagnostic pop
728 require_action(set_trust_settings_for_cert(system_root), errOut, fail("failed to set trust settings for system_root"));
729 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag date non-CT cert with enterprise root trust succeeded");
730 if (error) {
731 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
732 (long)CFErrorGetCode(error), errSecVerifyActionFailed);
733 } else {
734 fail("expected trust evaluation to fail and it did not.");
735 }
736 require_action(remove_trust_settings_for_cert(system_root), errOut, fail("failed to remove trust settings for system_root"));
737
738 // test app anchor for failing cert passes
739 anchors = @[ (__bridge id)system_server_after ];
740 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
741 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert app anchor");
742
743 // test trust settings for failing cert passes
744 #pragma clang diagnostic push
745 #pragma clang diagnostic ignored "-Wnonnull" /* required because of <rdar://32627101> */
746 require_noerr_action(SecTrustSetAnchorCertificates(trust, NULL), errOut, fail("failed to remove anchors"));
747 #pragma clang diagnostic pop
748 require_action(set_trust_settings_for_cert(system_server_after), errOut, fail("failed to set trust settings for system_server_after"));
749 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert enterprise anchor");
750 require_action(remove_trust_settings_for_cert(system_server_after), errOut, fail("failed to remove trust settings for system_server_after"));
751
752 // EAP, test system cert after date without CT passes
753 anchors = @[ (__bridge id)system_root ];
754 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
755 CFReleaseNull(policy);
756 policy = SecPolicyCreateEAP(true, NULL);
757 require_noerr_action(SecTrustSetPolicies(trust, policy), errOut, fail("failed to set EAP policy"));
758 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with EAP cert");
759
760 // Test pinning policy name
761 CFReleaseNull(policy);
762 policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
763 require_noerr_action(SecTrustSetPolicies(trust, policy), errOut, fail("failed to set SSL policy"));
764 require_noerr_action(SecTrustSetPinningPolicyName(trust, CFSTR("a-policy-name")), errOut, fail("failed to set policy name"));
765 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with pinning policy name");
766 CFReleaseNull(trust);
767
768 // test system cert after date with CT passes
769 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
770 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
771 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
772 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
773 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date CT cert failed");
774 CFReleaseNull(trust);
775
776 // test system cert before date without CT passes
777 require_noerr_action(SecTrustCreateWithCertificates(system_server_before, policy, &trust), errOut, fail("failed to create trust"));
778 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
779 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
780 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
781 ok(SecTrustEvaluateWithError(trust, NULL), "system pre-flag-date non-CT cert failed");
782 CFReleaseNull(trust);
783
784 // test enterprise (non-public) after date without CT passes
785 require_action(set_trust_settings_for_cert(user_root), errOut, fail("failed to set trust settings for user_root"));
786 require_noerr_action(SecTrustCreateWithCertificates(user_server_after, policy, &trust), errOut, fail("failed to create trust"));
787 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
788 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
789 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with enterprise anchor");
790 require_action(remove_trust_settings_for_cert(user_root), errOut, fail("failed to remove trust settings for user_root"));
791
792 // test app anchor (non-public) after date without CT passes
793 anchors = @[ (__bridge id)user_root ];
794 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
795 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with app anchor");
796 CFReleaseNull(trust);
797 CFReleaseNull(policy);
798
799 errOut:
800 cleanup_keychain(keychain_certs);
801 CFReleaseNull(system_root);
802 CFReleaseNull(user_root);
803 CFReleaseNull(system_server_before);
804 CFReleaseNull(system_server_after);
805 CFReleaseNull(system_server_after_with_CT);
806 CFReleaseNull(user_server_after);
807 CFReleaseNull(trustedLogs);
808 CFReleaseNull(trust);
809 CFReleaseNull(policy);
810 }
811
812 static void test_apple_enforcement_exceptions(void) {
813 SecCertificateRef appleRoot = NULL, appleServerAuthCA = NULL, apple_server_after = NULL;
814 SecCertificateRef geoTrustRoot = NULL, appleISTCA8G1 = NULL, livability = NULL;
815 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
816 SecTrustRef trust = NULL;
817 SecPolicyRef policy = NULL;
818 NSArray *anchors = nil, *certs = nil;
819 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
820
821 require_action(appleRoot = SecCertificateCreateFromResource(@"enforcement_apple_root"),
822 errOut, fail("failed to create apple root"));
823 require_action(appleServerAuthCA = SecCertificateCreateFromResource(@"enforcement_apple_ca"),
824 errOut, fail("failed to create apple server auth CA"));
825 require_action(apple_server_after = SecCertificateCreateFromResource(@"enforcement_apple_server_after"),
826 errOut, fail("failed to create apple server cert issued after flag day"));
827 require_action(geoTrustRoot = SecCertificateCreateFromResource(@"GeoTrustPrimaryCAG2"),
828 errOut, fail("failed to create GeoTrust root"));
829 require_action(appleISTCA8G1 = SecCertificateCreateFromResource(@"AppleISTCA8G1"),
830 errOut, fail("failed to create apple IST CA"));
831 require_action(livability = SecCertificateCreateFromResource(@"livability"),
832 errOut, fail("failed to create livability cert"));
833
834 // test apple anchor after date without CT passes
835 policy = SecPolicyCreateSSL(true, CFSTR("bbasile-test.scv.apple.com"));
836 certs = @[ (__bridge id)apple_server_after, (__bridge id)appleServerAuthCA ];
837 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
838 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
839 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
840 ok(SecTrustEvaluateWithError(trust, NULL), "apple root post-flag-date non-CT cert failed");
841 CFReleaseNull(trust);
842 CFReleaseNull(policy);
843
844 // test apple ca after date without CT passes
845 policy = SecPolicyCreateSSL(true, CFSTR("livability.swe.apple.com"));
846 certs = @[ (__bridge id)livability, (__bridge id)appleISTCA8G1 ];
847 anchors = @[ (__bridge id)geoTrustRoot ];
848 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
849 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
850 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
851 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
852 ok(SecTrustEvaluateWithError(trust, NULL), "apple public post-flag-date non-CT cert failed");
853
854 errOut:
855 CFReleaseNull(appleRoot);
856 CFReleaseNull(appleServerAuthCA);
857 CFReleaseNull(apple_server_after);
858 CFReleaseNull(geoTrustRoot);
859 CFReleaseNull(appleISTCA8G1);
860 CFReleaseNull(livability);
861 CFReleaseNull(trustedLogs);
862 CFReleaseNull(trust);
863 CFReleaseNull(policy);
864 }
865
866 static void test_google_enforcement_exception(void) {
867 SecCertificateRef globalSignRoot = NULL, googleIAG3 = NULL, google = NULL;
868 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
869 SecTrustRef trust = NULL;
870 SecPolicyRef policy = NULL;
871 NSArray *anchors = nil, *certs = nil;
872 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
873
874 require_action(globalSignRoot = SecCertificateCreateFromResource(@"GlobalSignRootCAR2"),
875 errOut, fail("failed to create GlobalSign root"));
876 require_action(googleIAG3 = SecCertificateCreateFromResource(@"GoogleIAG3"),
877 errOut, fail("failed to create Google IA CA"));
878 require_action(google = SecCertificateCreateFromResource(@"google"),
879 errOut, fail("failed to create google server cert"));
880
881 // test google ca after date without CT passes
882 policy = SecPolicyCreateSSL(true, CFSTR("www.google.com"));
883 certs = @[ (__bridge id)google, (__bridge id)googleIAG3];
884 anchors = @[ (__bridge id)globalSignRoot ];
885 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
886 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
887 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
888 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
889 ok(SecTrustEvaluateWithError(trust, NULL), "google public post-flag-date non-CT cert failed");
890
891 errOut:
892 CFReleaseNull(globalSignRoot);
893 CFReleaseNull(googleIAG3);
894 CFReleaseNull(google);
895 CFReleaseNull(trustedLogs);
896 CFReleaseNull(trust);
897 CFReleaseNull(policy);
898 }
899
900 static void test_precerts_fail(void) {
901 SecCertificateRef precert = NULL, system_root = NULL;
902 SecTrustRef trust = NULL;
903 NSArray *anchors = nil;
904 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:561540800.0]; // October 18, 2018 at 12:33:20 AM PDT
905 CFErrorRef error = NULL;
906
907 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
908 errOut, fail("failed to create system root"));
909 require_action(precert = SecCertificateCreateFromResource(@"precert"),
910 errOut, fail("failed to create precert"));
911
912 anchors = @[(__bridge id)system_root];
913 require_noerr_action(SecTrustCreateWithCertificates(precert, NULL, &trust), errOut, fail("failed to create trust object"));
914 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchor certificate"));
915 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
916
917 is(SecTrustEvaluateWithError(trust, &error), false, "SECURITY: trust evaluation of precert succeeded");
918 if (error) {
919 is(CFErrorGetCode(error), errSecUnknownCriticalExtensionFlag, "got wrong error code for precert, got %ld, expected %d",
920 (long)CFErrorGetCode(error), errSecUnknownCriticalExtensionFlag);
921 } else {
922 fail("expected trust evaluation to fail and it did not.");
923 }
924
925
926 errOut:
927 CFReleaseNull(system_root);
928 CFReleaseNull(precert);
929 CFReleaseNull(error);
930 }
931
932 #define evalTrustExpectingError(errCode, ...) \
933 is(SecTrustEvaluateWithError(trust, &error), false, __VA_ARGS__); \
934 if (error) { \
935 is(CFErrorGetCode(error), errCode, "got wrong error code, got %ld, expected %d", \
936 (long)CFErrorGetCode(error), errCode); \
937 } else { \
938 fail("expected trust evaluation to fail and it did not."); \
939 } \
940 CFReleaseNull(error);
941
942 static void test_specific_domain_exceptions(void) {
943 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
944 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
945 SecTrustRef trust = NULL;
946 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
947 NSArray *anchors = nil;
948 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
949 CFErrorRef error = nil;
950 NSDictionary *exceptions = nil;
951
952 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
953 errOut, fail("failed to create system root"));
954 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
955 errOut, fail("failed to create system server cert issued after flag day"));
956 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
957 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
958
959 anchors = @[ (__bridge id)system_root ];
960 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
961 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
962 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
963 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
964
965 /* superdomain exception without CT fails */
966 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"test.apple.com"] };
967 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
968 evalTrustExpectingError(errSecVerifyActionFailed, "superdomain exception unexpectedly succeeded");
969
970 /* subdomain exceptions without CT fails */
971 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"one.ct.test.apple.com"] };
972 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
973 SecTrustSetNeedsEvaluation(trust);
974 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded")
975
976 /* no match without CT fails */
977 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"example.com"] };
978 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
979 SecTrustSetNeedsEvaluation(trust);
980 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
981
982 /* matching domain without CT succeeds */
983 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com"] };
984 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
985 SecTrustSetNeedsEvaluation(trust);
986 is(SecTrustEvaluateWithError(trust, &error), true, "exact match domain exception did not apply");
987
988 /* matching domain with CT succeeds */
989 CFReleaseNull(trust);
990 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
991 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
992 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
993 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
994 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
995
996 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
997
998 errOut:
999 CFReleaseNull(system_root);
1000 CFReleaseNull(system_server_after);
1001 CFReleaseNull(system_server_after_with_CT);
1002 CFReleaseNull(trust);
1003 CFReleaseNull(policy);
1004 CFReleaseNull(error);
1005 CFReleaseNull(trustedLogs);
1006 }
1007
1008 static void test_subdomain_exceptions(void) {
1009 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1010 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1011 SecTrustRef trust = NULL;
1012 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1013 NSArray *anchors = nil;
1014 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1015 CFErrorRef error = nil;
1016 NSDictionary *exceptions = nil;
1017
1018 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1019 errOut, fail("failed to create system root"));
1020 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1021 errOut, fail("failed to create system server cert issued after flag day"));
1022 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1023 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1024
1025 anchors = @[ (__bridge id)system_root ];
1026 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1027 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1028 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1029 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1030
1031 /* superdomain exception without CT succeeds */
1032 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".test.apple.com"] };
1033 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1034 is(SecTrustEvaluateWithError(trust, &error), true, "superdomain exception did not apply");
1035
1036 /* exact domain exception without CT succeeds */
1037 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".ct.test.apple.com"] };
1038 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1039 SecTrustSetNeedsEvaluation(trust);
1040 is(SecTrustEvaluateWithError(trust, &error), true, "exact domain exception did not apply");
1041
1042 /* no match without CT fails */
1043 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".example.com"] };
1044 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1045 SecTrustSetNeedsEvaluation(trust);
1046 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
1047
1048 /* subdomain without CT fails */
1049 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".one.ct.test.apple.com"] };
1050 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1051 SecTrustSetNeedsEvaluation(trust);
1052 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded");
1053
1054 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1055
1056 errOut:
1057 CFReleaseNull(system_root);
1058 CFReleaseNull(system_server_after);
1059 CFReleaseNull(system_server_after_with_CT);
1060 CFReleaseNull(trust);
1061 CFReleaseNull(policy);
1062 CFReleaseNull(error);
1063 CFReleaseNull(trustedLogs);
1064 }
1065
1066 static void test_mixed_domain_exceptions(void) {
1067 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1068 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1069 SecTrustRef trust = NULL;
1070 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1071 NSArray *anchors = nil;
1072 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1073 CFErrorRef error = nil;
1074 NSDictionary *exceptions = nil;
1075
1076 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1077 errOut, fail("failed to create system root"));
1078 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1079 errOut, fail("failed to create system server cert issued after flag day"));
1080 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1081 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1082
1083 anchors = @[ (__bridge id)system_root ];
1084 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1085 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1086 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1087 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1088
1089 /* specific domain exception without CT succeeds */
1090 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".example.com" ] };
1091 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1092 is(SecTrustEvaluateWithError(trust, &error), true, "one of exact domain exception did not apply");
1093
1094 /* super domain exception without CT succeeds */
1095 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".apple.com", @"example.com" ] };
1096 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1097 SecTrustSetNeedsEvaluation(trust);
1098 is(SecTrustEvaluateWithError(trust, &error), true, "one of superdomain exception did not apply");
1099
1100 /* both super domain and specific domain exceptions without CT succeeds */
1101 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".apple.com" ] };
1102 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1103 SecTrustSetNeedsEvaluation(trust);
1104 is(SecTrustEvaluateWithError(trust, &error), true, "both domain exception did not apply");
1105
1106 /* neither specific domain nor super domain exceptions without CT fails */
1107 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"apple.com", @".example.com" ] };
1108 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1109 SecTrustSetNeedsEvaluation(trust);
1110 evalTrustExpectingError(errSecVerifyActionFailed, "no match domain unexpectedly succeeded");
1111
1112 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1113
1114 errOut:
1115 CFReleaseNull(system_root);
1116 CFReleaseNull(system_server_after);
1117 CFReleaseNull(system_server_after_with_CT);
1118 CFReleaseNull(trust);
1119 CFReleaseNull(policy);
1120 CFReleaseNull(error);
1121 CFReleaseNull(trustedLogs);
1122 }
1123
1124
1125
1126 static void test_ct_domain_exceptions(void) {
1127 test_specific_domain_exceptions();
1128 test_subdomain_exceptions();
1129 test_mixed_domain_exceptions();
1130 }
1131
1132 static void test_ct_leaf_exceptions(void) {
1133 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1134 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1135 SecTrustRef trust = NULL;
1136 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1137 NSArray *anchors = nil;
1138 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1139 CFErrorRef error = nil;
1140 NSDictionary *leafException = nil, *exceptions = nil;
1141 NSData *leafHash = nil;
1142
1143 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1144 errOut, fail("failed to create system root"));
1145 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1146 errOut, fail("failed to create system server cert issued after flag day"));
1147 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1148 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1149
1150 anchors = @[ (__bridge id)system_root ];
1151 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1152 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1153 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1154 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1155
1156 /* set exception on leaf cert without CT */
1157 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after));
1158 leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1159 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : leafHash,
1160 };
1161 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ] };
1162 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1163 "failed to set exceptions: %@", error);
1164 is(SecTrustEvaluateWithError(trust, &error), true, "leaf public key exception did not apply");
1165
1166 /* set exception on leaf cert with CT */
1167 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after_with_CT));
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 SecTrustSetNeedsEvaluation(trust);
1175 evalTrustExpectingError(errSecVerifyActionFailed, "leaf cert with no public key exceptions succeeded");
1176
1177 /* matching public key with CT succeeds */
1178 CFReleaseNull(trust);
1179 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
1180 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1181 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1182 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1183 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
1184
1185 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1186
1187 errOut:
1188 CFReleaseNull(system_root);
1189 CFReleaseNull(system_server_after);
1190 CFReleaseNull(system_server_after_with_CT);
1191 CFReleaseNull(trustedLogs);
1192 CFReleaseNull(trust);
1193 CFReleaseNull(policy);
1194 CFReleaseNull(error);
1195 }
1196
1197 static void test_ct_unconstrained_ca_exceptions(void) {
1198 SecCertificateRef root = NULL, subca = NULL;
1199 SecCertificateRef server_matching = NULL, server_matching_with_CT = NULL, server_partial = NULL, server_no_match = NULL, server_no_org = NULL;
1200 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1201 SecTrustRef trust = NULL;
1202 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1203 NSArray *anchors = nil, *certs = nil;
1204 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1205 CFErrorRef error = nil;
1206 NSDictionary *caException = nil, *exceptions = nil;
1207 NSData *caHash = nil;
1208
1209 require_action(root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1210 errOut, fail("failed to create system root"));
1211 require_action(subca = SecCertificateCreateFromResource(@"enforcement_system_unconstrained_subca"),
1212 errOut, fail("failed to create subca"));
1213 require_action(server_matching = SecCertificateCreateFromResource(@"enforcement_system_server_matching_orgs"),
1214 errOut, fail("failed to create server cert with matching orgs"));
1215 require_action(server_matching_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_matching_orgs_scts"),
1216 errOut, fail("failed to create server cert with matching orgs and scts"));
1217 require_action(server_partial = SecCertificateCreateFromResource(@"enforcement_system_server_partial_orgs"),
1218 errOut, fail("failed to create server cert with partial orgs"));
1219 require_action(server_no_match = SecCertificateCreateFromResource(@"enforcement_system_server_nonmatching_orgs"),
1220 errOut, fail("failed to create server cert with non-matching orgs"));
1221 require_action(server_no_org = SecCertificateCreateFromResource(@"enforcement_system_server_no_orgs"),
1222 errOut, fail("failed to create server cert with no orgs"));
1223
1224 anchors = @[ (__bridge id)root ];
1225
1226 #define createTrust(certs) \
1227 CFReleaseNull(trust); \
1228 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
1229 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors")); \
1230 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
1231 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
1232
1233 /* Set exception on the subCA */
1234 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(subca));
1235 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1236 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1237 };
1238 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ caException ] };
1239 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1240 "failed to set exceptions: %@", error);
1241
1242 /* Verify that non-CT cert with Orgs matching subCA passes */
1243 certs = @[ (__bridge id)server_matching, (__bridge id)subca];
1244 createTrust(certs);
1245 is(SecTrustEvaluateWithError(trust, &error), true, "matching org subca exception did not apply: %@", error);
1246
1247 /* Verify that CT cert with Orgs matching subCA passes */
1248 certs = @[ (__bridge id)server_matching_with_CT, (__bridge id)subca];
1249 createTrust(certs);
1250 is(SecTrustEvaluateWithError(trust, &error), true, "CT matching org subca exception did not apply: %@", error);
1251
1252 /* Verify that non-CT cert with partial Org match fails */
1253 certs = @[ (__bridge id)server_partial, (__bridge id)subca];
1254 createTrust(certs);
1255 evalTrustExpectingError(errSecVerifyActionFailed, "partial matching org leaf succeeded");
1256
1257 /* Verify that a non-CT cert with non-matching Org fails */
1258 certs = @[ (__bridge id)server_no_match, (__bridge id)subca];
1259 createTrust(certs);
1260 evalTrustExpectingError(errSecVerifyActionFailed, "non-matching org leaf succeeded");
1261
1262 /* Verify that a non-CT cert with no Org fails */
1263 certs = @[ (__bridge id)server_no_org, (__bridge id)subca];
1264 createTrust(certs);
1265 evalTrustExpectingError(errSecVerifyActionFailed, "no org leaf succeeded");
1266
1267 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1268
1269 #undef createTrust
1270
1271 errOut:
1272 CFReleaseNull(root);
1273 CFReleaseNull(subca);
1274 CFReleaseNull(server_matching);
1275 CFReleaseNull(server_matching_with_CT);
1276 CFReleaseNull(server_partial);
1277 CFReleaseNull(server_no_match);
1278 CFReleaseNull(server_no_org);
1279 CFReleaseNull(trustedLogs);
1280 CFReleaseNull(trust);
1281 CFReleaseNull(policy);
1282 CFReleaseNull(error);
1283 }
1284
1285 static void test_ct_constrained_ca_exceptions(void) {
1286 SecCertificateRef root = NULL, org_constrained_subca = NULL;
1287 SecCertificateRef constraint_pass_server = NULL, constraint_pass_server_ct = NULL, constraint_fail_server = NULL;
1288 SecCertificateRef dn_constrained_subca = NULL, dn_constrained_server = NULL, dn_constrained_server_mismatch = NULL;
1289 SecCertificateRef dns_constrained_subca = NULL, dns_constrained_server = NULL, dns_constrained_server_mismatch = NULL;
1290 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1291 SecTrustRef trust = NULL;
1292 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1293 NSArray *anchors = nil, *certs = nil;
1294 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1295 CFErrorRef error = nil;
1296 NSDictionary *caException = nil, *exceptions = nil;
1297 NSMutableArray *caExceptions = [NSMutableArray array];
1298 NSData *caHash = nil;
1299
1300 require_action(root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1301 errOut, fail("failed to create system root"));
1302 require_action(org_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_subca"),
1303 errOut, fail("failed to create org-constrained subca"));
1304 require_action(constraint_pass_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_server"),
1305 errOut, fail("failed to create constrained non-CT leaf"));
1306 require_action(constraint_pass_server_ct = SecCertificateCreateFromResource(@"enforcement_system_constrained_server_scts"),
1307 errOut, fail("failed to create constrained CT leaf"));
1308 require_action(constraint_fail_server= SecCertificateCreateFromResource(@"enforcement_system_constrained_fail_server"),
1309 errOut, fail("failed to create constraint failure leaf"));
1310 require_action(dn_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_subca"),
1311 errOut, fail("failed to create dn-constrained subca"));
1312 require_action(dn_constrained_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_server"),
1313 errOut, fail("failed to create dn-constrained leaf"));
1314 require_action(dn_constrained_server_mismatch = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_server_mismatch"),
1315 errOut, fail("failed to create dn-constrained leaf with mismatched orgs"));
1316 require_action(dns_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_subca"),
1317 errOut, fail("failed to create dns-constrained subca"));
1318 require_action(dns_constrained_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_server"),
1319 errOut, fail("failed to create dns-constrained leaf"));
1320 require_action(dns_constrained_server_mismatch = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_server_mismatch"),
1321 errOut, fail("failed to create dns-constrained leaf with mismatched orgs"));
1322
1323 anchors = @[ (__bridge id)root ];
1324
1325 /* Set exception on the subCAs */
1326 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(org_constrained_subca));
1327 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1328 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1329 };
1330 [caExceptions addObject:caException];
1331
1332 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dn_constrained_subca));
1333 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1334 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1335 };
1336 [caExceptions addObject:caException];
1337
1338 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dns_constrained_subca));
1339 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1340 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1341 };
1342 [caExceptions addObject:caException];
1343 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : caExceptions };
1344 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1345 "failed to set exceptions: %@", error);
1346
1347 #define createTrust(certs) \
1348 CFReleaseNull(trust); \
1349 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
1350 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors")); \
1351 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
1352 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
1353
1354 /* Verify org-constrained non-CT leaf passes */
1355 certs = @[ (__bridge id)constraint_pass_server, (__bridge id)org_constrained_subca ];
1356 createTrust(certs);
1357 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1358
1359 /* Verify org-constrained CT leaf passes */
1360 certs = @[ (__bridge id)constraint_pass_server_ct, (__bridge id)org_constrained_subca ];
1361 createTrust(certs);
1362 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1363
1364 /* Verify org-constrained non-CT leaf with wrong org fails */
1365 certs = @[ (__bridge id)constraint_fail_server, (__bridge id)org_constrained_subca ];
1366 createTrust(certs);
1367 evalTrustExpectingError(errSecInvalidName, "leaf failing name constraints succeeded");
1368
1369 /* Verify dn-constrained (but not with org) non-CT leaf with matching orgs succeeds */
1370 certs = @[ (__bridge id)dn_constrained_server, (__bridge id)dn_constrained_subca ];
1371 createTrust(certs);
1372 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1373
1374 /* Verify dn-constrained (but not with org) non-CT leaf without matching orgs fails */
1375 certs = @[ (__bridge id)dn_constrained_server_mismatch, (__bridge id)dn_constrained_subca ];
1376 createTrust(certs);
1377 evalTrustExpectingError(errSecVerifyActionFailed, "dn name constraints with no org succeeded");
1378
1379 /* Verify dns-constrained (no DN constraints) non-CT leaf with matching orgs succeeds */
1380 certs = @[ (__bridge id)dns_constrained_server, (__bridge id)dns_constrained_subca ];
1381 createTrust(certs);
1382 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1383
1384 /* Verify dns-constrained (no DN constraints) non-CT leaf without matching orgs fails*/
1385 certs = @[ (__bridge id)dns_constrained_server_mismatch, (__bridge id)dns_constrained_subca ];
1386 createTrust(certs);
1387 evalTrustExpectingError(errSecVerifyActionFailed, "dns name constraints with no DN constraint succeeded");
1388
1389 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1390
1391 #undef createTrust
1392
1393 errOut:
1394 CFReleaseNull(root);
1395 CFReleaseNull(org_constrained_subca);
1396 CFReleaseNull(constraint_pass_server);
1397 CFReleaseNull(constraint_pass_server_ct);
1398 CFReleaseNull(constraint_fail_server);
1399 CFReleaseNull(dn_constrained_subca);
1400 CFReleaseNull(dn_constrained_server);
1401 CFReleaseNull(dn_constrained_server_mismatch);
1402 CFReleaseNull(dns_constrained_subca);
1403 CFReleaseNull(dns_constrained_server);
1404 CFReleaseNull(dns_constrained_server_mismatch);
1405 CFReleaseNull(trustedLogs);
1406 CFReleaseNull(trust);
1407 CFReleaseNull(policy);
1408 CFReleaseNull(error);
1409 }
1410
1411 static void test_ct_key_exceptions(void) {
1412 test_ct_leaf_exceptions();
1413 test_ct_unconstrained_ca_exceptions();
1414 test_ct_constrained_ca_exceptions();
1415 }
1416
1417 static void test_ct_exceptions(void) {
1418 test_ct_domain_exceptions();
1419 test_ct_key_exceptions();
1420 }
1421
1422 int si_82_sectrust_ct(int argc, char *const *argv)
1423 {
1424 plan_tests(432);
1425
1426 tests();
1427 test_sct_serialization();
1428 testSetCTExceptions();
1429 test_enforcement();
1430 test_apple_enforcement_exceptions();
1431 test_google_enforcement_exception();
1432 test_precerts_fail();
1433 test_ct_exceptions();
1434
1435 return 0;
1436 }