5 * Copyright (c) 2014 Apple Inc. All Rights Reserved.
9 #include <CoreFoundation/CoreFoundation.h>
10 #include <Security/SecCertificatePriv.h>
11 #include <Security/SecTrustPriv.h>
12 #include <Security/SecPolicy.h>
15 #include <utilities/SecCFWrappers.h>
17 #include "shared_regressions.h"
19 //define this if you want to print clock time of SecTrustEvaluate call.
20 //define PRINT_SECTRUST_EVALUATE_TIME
22 static bool isCFTrue(CFTypeRef cf)
24 return (cf == kCFBooleanTrue);
27 static void test_ct_trust(CFArrayRef certs, CFArrayRef scts, CFTypeRef ocspresponses, CFArrayRef anchors,
28 CFArrayRef trustedLogs, CFStringRef hostname, CFDateRef date,
29 bool ct_expected, bool ev_expected, bool ct_whitelist_expected,
30 const char *test_name)
32 CFArrayRef policies=NULL;
33 SecPolicyRef policy=NULL;
34 SecTrustRef trust=NULL;
35 SecTrustResultType trustResult;
36 CFDictionaryRef results=NULL;
37 CFArrayRef properties=NULL;
41 isnt(policy = SecPolicyCreateSSL(false, hostname), NULL, "create policy");
42 isnt(policies = CFArrayCreate(kCFAllocatorDefault, (const void **)&policy, 1, &kCFTypeArrayCallBacks), NULL, "create policies");
43 ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust");
45 assert(trust); // silence analyzer
47 ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors");
51 ok_status(SecTrustSetSignedCertificateTimestamps(trust, scts), "set standalone SCTs");;
55 ok_status(SecTrustSetTrustedLogs(trust, trustedLogs), "set trusted logs");
59 ok_status(SecTrustSetOCSPResponse(trust, ocspresponses), "set ocsp responses");
62 if (!date) { goto errOut; }
63 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
64 #ifdef PRINT_SECTRUST_EVALUATE_TIME
67 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
68 #ifdef PRINT_SECTRUST_EVALUATE_TIME
69 clock_t t1 = clock() - t0;
71 ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)",
74 results = SecTrustCopyResult(trust);
76 CFTypeRef ct = CFDictionaryGetValue(results, kSecTrustCertificateTransparency);
77 CFTypeRef ev = CFDictionaryGetValue(results, kSecTrustExtendedValidation);
78 CFTypeRef ct_whitelist = CFDictionaryGetValue(results, kSecTrustCertificateTransparencyWhiteList);
81 ok((isCFTrue(ct) == ct_expected), "unexpected CT result (%s)", test_name);
82 ok((isCFTrue(ev) == ev_expected), "unexpected EV result (%s)", test_name);
83 ok((isCFTrue(ct_whitelist) == ct_whitelist_expected), "unexpected CT WhiteList result (%s)", test_name);
84 /* Note that the CT whitelist has been removed due to the expiration of all contents. */
86 #ifdef PRINT_SECTRUST_EVALUATE_TIME
87 printf("%s: %lu\n", test_name, t1);
90 properties = SecTrustCopyProperties(trust);
93 CFReleaseSafe(policy);
94 CFReleaseSafe(policies);
96 CFReleaseSafe(results);
97 CFReleaseSafe(properties);
100 #import <Foundation/Foundation.h>
103 SecCertificateRef SecCertificateCreateFromResource(NSString *name)
105 NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".crt" subdirectory:@"si-82-sectrust-ct-data"];
107 NSData *certData = [NSData dataWithContentsOfURL:url];
109 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData);
115 CFDataRef CFDataCreateFromResource(NSString *name)
117 NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".bin" subdirectory:@"si-82-sectrust-ct-data"];
119 NSData *binData = [[NSData alloc] initWithContentsOfURL:url];
121 return (__bridge_retained CFDataRef) binData;
126 SecCertificateRef certA=NULL, certD=NULL, certF=NULL, certCA_alpha=NULL, certCA_beta=NULL;
127 CFDataRef proofD=NULL, proofA_1=NULL, proofA_2=NULL;
128 SecCertificateRef www_digicert_com_2015_cert=NULL, www_digicert_com_2016_cert=NULL, digicert_sha2_ev_server_ca=NULL;
129 SecCertificateRef www_paypal_com_cert=NULL, www_paypal_com_issuer_cert=NULL;
130 SecCertificateRef pilot_cert_3055998=NULL, pilot_cert_3055998_issuer=NULL;
131 SecCertificateRef whitelist_00008013=NULL, whitelist_5555bc4f=NULL, whitelist_aaaae152=NULL, whitelist_fff9b5f6=NULL;
132 SecCertificateRef whitelist_00008013_issuer=NULL, whitelist_5555bc4f_issuer=NULL, whitelist_fff9b5f6_issuer=NULL;
133 SecCertificateRef cfCert = NULL;
134 CFMutableArrayRef certs=NULL;
135 CFMutableArrayRef scts=NULL;
136 CFMutableArrayRef anchors=NULL;
137 CFDataRef valid_ocsp=NULL;
138 CFDataRef invalid_ocsp=NULL;
139 CFDataRef bad_hash_ocsp=NULL;
141 CFArrayRef trustedLogs=NULL;
142 CFURLRef trustedLogsURL=NULL;
144 trustedLogsURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
147 CFSTR("si-82-sectrust-ct-data"));
148 isnt(trustedLogsURL, NULL, "trustedLogsURL");
149 trustedLogs = (CFArrayRef) CFPropertyListReadFromFile(trustedLogsURL);
150 isnt(trustedLogs, NULL, "trustedLogs");
152 isnt(certCA_alpha = SecCertificateCreateFromResource(@"CA_alpha"), NULL, "create ca-alpha cert");
153 isnt(certCA_beta = SecCertificateCreateFromResource(@"CA_beta"), NULL, "create ca-beta cert");
154 isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array");
155 CFArrayAppendValue(anchors, certCA_alpha);
156 CFArrayAppendValue(anchors, certCA_beta);
157 isnt(certA = SecCertificateCreateFromResource(@"serverA"), NULL, "create certA");
158 isnt(certD = SecCertificateCreateFromResource(@"serverD"), NULL, "create certD");
159 isnt(certF = SecCertificateCreateFromResource(@"serverF"), NULL, "create certF");
160 isnt(proofD = CFDataCreateFromResource(@"serverD_proof"), NULL, "creat proofD");
161 isnt(proofA_1 = CFDataCreateFromResource(@"serverA_proof_Alfa_3"), NULL, "creat proofA_1");
162 isnt(proofA_2 = CFDataCreateFromResource(@"serverA_proof_Bravo_3"), NULL, "creat proofA_2");
163 isnt(www_digicert_com_2015_cert = SecCertificateCreateFromResource(@"www_digicert_com_2015"), NULL, "create www.digicert.com 2015 cert");
164 isnt(www_digicert_com_2016_cert = SecCertificateCreateFromResource(@"www_digicert_com_2016"), NULL, "create www.digicert.com 2016 cert");
165 isnt(digicert_sha2_ev_server_ca = SecCertificateCreateFromResource(@"digicert_sha2_ev_server_ca"), NULL, "create digicert.com subCA cert");
166 isnt(www_paypal_com_cert = SecCertificateCreateFromResource(@"www_paypal_com"), NULL, "create www.paypal.com cert");
167 isnt(www_paypal_com_issuer_cert = SecCertificateCreateFromResource(@"www_paypal_com_issuer"), NULL, "create www.paypal.com issuer cert");
168 isnt(valid_ocsp = CFDataCreateFromResource(@"valid_ocsp_response"), NULL, "create valid_ocsp");
169 isnt(invalid_ocsp = CFDataCreateFromResource(@"invalid_ocsp_response"), NULL, "create invalid_ocsp");
170 isnt(bad_hash_ocsp = CFDataCreateFromResource(@"bad_hash_ocsp_response"), NULL, "create bad_hash_ocsp");
171 isnt(pilot_cert_3055998 = SecCertificateCreateFromResource(@"pilot_3055998"), NULL, "create pilot_cert_3055998 cert");
172 isnt(pilot_cert_3055998_issuer = SecCertificateCreateFromResource(@"pilot_3055998_issuer"), NULL, "create pilot_cert_3055998 issuer cert");
174 isnt(whitelist_00008013 = SecCertificateCreateFromResource(@"whitelist_00008013"), NULL, "create whitelist_00008013 cert");
175 isnt(whitelist_5555bc4f = SecCertificateCreateFromResource(@"whitelist_5555bc4f"), NULL, "create whitelist_5555bc4f cert");
176 isnt(whitelist_aaaae152 = SecCertificateCreateFromResource(@"whitelist_aaaae152"), NULL, "create whitelist_aaaae152 cert");
177 isnt(whitelist_fff9b5f6 = SecCertificateCreateFromResource(@"whitelist_fff9b5f6"), NULL, "create whitelist_fff9b5f6 cert");
178 isnt(whitelist_00008013_issuer = SecCertificateCreateFromResource(@"whitelist_00008013_issuer"), NULL, "create whitelist_00008013_issuer cert");
179 isnt(whitelist_5555bc4f_issuer = SecCertificateCreateFromResource(@"whitelist_5555bc4f_issuer"), NULL, "create whitelist_5555bc4f_issuer cert");
180 isnt(whitelist_fff9b5f6_issuer = SecCertificateCreateFromResource(@"whitelist_fff9b5f6_issuer"), NULL, "create whitelist_fff9b5f6_issuer cert");
182 CFCalendarRef cal = NULL;
184 CFDateRef date_20150307 = NULL; // Date for older set of tests.
185 CFDateRef date_20160422 = NULL; // Date for newer set of tests.
187 isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar");
188 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2015, 3, 7), "create verify absolute time 20150307");
189 isnt(date_20150307 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20150307");
190 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2016, 4, 22), "create verify absolute time 20160422");
191 isnt(date_20160422 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20160422");
194 /* Case 1: coreos-ct-test embedded SCT - only 1 SCT - so not CT qualified */
195 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
196 CFArrayAppendValue(certs, certF);
197 test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
198 false, false, false, "coreos-ct-test 1");
199 CFReleaseNull(certs);
201 /* Case 2: coreos-ct-test standalone SCT - only 1 SCT - so not CT qualified */
202 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
203 CFArrayAppendValue(certs, certD);
204 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
205 CFArrayAppendValue(scts, proofD);
206 test_ct_trust(certs, scts, NULL, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
207 false, false, false, "coreos-ct-test 2");
208 CFReleaseNull(certs);
211 /* case 3: digicert : 2 embedded SCTs, but lifetime of cert is 24 month, so not CT qualified */
212 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
213 CFArrayAppendValue(certs, www_digicert_com_2015_cert);
214 CFArrayAppendValue(certs, digicert_sha2_ev_server_ca);
215 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.digicert.com"), date_20150307,
216 false, false, false, "digicert 2015");
217 CFReleaseNull(certs);
219 /* case 4: paypal.com cert - not CT, but EV */
220 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
221 CFArrayAppendValue(certs, www_paypal_com_cert);
222 CFArrayAppendValue(certs, www_paypal_com_issuer_cert);
223 test_ct_trust(certs, NULL, NULL, NULL, trustedLogs, CFSTR("www.paypal.com"), date_20150307,
224 false, false, false, "paypal");
225 CFReleaseNull(certs);
227 /* Case 5: coreos-ct-test standalone SCT - 2 SCTs - CT qualified */
228 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
229 CFArrayAppendValue(certs, certA);
230 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
231 CFArrayAppendValue(scts, proofA_1);
232 CFArrayAppendValue(scts, proofA_2);
233 test_ct_trust(certs, scts, NULL, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
234 true, false, false, "coreos-ct-test 3");
235 CFReleaseNull(certs);
239 /* Case 6: Test with an invalid OCSP response */
240 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
241 CFArrayAppendValue(certs, certA);
242 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
243 CFArrayAppendValue(scts, proofA_1);
244 test_ct_trust(certs, scts, invalid_ocsp, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
245 false, false, false, "coreos-ct-test 4");
246 CFReleaseNull(certs);
249 /* Case 7: Test with a valid OCSP response */
250 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
251 CFArrayAppendValue(certs, certA);
252 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
253 CFArrayAppendValue(scts, proofA_1);
254 test_ct_trust(certs, scts, valid_ocsp, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
255 false, false, false, "coreos-ct-test 5");
256 CFReleaseNull(certs);
259 /* Case 8: Test with a bad hash OCSP response */
260 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
261 CFArrayAppendValue(certs, certA);
262 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
263 CFArrayAppendValue(scts, proofA_1);
264 test_ct_trust(certs, scts, bad_hash_ocsp, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
265 false, false, false, "coreos-ct-test 6");
266 CFReleaseNull(certs);
269 /* Case 9: Previously WhiteListed EV cert (expired in Feb 2016, so not on final whitelist)*/
270 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
271 CFArrayAppendValue(certs, pilot_cert_3055998);
272 CFArrayAppendValue(certs, pilot_cert_3055998_issuer);
273 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.ssbwingate.com"), date_20150307,
274 false, false, false, "previously whitelisted cert");
275 CFReleaseNull(certs);
277 /* Case 10-13: WhiteListed EV cert */
278 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
279 CFArrayAppendValue(certs, whitelist_00008013);
280 CFArrayAppendValue(certs, whitelist_00008013_issuer);
281 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("clava.com"), date_20150307,
282 false, false, false, "whitelisted cert 00008013");
283 CFReleaseNull(certs);
285 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
286 CFArrayAppendValue(certs, whitelist_5555bc4f);
287 CFArrayAppendValue(certs, whitelist_5555bc4f_issuer);
288 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("lanai.dartmouth.edu"),
289 date_20150307, false, false, false, "whitelisted cert 5555bc4f");
290 CFReleaseNull(certs);
292 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
293 CFArrayAppendValue(certs, whitelist_aaaae152);
294 CFArrayAppendValue(certs, whitelist_5555bc4f_issuer); // Same issuer (Go Daddy) as above
295 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.falymusic.com"),
296 date_20150307, false, false, false, "whitelisted cert aaaae152");
297 CFReleaseNull(certs);
299 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
300 CFArrayAppendValue(certs, whitelist_fff9b5f6);
301 CFArrayAppendValue(certs, whitelist_fff9b5f6_issuer);
302 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.defencehealth.com.au"),
303 date_20150307, false, false, false, "whitelisted cert fff9b5f6");
304 CFReleaseNull(certs);
307 /* case 14: Current (April 2016) www.digicert.com cert: 3 embedded SCTs, CT qualified */
308 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
309 CFArrayAppendValue(certs, www_digicert_com_2016_cert);
310 CFArrayAppendValue(certs, digicert_sha2_ev_server_ca);
311 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.digicert.com"), date_20160422,
312 true, true, false, "digicert 2016");
313 CFReleaseNull(certs);
317 #define TEST_CASE(x) \
319 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array for " #x); \
320 isnt(cfCert = SecCertificateCreateFromResource(@#x), NULL, "create cfCert from " #x); \
321 CFArrayAppendValue(certs, cfCert); \
322 test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307, true, false, false, #x); \
323 CFReleaseNull(certs); \
324 CFReleaseNull(cfCert); \
328 TEST_CASE(server_1601);
329 TEST_CASE(server_1603);
330 TEST_CASE(server_1604);
331 TEST_CASE(server_1701);
332 TEST_CASE(server_1704);
333 TEST_CASE(server_1705);
334 TEST_CASE(server_1801);
335 TEST_CASE(server_1804);
336 TEST_CASE(server_1805);
337 TEST_CASE(server_2001);
340 CFReleaseSafe(certCA_alpha);
341 CFReleaseSafe(certCA_beta);
342 CFReleaseSafe(anchors);
343 CFReleaseSafe(certA);
344 CFReleaseSafe(certD);
345 CFReleaseSafe(certF);
346 CFReleaseSafe(proofD);
347 CFReleaseSafe(proofA_1);
348 CFReleaseSafe(proofA_2);
349 CFReleaseSafe(www_digicert_com_2015_cert);
350 CFReleaseSafe(www_digicert_com_2016_cert);
351 CFReleaseSafe(digicert_sha2_ev_server_ca);
352 CFReleaseSafe(www_paypal_com_cert);
353 CFReleaseSafe(www_paypal_com_issuer_cert);
354 CFReleaseSafe(pilot_cert_3055998);
355 CFReleaseSafe(pilot_cert_3055998_issuer);
356 CFReleaseSafe(whitelist_00008013);
357 CFReleaseSafe(whitelist_5555bc4f);
358 CFReleaseSafe(whitelist_aaaae152);
359 CFReleaseSafe(whitelist_fff9b5f6);
360 CFReleaseSafe(whitelist_00008013_issuer);
361 CFReleaseSafe(whitelist_5555bc4f_issuer);
362 CFReleaseSafe(whitelist_fff9b5f6_issuer);
363 CFReleaseSafe(trustedLogsURL);
364 CFReleaseSafe(trustedLogs);
365 CFReleaseSafe(valid_ocsp);
366 CFReleaseSafe(invalid_ocsp);
367 CFReleaseSafe(bad_hash_ocsp);
369 CFReleaseSafe(date_20150307);
370 CFReleaseSafe(date_20160422);
375 int si_82_sectrust_ct(int argc, char *const *argv)