]> git.saurik.com Git - apple/security.git/blob - OSX/shared_regressions/si-82-sectrust-ct.m
Security-58286.251.4.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 NSDate *expiredDate = [NSDate dateWithTimeIntervalSinceReferenceDate:570000000.0]; // January 24, 2019 at 12:20:00 AM EST
678 CFErrorRef error = nil;
679 CFDataRef exceptions = nil;
680
681 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
682 errOut, fail("failed to create system root"));
683 require_action(user_root = SecCertificateCreateFromResource(@"enforcement_user_root"),
684 errOut, fail("failed to create user root"));
685 require_action(system_server_before = SecCertificateCreateFromResource(@"enforcement_system_server_before"),
686 errOut, fail("failed to create system server cert issued before flag day"));
687 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
688 errOut, fail("failed to create system server cert issued after flag day"));
689 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
690 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
691 require_action(user_server_after = SecCertificateCreateFromResource(@"enforcement_user_server_after"),
692 errOut, fail("failed to create user server cert issued after flag day"));
693
694 /* set up the user and system roots to be used with trust settings */
695 setup_for_user_trust(@[(__bridge id)system_root, (__bridge id)user_root, (__bridge id)system_server_after],
696 &keychain_certs);
697 anchors = @[ (__bridge id)system_root ];
698 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
699 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
700 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
701
702 #if 0 // Disable this test until we can mock MobileAsset and force asset to be out-of-date
703 // Out-of-date asset, test system cert after date without CT passes
704 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with out-of-date asset");
705 #endif
706
707 // test system cert after date without CT fails
708 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
709 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag-date non-CT cert with in-date asset succeeded");
710 if (error) {
711 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
712 (long)CFErrorGetCode(error), errSecVerifyActionFailed);
713 } else {
714 fail("expected trust evaluation to fail and it did not.");
715 }
716
717 // test expired system cert after date without CT passes with only expiration error
718 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)expiredDate), errOut, fail("failed to set verify date"));
719 ok(SecTrustIsExpiredOnly(trust), "expired system post-flag-date non-CT cert had non-expiration errors");
720 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
721
722 // test exceptions for failing cert passes
723 exceptions = SecTrustCopyExceptions(trust);
724 ok(SecTrustSetExceptions(trust, exceptions), "failed to set exceptions for failing non-CT cert");
725 CFReleaseNull(exceptions);
726 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with exceptions set");
727 SecTrustSetExceptions(trust, NULL);
728
729 // test system cert + enterprise anchor after date without CT fails
730 #pragma clang diagnostic push
731 #pragma clang diagnostic ignored "-Wnonnull" /* required because of <rdar://32627101> */
732 require_noerr_action(SecTrustSetAnchorCertificates(trust, NULL), errOut, fail("failed to unset anchors"));
733 #pragma clang diagnostic pop
734 require_action(set_trust_settings_for_cert(system_root), errOut, fail("failed to set trust settings for system_root"));
735 is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag date non-CT cert with enterprise root trust succeeded");
736 if (error) {
737 is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d",
738 (long)CFErrorGetCode(error), errSecVerifyActionFailed);
739 } else {
740 fail("expected trust evaluation to fail and it did not.");
741 }
742 require_action(remove_trust_settings_for_cert(system_root), errOut, fail("failed to remove trust settings for system_root"));
743
744 // test app anchor for failing cert passes
745 anchors = @[ (__bridge id)system_server_after ];
746 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
747 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert app anchor");
748
749 // test trust settings for failing cert passes
750 #pragma clang diagnostic push
751 #pragma clang diagnostic ignored "-Wnonnull" /* required because of <rdar://32627101> */
752 require_noerr_action(SecTrustSetAnchorCertificates(trust, NULL), errOut, fail("failed to remove anchors"));
753 #pragma clang diagnostic pop
754 require_action(set_trust_settings_for_cert(system_server_after), errOut, fail("failed to set trust settings for system_server_after"));
755 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with server cert enterprise anchor");
756 require_action(remove_trust_settings_for_cert(system_server_after), errOut, fail("failed to remove trust settings for system_server_after"));
757
758 // EAP, test system cert after date without CT passes
759 anchors = @[ (__bridge id)system_root ];
760 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
761 CFReleaseNull(policy);
762 policy = SecPolicyCreateEAP(true, NULL);
763 require_noerr_action(SecTrustSetPolicies(trust, policy), errOut, fail("failed to set EAP policy"));
764 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with EAP cert");
765
766 // Test pinning policy name
767 CFReleaseNull(policy);
768 policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
769 require_noerr_action(SecTrustSetPolicies(trust, policy), errOut, fail("failed to set SSL policy"));
770 require_noerr_action(SecTrustSetPinningPolicyName(trust, CFSTR("a-policy-name")), errOut, fail("failed to set policy name"));
771 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert failed with pinning policy name");
772 CFReleaseNull(trust);
773
774 // test system cert after date with CT passes
775 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
776 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
777 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
778 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
779 ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date CT cert failed");
780 CFReleaseNull(trust);
781
782 // test system cert before date without CT passes
783 require_noerr_action(SecTrustCreateWithCertificates(system_server_before, policy, &trust), errOut, fail("failed to create trust"));
784 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
785 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
786 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
787 ok(SecTrustEvaluateWithError(trust, NULL), "system pre-flag-date non-CT cert failed");
788 CFReleaseNull(trust);
789
790 // test enterprise (non-public) after date without CT passes
791 require_action(set_trust_settings_for_cert(user_root), errOut, fail("failed to set trust settings for user_root"));
792 require_noerr_action(SecTrustCreateWithCertificates(user_server_after, policy, &trust), errOut, fail("failed to create trust"));
793 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
794 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
795 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with enterprise anchor");
796 require_action(remove_trust_settings_for_cert(user_root), errOut, fail("failed to remove trust settings for user_root"));
797
798 // test app anchor (non-public) after date without CT passes
799 anchors = @[ (__bridge id)user_root ];
800 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
801 ok(SecTrustEvaluateWithError(trust, NULL), "non-system post-flag-date non-CT cert failed with app anchor");
802 CFReleaseNull(trust);
803 CFReleaseNull(policy);
804
805 errOut:
806 cleanup_keychain(keychain_certs);
807 CFReleaseNull(system_root);
808 CFReleaseNull(user_root);
809 CFReleaseNull(system_server_before);
810 CFReleaseNull(system_server_after);
811 CFReleaseNull(system_server_after_with_CT);
812 CFReleaseNull(user_server_after);
813 CFReleaseNull(trustedLogs);
814 CFReleaseNull(trust);
815 CFReleaseNull(policy);
816 }
817
818 static void test_apple_enforcement_exceptions(void) {
819 SecCertificateRef appleRoot = NULL, appleServerAuthCA = NULL, apple_server_after = NULL;
820 SecCertificateRef geoTrustRoot = NULL, appleISTCA8G1 = NULL, livability = NULL;
821 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
822 SecTrustRef trust = NULL;
823 SecPolicyRef policy = NULL;
824 NSArray *anchors = nil, *certs = nil;
825 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
826
827 require_action(appleRoot = SecCertificateCreateFromResource(@"enforcement_apple_root"),
828 errOut, fail("failed to create apple root"));
829 require_action(appleServerAuthCA = SecCertificateCreateFromResource(@"enforcement_apple_ca"),
830 errOut, fail("failed to create apple server auth CA"));
831 require_action(apple_server_after = SecCertificateCreateFromResource(@"enforcement_apple_server_after"),
832 errOut, fail("failed to create apple server cert issued after flag day"));
833 require_action(geoTrustRoot = SecCertificateCreateFromResource(@"GeoTrustPrimaryCAG2"),
834 errOut, fail("failed to create GeoTrust root"));
835 require_action(appleISTCA8G1 = SecCertificateCreateFromResource(@"AppleISTCA8G1"),
836 errOut, fail("failed to create apple IST CA"));
837 require_action(livability = SecCertificateCreateFromResource(@"livability"),
838 errOut, fail("failed to create livability cert"));
839
840 // test apple anchor after date without CT passes
841 policy = SecPolicyCreateSSL(true, CFSTR("bbasile-test.scv.apple.com"));
842 certs = @[ (__bridge id)apple_server_after, (__bridge id)appleServerAuthCA ];
843 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
844 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
845 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
846 ok(SecTrustEvaluateWithError(trust, NULL), "apple root post-flag-date non-CT cert failed");
847 CFReleaseNull(trust);
848 CFReleaseNull(policy);
849
850 // test apple ca after date without CT passes
851 policy = SecPolicyCreateSSL(true, CFSTR("livability.swe.apple.com"));
852 certs = @[ (__bridge id)livability, (__bridge id)appleISTCA8G1 ];
853 anchors = @[ (__bridge id)geoTrustRoot ];
854 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
855 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
856 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
857 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
858 ok(SecTrustEvaluateWithError(trust, NULL), "apple public post-flag-date non-CT cert failed");
859
860 errOut:
861 CFReleaseNull(appleRoot);
862 CFReleaseNull(appleServerAuthCA);
863 CFReleaseNull(apple_server_after);
864 CFReleaseNull(geoTrustRoot);
865 CFReleaseNull(appleISTCA8G1);
866 CFReleaseNull(livability);
867 CFReleaseNull(trustedLogs);
868 CFReleaseNull(trust);
869 CFReleaseNull(policy);
870 }
871
872 static void test_google_enforcement_exception(void) {
873 SecCertificateRef globalSignRoot = NULL, googleIAG3 = NULL, google = NULL;
874 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
875 SecTrustRef trust = NULL;
876 SecPolicyRef policy = NULL;
877 NSArray *anchors = nil, *certs = nil;
878 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
879
880 require_action(globalSignRoot = SecCertificateCreateFromResource(@"GlobalSignRootCAR2"),
881 errOut, fail("failed to create GlobalSign root"));
882 require_action(googleIAG3 = SecCertificateCreateFromResource(@"GoogleIAG3"),
883 errOut, fail("failed to create Google IA CA"));
884 require_action(google = SecCertificateCreateFromResource(@"google"),
885 errOut, fail("failed to create google server cert"));
886
887 // test google ca after date without CT passes
888 policy = SecPolicyCreateSSL(true, CFSTR("www.google.com"));
889 certs = @[ (__bridge id)google, (__bridge id)googleIAG3];
890 anchors = @[ (__bridge id)globalSignRoot ];
891 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust"));
892 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
893 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
894 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
895 ok(SecTrustEvaluateWithError(trust, NULL), "google public post-flag-date non-CT cert failed");
896
897 errOut:
898 CFReleaseNull(globalSignRoot);
899 CFReleaseNull(googleIAG3);
900 CFReleaseNull(google);
901 CFReleaseNull(trustedLogs);
902 CFReleaseNull(trust);
903 CFReleaseNull(policy);
904 }
905
906 static void test_precerts_fail(void) {
907 SecCertificateRef precert = NULL, system_root = NULL;
908 SecTrustRef trust = NULL;
909 NSArray *anchors = nil;
910 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:561540800.0]; // October 18, 2018 at 12:33:20 AM PDT
911 CFErrorRef error = NULL;
912
913 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
914 errOut, fail("failed to create system root"));
915 require_action(precert = SecCertificateCreateFromResource(@"precert"),
916 errOut, fail("failed to create precert"));
917
918 anchors = @[(__bridge id)system_root];
919 require_noerr_action(SecTrustCreateWithCertificates(precert, NULL, &trust), errOut, fail("failed to create trust object"));
920 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchor certificate"));
921 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
922
923 is(SecTrustEvaluateWithError(trust, &error), false, "SECURITY: trust evaluation of precert succeeded");
924 if (error) {
925 is(CFErrorGetCode(error), errSecUnknownCriticalExtensionFlag, "got wrong error code for precert, got %ld, expected %d",
926 (long)CFErrorGetCode(error), errSecUnknownCriticalExtensionFlag);
927 } else {
928 fail("expected trust evaluation to fail and it did not.");
929 }
930
931
932 errOut:
933 CFReleaseNull(system_root);
934 CFReleaseNull(precert);
935 CFReleaseNull(error);
936 }
937
938 #define evalTrustExpectingError(errCode, ...) \
939 is(SecTrustEvaluateWithError(trust, &error), false, __VA_ARGS__); \
940 if (error) { \
941 is(CFErrorGetCode(error), errCode, "got wrong error code, got %ld, expected %d", \
942 (long)CFErrorGetCode(error), errCode); \
943 } else { \
944 fail("expected trust evaluation to fail and it did not."); \
945 } \
946 CFReleaseNull(error);
947
948 static void test_specific_domain_exceptions(void) {
949 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
950 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
951 SecTrustRef trust = NULL;
952 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
953 NSArray *anchors = nil;
954 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
955 CFErrorRef error = nil;
956 NSDictionary *exceptions = nil;
957
958 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
959 errOut, fail("failed to create system root"));
960 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
961 errOut, fail("failed to create system server cert issued after flag day"));
962 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
963 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
964
965 anchors = @[ (__bridge id)system_root ];
966 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
967 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
968 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
969 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
970
971 /* superdomain exception without CT fails */
972 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"test.apple.com"] };
973 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
974 evalTrustExpectingError(errSecVerifyActionFailed, "superdomain exception unexpectedly succeeded");
975
976 /* subdomain exceptions without CT fails */
977 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"one.ct.test.apple.com"] };
978 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
979 SecTrustSetNeedsEvaluation(trust);
980 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded")
981
982 /* no match without CT fails */
983 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"example.com"] };
984 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
985 SecTrustSetNeedsEvaluation(trust);
986 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
987
988 /* matching domain without CT succeeds */
989 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com"] };
990 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
991 SecTrustSetNeedsEvaluation(trust);
992 is(SecTrustEvaluateWithError(trust, &error), true, "exact match domain exception did not apply");
993
994 /* matching domain with CT succeeds */
995 CFReleaseNull(trust);
996 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
997 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
998 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
999 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1000 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
1001
1002 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1003
1004 errOut:
1005 CFReleaseNull(system_root);
1006 CFReleaseNull(system_server_after);
1007 CFReleaseNull(system_server_after_with_CT);
1008 CFReleaseNull(trust);
1009 CFReleaseNull(policy);
1010 CFReleaseNull(error);
1011 CFReleaseNull(trustedLogs);
1012 }
1013
1014 static void test_subdomain_exceptions(void) {
1015 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1016 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1017 SecTrustRef trust = NULL;
1018 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1019 NSArray *anchors = nil;
1020 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1021 CFErrorRef error = nil;
1022 NSDictionary *exceptions = nil;
1023
1024 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1025 errOut, fail("failed to create system root"));
1026 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1027 errOut, fail("failed to create system server cert issued after flag day"));
1028 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1029 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1030
1031 anchors = @[ (__bridge id)system_root ];
1032 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1033 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1034 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1035 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1036
1037 /* superdomain exception without CT succeeds */
1038 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".test.apple.com"] };
1039 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1040 is(SecTrustEvaluateWithError(trust, &error), true, "superdomain exception did not apply");
1041
1042 /* exact domain exception without CT succeeds */
1043 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".ct.test.apple.com"] };
1044 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1045 SecTrustSetNeedsEvaluation(trust);
1046 is(SecTrustEvaluateWithError(trust, &error), true, "exact domain exception did not apply");
1047
1048 /* no match without CT fails */
1049 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".example.com"] };
1050 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1051 SecTrustSetNeedsEvaluation(trust);
1052 evalTrustExpectingError(errSecVerifyActionFailed, "unrelated domain exception unexpectedly succeeded");
1053
1054 /* subdomain without CT fails */
1055 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".one.ct.test.apple.com"] };
1056 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1057 SecTrustSetNeedsEvaluation(trust);
1058 evalTrustExpectingError(errSecVerifyActionFailed, "subdomain exception unexpectedly succeeded");
1059
1060 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1061
1062 errOut:
1063 CFReleaseNull(system_root);
1064 CFReleaseNull(system_server_after);
1065 CFReleaseNull(system_server_after_with_CT);
1066 CFReleaseNull(trust);
1067 CFReleaseNull(policy);
1068 CFReleaseNull(error);
1069 CFReleaseNull(trustedLogs);
1070 }
1071
1072 static void test_mixed_domain_exceptions(void) {
1073 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1074 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1075 SecTrustRef trust = NULL;
1076 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1077 NSArray *anchors = nil;
1078 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1079 CFErrorRef error = nil;
1080 NSDictionary *exceptions = nil;
1081
1082 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1083 errOut, fail("failed to create system root"));
1084 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1085 errOut, fail("failed to create system server cert issued after flag day"));
1086 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1087 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1088
1089 anchors = @[ (__bridge id)system_root ];
1090 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1091 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1092 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1093 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1094
1095 /* specific domain exception without CT succeeds */
1096 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".example.com" ] };
1097 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1098 is(SecTrustEvaluateWithError(trust, &error), true, "one of exact domain exception did not apply");
1099
1100 /* super domain exception without CT succeeds */
1101 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@".apple.com", @"example.com" ] };
1102 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1103 SecTrustSetNeedsEvaluation(trust);
1104 is(SecTrustEvaluateWithError(trust, &error), true, "one of superdomain exception did not apply");
1105
1106 /* both super domain and specific domain exceptions without CT succeeds */
1107 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"ct.test.apple.com", @".apple.com" ] };
1108 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1109 SecTrustSetNeedsEvaluation(trust);
1110 is(SecTrustEvaluateWithError(trust, &error), true, "both domain exception did not apply");
1111
1112 /* neither specific domain nor super domain exceptions without CT fails */
1113 exceptions = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[@"apple.com", @".example.com" ] };
1114 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error), "failed to set exceptions: %@", error);
1115 SecTrustSetNeedsEvaluation(trust);
1116 evalTrustExpectingError(errSecVerifyActionFailed, "no match domain unexpectedly succeeded");
1117
1118 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1119
1120 errOut:
1121 CFReleaseNull(system_root);
1122 CFReleaseNull(system_server_after);
1123 CFReleaseNull(system_server_after_with_CT);
1124 CFReleaseNull(trust);
1125 CFReleaseNull(policy);
1126 CFReleaseNull(error);
1127 CFReleaseNull(trustedLogs);
1128 }
1129
1130
1131
1132 static void test_ct_domain_exceptions(void) {
1133 test_specific_domain_exceptions();
1134 test_subdomain_exceptions();
1135 test_mixed_domain_exceptions();
1136 }
1137
1138 static void test_ct_leaf_exceptions(void) {
1139 SecCertificateRef system_root = NULL, system_server_after = NULL, system_server_after_with_CT = NULL;
1140 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1141 SecTrustRef trust = NULL;
1142 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1143 NSArray *anchors = nil;
1144 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1145 CFErrorRef error = nil;
1146 NSDictionary *leafException = nil, *exceptions = nil;
1147 NSData *leafHash = nil;
1148
1149 require_action(system_root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1150 errOut, fail("failed to create system root"));
1151 require_action(system_server_after = SecCertificateCreateFromResource(@"enforcement_system_server_after"),
1152 errOut, fail("failed to create system server cert issued after flag day"));
1153 require_action(system_server_after_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_after_scts"),
1154 errOut, fail("failed to create system server cert issued after flag day with SCTs"));
1155
1156 anchors = @[ (__bridge id)system_root ];
1157 require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust"));
1158 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1159 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1160 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1161
1162 /* set exception on leaf cert without CT */
1163 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after));
1164 leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1165 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : leafHash,
1166 };
1167 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ] };
1168 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1169 "failed to set exceptions: %@", error);
1170 is(SecTrustEvaluateWithError(trust, &error), true, "leaf public key exception did not apply");
1171
1172 /* set exception on leaf cert with CT */
1173 leafHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(system_server_after_with_CT));
1174 leafException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1175 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : leafHash,
1176 };
1177 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ leafException ] };
1178 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1179 "failed to set exceptions: %@", error);
1180 SecTrustSetNeedsEvaluation(trust);
1181 evalTrustExpectingError(errSecVerifyActionFailed, "leaf cert with no public key exceptions succeeded");
1182
1183 /* matching public key with CT succeeds */
1184 CFReleaseNull(trust);
1185 require_noerr_action(SecTrustCreateWithCertificates(system_server_after_with_CT, policy, &trust), errOut, fail("failed to create trust"));
1186 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors"));
1187 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date"));
1188 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs")); // set trusted logs to trigger enforcing behavior
1189 is(SecTrustEvaluateWithError(trust, &error), true, "ct cert should always pass");
1190
1191 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1192
1193 errOut:
1194 CFReleaseNull(system_root);
1195 CFReleaseNull(system_server_after);
1196 CFReleaseNull(system_server_after_with_CT);
1197 CFReleaseNull(trustedLogs);
1198 CFReleaseNull(trust);
1199 CFReleaseNull(policy);
1200 CFReleaseNull(error);
1201 }
1202
1203 static void test_ct_unconstrained_ca_exceptions(void) {
1204 SecCertificateRef root = NULL, subca = NULL;
1205 SecCertificateRef server_matching = NULL, server_matching_with_CT = NULL, server_partial = NULL, server_no_match = NULL, server_no_org = NULL;
1206 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1207 SecTrustRef trust = NULL;
1208 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1209 NSArray *anchors = nil, *certs = nil;
1210 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1211 CFErrorRef error = nil;
1212 NSDictionary *caException = nil, *exceptions = nil;
1213 NSData *caHash = nil;
1214
1215 require_action(root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1216 errOut, fail("failed to create system root"));
1217 require_action(subca = SecCertificateCreateFromResource(@"enforcement_system_unconstrained_subca"),
1218 errOut, fail("failed to create subca"));
1219 require_action(server_matching = SecCertificateCreateFromResource(@"enforcement_system_server_matching_orgs"),
1220 errOut, fail("failed to create server cert with matching orgs"));
1221 require_action(server_matching_with_CT = SecCertificateCreateFromResource(@"enforcement_system_server_matching_orgs_scts"),
1222 errOut, fail("failed to create server cert with matching orgs and scts"));
1223 require_action(server_partial = SecCertificateCreateFromResource(@"enforcement_system_server_partial_orgs"),
1224 errOut, fail("failed to create server cert with partial orgs"));
1225 require_action(server_no_match = SecCertificateCreateFromResource(@"enforcement_system_server_nonmatching_orgs"),
1226 errOut, fail("failed to create server cert with non-matching orgs"));
1227 require_action(server_no_org = SecCertificateCreateFromResource(@"enforcement_system_server_no_orgs"),
1228 errOut, fail("failed to create server cert with no orgs"));
1229
1230 anchors = @[ (__bridge id)root ];
1231
1232 #define createTrust(certs) \
1233 CFReleaseNull(trust); \
1234 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
1235 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors")); \
1236 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
1237 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
1238
1239 /* Set exception on the subCA */
1240 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(subca));
1241 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1242 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1243 };
1244 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : @[ caException ] };
1245 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1246 "failed to set exceptions: %@", error);
1247
1248 /* Verify that non-CT cert with Orgs matching subCA passes */
1249 certs = @[ (__bridge id)server_matching, (__bridge id)subca];
1250 createTrust(certs);
1251 is(SecTrustEvaluateWithError(trust, &error), true, "matching org subca exception did not apply: %@", error);
1252
1253 /* Verify that CT cert with Orgs matching subCA passes */
1254 certs = @[ (__bridge id)server_matching_with_CT, (__bridge id)subca];
1255 createTrust(certs);
1256 is(SecTrustEvaluateWithError(trust, &error), true, "CT matching org subca exception did not apply: %@", error);
1257
1258 /* Verify that non-CT cert with partial Org match fails */
1259 certs = @[ (__bridge id)server_partial, (__bridge id)subca];
1260 createTrust(certs);
1261 evalTrustExpectingError(errSecVerifyActionFailed, "partial matching org leaf succeeded");
1262
1263 /* Verify that a non-CT cert with non-matching Org fails */
1264 certs = @[ (__bridge id)server_no_match, (__bridge id)subca];
1265 createTrust(certs);
1266 evalTrustExpectingError(errSecVerifyActionFailed, "non-matching org leaf succeeded");
1267
1268 /* Verify that a non-CT cert with no Org fails */
1269 certs = @[ (__bridge id)server_no_org, (__bridge id)subca];
1270 createTrust(certs);
1271 evalTrustExpectingError(errSecVerifyActionFailed, "no org leaf succeeded");
1272
1273 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1274
1275 #undef createTrust
1276
1277 errOut:
1278 CFReleaseNull(root);
1279 CFReleaseNull(subca);
1280 CFReleaseNull(server_matching);
1281 CFReleaseNull(server_matching_with_CT);
1282 CFReleaseNull(server_partial);
1283 CFReleaseNull(server_no_match);
1284 CFReleaseNull(server_no_org);
1285 CFReleaseNull(trustedLogs);
1286 CFReleaseNull(trust);
1287 CFReleaseNull(policy);
1288 CFReleaseNull(error);
1289 }
1290
1291 static void test_ct_constrained_ca_exceptions(void) {
1292 SecCertificateRef root = NULL, org_constrained_subca = NULL;
1293 SecCertificateRef constraint_pass_server = NULL, constraint_pass_server_ct = NULL, constraint_fail_server = NULL;
1294 SecCertificateRef dn_constrained_subca = NULL, dn_constrained_server = NULL, dn_constrained_server_mismatch = NULL;
1295 SecCertificateRef dns_constrained_subca = NULL, dns_constrained_server = NULL, dns_constrained_server_mismatch = NULL;
1296 CFArrayRef trustedLogs = CTTestsCopyTrustedLogs();
1297 SecTrustRef trust = NULL;
1298 SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("ct.test.apple.com"));
1299 NSArray *anchors = nil, *certs = nil;
1300 NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT
1301 CFErrorRef error = nil;
1302 NSDictionary *caException = nil, *exceptions = nil;
1303 NSMutableArray *caExceptions = [NSMutableArray array];
1304 NSData *caHash = nil;
1305
1306 require_action(root = SecCertificateCreateFromResource(@"enforcement_system_root"),
1307 errOut, fail("failed to create system root"));
1308 require_action(org_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_subca"),
1309 errOut, fail("failed to create org-constrained subca"));
1310 require_action(constraint_pass_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_server"),
1311 errOut, fail("failed to create constrained non-CT leaf"));
1312 require_action(constraint_pass_server_ct = SecCertificateCreateFromResource(@"enforcement_system_constrained_server_scts"),
1313 errOut, fail("failed to create constrained CT leaf"));
1314 require_action(constraint_fail_server= SecCertificateCreateFromResource(@"enforcement_system_constrained_fail_server"),
1315 errOut, fail("failed to create constraint failure leaf"));
1316 require_action(dn_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_subca"),
1317 errOut, fail("failed to create dn-constrained subca"));
1318 require_action(dn_constrained_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_server"),
1319 errOut, fail("failed to create dn-constrained leaf"));
1320 require_action(dn_constrained_server_mismatch = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_org_server_mismatch"),
1321 errOut, fail("failed to create dn-constrained leaf with mismatched orgs"));
1322 require_action(dns_constrained_subca = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_subca"),
1323 errOut, fail("failed to create dns-constrained subca"));
1324 require_action(dns_constrained_server = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_server"),
1325 errOut, fail("failed to create dns-constrained leaf"));
1326 require_action(dns_constrained_server_mismatch = SecCertificateCreateFromResource(@"enforcement_system_constrained_no_dn_server_mismatch"),
1327 errOut, fail("failed to create dns-constrained leaf with mismatched orgs"));
1328
1329 anchors = @[ (__bridge id)root ];
1330
1331 /* Set exception on the subCAs */
1332 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(org_constrained_subca));
1333 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1334 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1335 };
1336 [caExceptions addObject:caException];
1337
1338 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dn_constrained_subca));
1339 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1340 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1341 };
1342 [caExceptions addObject:caException];
1343
1344 caHash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(dns_constrained_subca));
1345 caException = @{ (__bridge NSString*)kSecCTExceptionsHashAlgorithmKey : @"sha256",
1346 (__bridge NSString*)kSecCTExceptionsSPKIHashKey : caHash,
1347 };
1348 [caExceptions addObject:caException];
1349 exceptions = @{ (__bridge NSString*)kSecCTExceptionsCAsKey : caExceptions };
1350 ok(SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)exceptions, &error),
1351 "failed to set exceptions: %@", error);
1352
1353 #define createTrust(certs) \
1354 CFReleaseNull(trust); \
1355 require_noerr_action(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), errOut, fail("failed to create trust")); \
1356 require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("failed to set anchors")); \
1357 require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); \
1358 require_noerr_action(SecTrustSetTrustedLogs(trust, trustedLogs), errOut, fail("failed to set trusted logs"));
1359
1360 /* Verify org-constrained non-CT leaf passes */
1361 certs = @[ (__bridge id)constraint_pass_server, (__bridge id)org_constrained_subca ];
1362 createTrust(certs);
1363 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1364
1365 /* Verify org-constrained CT leaf passes */
1366 certs = @[ (__bridge id)constraint_pass_server_ct, (__bridge id)org_constrained_subca ];
1367 createTrust(certs);
1368 is(SecTrustEvaluateWithError(trust, &error), true, "org constrained exception did not apply: %@", error);
1369
1370 /* Verify org-constrained non-CT leaf with wrong org fails */
1371 certs = @[ (__bridge id)constraint_fail_server, (__bridge id)org_constrained_subca ];
1372 createTrust(certs);
1373 evalTrustExpectingError(errSecInvalidName, "leaf failing name constraints succeeded");
1374
1375 /* Verify dn-constrained (but not with org) non-CT leaf with matching orgs succeeds */
1376 certs = @[ (__bridge id)dn_constrained_server, (__bridge id)dn_constrained_subca ];
1377 createTrust(certs);
1378 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1379
1380 /* Verify dn-constrained (but not with org) non-CT leaf without matching orgs fails */
1381 certs = @[ (__bridge id)dn_constrained_server_mismatch, (__bridge id)dn_constrained_subca ];
1382 createTrust(certs);
1383 evalTrustExpectingError(errSecVerifyActionFailed, "dn name constraints with no org succeeded");
1384
1385 /* Verify dns-constrained (no DN constraints) non-CT leaf with matching orgs succeeds */
1386 certs = @[ (__bridge id)dns_constrained_server, (__bridge id)dns_constrained_subca ];
1387 createTrust(certs);
1388 is(SecTrustEvaluateWithError(trust, &error), true, "org match exception did not apply: %@", error);
1389
1390 /* Verify dns-constrained (no DN constraints) non-CT leaf without matching orgs fails*/
1391 certs = @[ (__bridge id)dns_constrained_server_mismatch, (__bridge id)dns_constrained_subca ];
1392 createTrust(certs);
1393 evalTrustExpectingError(errSecVerifyActionFailed, "dns name constraints with no DN constraint succeeded");
1394
1395 ok(SecTrustStoreSetCTExceptions(NULL, NULL, &error), "failed to reset exceptions: %@", error);
1396
1397 #undef createTrust
1398
1399 errOut:
1400 CFReleaseNull(root);
1401 CFReleaseNull(org_constrained_subca);
1402 CFReleaseNull(constraint_pass_server);
1403 CFReleaseNull(constraint_pass_server_ct);
1404 CFReleaseNull(constraint_fail_server);
1405 CFReleaseNull(dn_constrained_subca);
1406 CFReleaseNull(dn_constrained_server);
1407 CFReleaseNull(dn_constrained_server_mismatch);
1408 CFReleaseNull(dns_constrained_subca);
1409 CFReleaseNull(dns_constrained_server);
1410 CFReleaseNull(dns_constrained_server_mismatch);
1411 CFReleaseNull(trustedLogs);
1412 CFReleaseNull(trust);
1413 CFReleaseNull(policy);
1414 CFReleaseNull(error);
1415 }
1416
1417 static void test_ct_key_exceptions(void) {
1418 test_ct_leaf_exceptions();
1419 test_ct_unconstrained_ca_exceptions();
1420 test_ct_constrained_ca_exceptions();
1421 }
1422
1423 static void test_ct_exceptions(void) {
1424 test_ct_domain_exceptions();
1425 test_ct_key_exceptions();
1426 }
1427
1428 int si_82_sectrust_ct(int argc, char *const *argv)
1429 {
1430 plan_tests(433);
1431
1432 tests();
1433 test_sct_serialization();
1434 testSetCTExceptions();
1435 test_enforcement();
1436 test_apple_enforcement_exceptions();
1437 test_google_enforcement_exception();
1438 test_precerts_fail();
1439 test_ct_exceptions();
1440
1441 return 0;
1442 }