]>
Commit | Line | Data |
---|---|---|
fa7225c8 A |
1 | /* |
2 | * si-82-sectrust-ct.c | |
3 | * Security | |
4 | * | |
5 | * Copyright (c) 2014 Apple Inc. All Rights Reserved. | |
6 | * | |
7 | */ | |
8 | ||
7512f6be | 9 | #include <AssertMacros.h> |
fa7225c8 A |
10 | #include <CoreFoundation/CoreFoundation.h> |
11 | #include <Security/SecCertificatePriv.h> | |
12 | #include <Security/SecTrustPriv.h> | |
7512f6be | 13 | #include <Security/SecPolicyPriv.h> |
fa7225c8 A |
14 | #include <stdlib.h> |
15 | #include <unistd.h> | |
16 | #include <utilities/SecCFWrappers.h> | |
7512f6be A |
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 | |
fa7225c8 A |
26 | |
27 | #include "shared_regressions.h" | |
7512f6be | 28 | #include "si-82-sectrust-ct.h" |
fa7225c8 A |
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 | ||
79b9da22 | 52 | isnt(policy = SecPolicyCreateSSL(true, hostname), NULL, "create policy"); |
fa7225c8 A |
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) { | |
7512f6be A |
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 | |
fa7225c8 A |
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); | |
866f8763 | 98 | /* Note that the CT whitelist has been removed due to the expiration of all contents. */ |
fa7225c8 A |
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 | { | |
79b9da22 | 119 | NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".cer" subdirectory:@"si-82-sectrust-ct-data"]; |
fa7225c8 A |
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 | ||
7512f6be A |
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 | ||
fa7225c8 A |
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 | ||
7512f6be | 171 | CFArrayRef trustedLogs= CTTestsCopyTrustedLogs(); |
fa7225c8 A |
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); | |
79b9da22 | 218 | test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, NULL, date_20150307, |
fa7225c8 A |
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); | |
79b9da22 | 227 | test_ct_trust(certs, scts, NULL, anchors, trustedLogs, NULL, date_20150307, |
fa7225c8 A |
228 | false, false, false, "coreos-ct-test 2"); |
229 | CFReleaseNull(certs); | |
230 | CFReleaseNull(scts); | |
231 | ||
866f8763 | 232 | /* case 3: digicert : 2 embedded SCTs, but lifetime of cert is 24 month, so not CT qualified */ |
fa7225c8 A |
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, | |
866f8763 | 237 | false, false, false, "digicert 2015"); |
fa7225c8 A |
238 | CFReleaseNull(certs); |
239 | ||
79b9da22 | 240 | /* Case 4: coreos-ct-test standalone SCT - 2 SCTs - CT qualified */ |
fa7225c8 A |
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); | |
79b9da22 | 246 | test_ct_trust(certs, scts, NULL, anchors, trustedLogs, NULL, date_20150307, |
fa7225c8 A |
247 | true, false, false, "coreos-ct-test 3"); |
248 | CFReleaseNull(certs); | |
249 | CFReleaseNull(scts); | |
250 | ||
79b9da22 | 251 | /* Case 5: Test with an invalid OCSP response */ |
fa7225c8 A |
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); | |
79b9da22 | 256 | test_ct_trust(certs, scts, invalid_ocsp, anchors, trustedLogs, NULL, date_20150307, |
fa7225c8 A |
257 | false, false, false, "coreos-ct-test 4"); |
258 | CFReleaseNull(certs); | |
259 | CFReleaseNull(scts); | |
260 | ||
79b9da22 | 261 | /* Case 6: Test with a valid OCSP response */ |
fa7225c8 A |
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); | |
79b9da22 | 266 | test_ct_trust(certs, scts, valid_ocsp, anchors, trustedLogs, NULL, date_20150307, |
fa7225c8 A |
267 | false, false, false, "coreos-ct-test 5"); |
268 | CFReleaseNull(certs); | |
269 | CFReleaseNull(scts); | |
270 | ||
79b9da22 | 271 | /* Case 7: Test with a bad hash OCSP response */ |
fa7225c8 A |
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); | |
79b9da22 | 276 | test_ct_trust(certs, scts, bad_hash_ocsp, anchors, trustedLogs, NULL, date_20150307, |
fa7225c8 A |
277 | false, false, false, "coreos-ct-test 6"); |
278 | CFReleaseNull(certs); | |
279 | CFReleaseNull(scts); | |
280 | ||
79b9da22 | 281 | /* case 8: Current (April 2016) www.digicert.com cert: 3 embedded SCTs, CT qualified */ |
fa7225c8 A |
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); \ | |
79b9da22 | 296 | test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, NULL, date_20150307, true, false, false, #x); \ |
fa7225c8 A |
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); | |
fa7225c8 A |
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 | ||
7512f6be A |
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 | } | |
fa7225c8 A |
1421 | |
1422 | int si_82_sectrust_ct(int argc, char *const *argv) | |
1423 | { | |
7512f6be | 1424 | plan_tests(432); |
fa7225c8 A |
1425 | |
1426 | tests(); | |
7512f6be A |
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(); | |
fa7225c8 A |
1434 | |
1435 | return 0; | |
1436 | } |