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);
85 #ifdef PRINT_SECTRUST_EVALUATE_TIME
86 printf("%s: %lu\n", test_name, t1);
89 properties = SecTrustCopyProperties(trust);
92 CFReleaseSafe(policy);
93 CFReleaseSafe(policies);
95 CFReleaseSafe(results);
96 CFReleaseSafe(properties);
99 #import <Foundation/Foundation.h>
102 SecCertificateRef SecCertificateCreateFromResource(NSString *name)
104 NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".crt" subdirectory:@"si-82-sectrust-ct-data"];
106 NSData *certData = [NSData dataWithContentsOfURL:url];
108 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData);
114 CFDataRef CFDataCreateFromResource(NSString *name)
116 NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".bin" subdirectory:@"si-82-sectrust-ct-data"];
118 NSData *binData = [[NSData alloc] initWithContentsOfURL:url];
120 return (__bridge_retained CFDataRef) binData;
125 SecCertificateRef certA=NULL, certD=NULL, certF=NULL, certCA_alpha=NULL, certCA_beta=NULL;
126 CFDataRef proofD=NULL, proofA_1=NULL, proofA_2=NULL;
127 SecCertificateRef www_digicert_com_2015_cert=NULL, www_digicert_com_2016_cert=NULL, digicert_sha2_ev_server_ca=NULL;
128 SecCertificateRef www_paypal_com_cert=NULL, www_paypal_com_issuer_cert=NULL;
129 SecCertificateRef pilot_cert_3055998=NULL, pilot_cert_3055998_issuer=NULL;
130 SecCertificateRef whitelist_00008013=NULL, whitelist_5555bc4f=NULL, whitelist_aaaae152=NULL, whitelist_fff9b5f6=NULL;
131 SecCertificateRef whitelist_00008013_issuer=NULL, whitelist_5555bc4f_issuer=NULL, whitelist_fff9b5f6_issuer=NULL;
132 SecCertificateRef cfCert = NULL;
133 CFMutableArrayRef certs=NULL;
134 CFMutableArrayRef scts=NULL;
135 CFMutableArrayRef anchors=NULL;
136 CFDataRef valid_ocsp=NULL;
137 CFDataRef invalid_ocsp=NULL;
138 CFDataRef bad_hash_ocsp=NULL;
140 CFArrayRef trustedLogs=NULL;
141 CFURLRef trustedLogsURL=NULL;
143 trustedLogsURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
146 CFSTR("si-82-sectrust-ct-data"));
147 isnt(trustedLogsURL, NULL, "trustedLogsURL");
148 trustedLogs = (CFArrayRef) CFPropertyListReadFromFile(trustedLogsURL);
149 isnt(trustedLogs, NULL, "trustedLogs");
151 isnt(certCA_alpha = SecCertificateCreateFromResource(@"CA_alpha"), NULL, "create ca-alpha cert");
152 isnt(certCA_beta = SecCertificateCreateFromResource(@"CA_beta"), NULL, "create ca-beta cert");
153 isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array");
154 CFArrayAppendValue(anchors, certCA_alpha);
155 CFArrayAppendValue(anchors, certCA_beta);
156 isnt(certA = SecCertificateCreateFromResource(@"serverA"), NULL, "create certA");
157 isnt(certD = SecCertificateCreateFromResource(@"serverD"), NULL, "create certD");
158 isnt(certF = SecCertificateCreateFromResource(@"serverF"), NULL, "create certF");
159 isnt(proofD = CFDataCreateFromResource(@"serverD_proof"), NULL, "creat proofD");
160 isnt(proofA_1 = CFDataCreateFromResource(@"serverA_proof_Alfa_3"), NULL, "creat proofA_1");
161 isnt(proofA_2 = CFDataCreateFromResource(@"serverA_proof_Bravo_3"), NULL, "creat proofA_2");
162 isnt(www_digicert_com_2015_cert = SecCertificateCreateFromResource(@"www_digicert_com_2015"), NULL, "create www.digicert.com 2015 cert");
163 isnt(www_digicert_com_2016_cert = SecCertificateCreateFromResource(@"www_digicert_com_2016"), NULL, "create www.digicert.com 2016 cert");
164 isnt(digicert_sha2_ev_server_ca = SecCertificateCreateFromResource(@"digicert_sha2_ev_server_ca"), NULL, "create digicert.com subCA cert");
165 isnt(www_paypal_com_cert = SecCertificateCreateFromResource(@"www_paypal_com"), NULL, "create www.paypal.com cert");
166 isnt(www_paypal_com_issuer_cert = SecCertificateCreateFromResource(@"www_paypal_com_issuer"), NULL, "create www.paypal.com issuer cert");
167 isnt(valid_ocsp = CFDataCreateFromResource(@"valid_ocsp_response"), NULL, "create valid_ocsp");
168 isnt(invalid_ocsp = CFDataCreateFromResource(@"invalid_ocsp_response"), NULL, "create invalid_ocsp");
169 isnt(bad_hash_ocsp = CFDataCreateFromResource(@"bad_hash_ocsp_response"), NULL, "create bad_hash_ocsp");
170 isnt(pilot_cert_3055998 = SecCertificateCreateFromResource(@"pilot_3055998"), NULL, "create pilot_cert_3055998 cert");
171 isnt(pilot_cert_3055998_issuer = SecCertificateCreateFromResource(@"pilot_3055998_issuer"), NULL, "create pilot_cert_3055998 issuer cert");
173 isnt(whitelist_00008013 = SecCertificateCreateFromResource(@"whitelist_00008013"), NULL, "create whitelist_00008013 cert");
174 isnt(whitelist_5555bc4f = SecCertificateCreateFromResource(@"whitelist_5555bc4f"), NULL, "create whitelist_5555bc4f cert");
175 isnt(whitelist_aaaae152 = SecCertificateCreateFromResource(@"whitelist_aaaae152"), NULL, "create whitelist_aaaae152 cert");
176 isnt(whitelist_fff9b5f6 = SecCertificateCreateFromResource(@"whitelist_fff9b5f6"), NULL, "create whitelist_fff9b5f6 cert");
177 isnt(whitelist_00008013_issuer = SecCertificateCreateFromResource(@"whitelist_00008013_issuer"), NULL, "create whitelist_00008013_issuer cert");
178 isnt(whitelist_5555bc4f_issuer = SecCertificateCreateFromResource(@"whitelist_5555bc4f_issuer"), NULL, "create whitelist_5555bc4f_issuer cert");
179 isnt(whitelist_fff9b5f6_issuer = SecCertificateCreateFromResource(@"whitelist_fff9b5f6_issuer"), NULL, "create whitelist_fff9b5f6_issuer cert");
181 CFCalendarRef cal = NULL;
183 CFDateRef date_20150307 = NULL; // Date for older set of tests.
184 CFDateRef date_20160422 = NULL; // Date for newer set of tests.
186 isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar");
187 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2015, 3, 7), "create verify absolute time 20150307");
188 isnt(date_20150307 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20150307");
189 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2016, 4, 22), "create verify absolute time 20160422");
190 isnt(date_20160422 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20160422");
193 /* Case 1: coreos-ct-test embedded SCT - only 1 SCT - so not CT qualified */
194 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
195 CFArrayAppendValue(certs, certF);
196 test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
197 false, false, false, "coreos-ct-test 1");
198 CFReleaseNull(certs);
200 /* Case 2: coreos-ct-test standalone SCT - only 1 SCT - so not CT qualified */
201 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
202 CFArrayAppendValue(certs, certD);
203 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
204 CFArrayAppendValue(scts, proofD);
205 test_ct_trust(certs, scts, NULL, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
206 false, false, false, "coreos-ct-test 2");
207 CFReleaseNull(certs);
210 /* case 3: digicert : 2 embedded SCTs, but lifetime of cert is 24 month, so not CT qualified, but is whitelisted */
211 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
212 CFArrayAppendValue(certs, www_digicert_com_2015_cert);
213 CFArrayAppendValue(certs, digicert_sha2_ev_server_ca);
214 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.digicert.com"), date_20150307,
215 false, true, true, "digicert 2015");
216 CFReleaseNull(certs);
218 /* case 4: paypal.com cert - not CT, but EV */
219 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
220 CFArrayAppendValue(certs, www_paypal_com_cert);
221 CFArrayAppendValue(certs, www_paypal_com_issuer_cert);
222 test_ct_trust(certs, NULL, NULL, NULL, trustedLogs, CFSTR("www.paypal.com"), date_20150307,
223 false, true, false, "paypal");
224 CFReleaseNull(certs);
226 /* Case 5: coreos-ct-test standalone SCT - 2 SCTs - CT qualified */
227 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
228 CFArrayAppendValue(certs, certA);
229 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
230 CFArrayAppendValue(scts, proofA_1);
231 CFArrayAppendValue(scts, proofA_2);
232 test_ct_trust(certs, scts, NULL, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
233 true, false, false, "coreos-ct-test 3");
234 CFReleaseNull(certs);
238 /* Case 6: Test with an invalid OCSP response */
239 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
240 CFArrayAppendValue(certs, certA);
241 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
242 CFArrayAppendValue(scts, proofA_1);
243 test_ct_trust(certs, scts, invalid_ocsp, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
244 false, false, false, "coreos-ct-test 4");
245 CFReleaseNull(certs);
248 /* Case 7: Test with a valid OCSP response */
249 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
250 CFArrayAppendValue(certs, certA);
251 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
252 CFArrayAppendValue(scts, proofA_1);
253 test_ct_trust(certs, scts, valid_ocsp, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
254 false, false, false, "coreos-ct-test 5");
255 CFReleaseNull(certs);
258 /* Case 8: Test with a bad hash OCSP response */
259 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
260 CFArrayAppendValue(certs, certA);
261 isnt(scts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create SCT array");
262 CFArrayAppendValue(scts, proofA_1);
263 test_ct_trust(certs, scts, bad_hash_ocsp, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307,
264 false, false, false, "coreos-ct-test 6");
265 CFReleaseNull(certs);
268 /* Case 9: Previously WhiteListed EV cert (expired in Feb 2016, so not on final whitelist)*/
269 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
270 CFArrayAppendValue(certs, pilot_cert_3055998);
271 CFArrayAppendValue(certs, pilot_cert_3055998_issuer);
272 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.ssbwingate.com"), date_20150307,
273 false, true, false, "previously whitelisted cert");
274 CFReleaseNull(certs);
276 /* Case 10-13: WhiteListed EV cert */
277 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
278 CFArrayAppendValue(certs, whitelist_00008013);
279 CFArrayAppendValue(certs, whitelist_00008013_issuer);
280 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("clava.com"), date_20150307,
281 false, true, true, "whitelisted cert 00008013");
282 CFReleaseNull(certs);
284 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
285 CFArrayAppendValue(certs, whitelist_5555bc4f);
286 CFArrayAppendValue(certs, whitelist_5555bc4f_issuer);
287 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("lanai.dartmouth.edu"),
288 date_20150307, false, true, true, "whitelisted cert 5555bc4f");
289 CFReleaseNull(certs);
291 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
292 CFArrayAppendValue(certs, whitelist_aaaae152);
293 CFArrayAppendValue(certs, whitelist_5555bc4f_issuer); // Same issuer (Go Daddy) as above
294 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.falymusic.com"),
295 date_20150307, false, true, true, "whitelisted cert aaaae152");
296 CFReleaseNull(certs);
298 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
299 CFArrayAppendValue(certs, whitelist_fff9b5f6);
300 CFArrayAppendValue(certs, whitelist_fff9b5f6_issuer);
301 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.defencehealth.com.au"),
302 date_20150307, false, true, true, "whitelisted cert fff9b5f6");
303 CFReleaseNull(certs);
306 /* case 14: Current (April 2016) www.digicert.com cert: 3 embedded SCTs, CT qualified */
307 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
308 CFArrayAppendValue(certs, www_digicert_com_2016_cert);
309 CFArrayAppendValue(certs, digicert_sha2_ev_server_ca);
310 test_ct_trust(certs, NULL, NULL, NULL, NULL, CFSTR("www.digicert.com"), date_20160422,
311 true, true, false, "digicert 2016");
312 CFReleaseNull(certs);
316 #define TEST_CASE(x) \
318 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array for " #x); \
319 isnt(cfCert = SecCertificateCreateFromResource(@#x), NULL, "create cfCert from " #x); \
320 CFArrayAppendValue(certs, cfCert); \
321 test_ct_trust(certs, NULL, NULL, anchors, trustedLogs, CFSTR("coreos-ct-test.apple.com"), date_20150307, true, false, false, #x); \
322 CFReleaseNull(certs); \
323 CFReleaseNull(cfCert); \
327 TEST_CASE(server_1601);
328 TEST_CASE(server_1603);
329 TEST_CASE(server_1604);
330 TEST_CASE(server_1701);
331 TEST_CASE(server_1704);
332 TEST_CASE(server_1705);
333 TEST_CASE(server_1801);
334 TEST_CASE(server_1804);
335 TEST_CASE(server_1805);
336 TEST_CASE(server_2001);
339 CFReleaseSafe(certCA_alpha);
340 CFReleaseSafe(certCA_beta);
341 CFReleaseSafe(anchors);
342 CFReleaseSafe(certA);
343 CFReleaseSafe(certD);
344 CFReleaseSafe(certF);
345 CFReleaseSafe(proofD);
346 CFReleaseSafe(proofA_1);
347 CFReleaseSafe(proofA_2);
348 CFReleaseSafe(www_digicert_com_2015_cert);
349 CFReleaseSafe(www_digicert_com_2016_cert);
350 CFReleaseSafe(digicert_sha2_ev_server_ca);
351 CFReleaseSafe(www_paypal_com_cert);
352 CFReleaseSafe(www_paypal_com_issuer_cert);
353 CFReleaseSafe(pilot_cert_3055998);
354 CFReleaseSafe(pilot_cert_3055998_issuer);
355 CFReleaseSafe(whitelist_00008013);
356 CFReleaseSafe(whitelist_5555bc4f);
357 CFReleaseSafe(whitelist_aaaae152);
358 CFReleaseSafe(whitelist_fff9b5f6);
359 CFReleaseSafe(whitelist_00008013_issuer);
360 CFReleaseSafe(whitelist_5555bc4f_issuer);
361 CFReleaseSafe(whitelist_fff9b5f6_issuer);
362 CFReleaseSafe(trustedLogsURL);
363 CFReleaseSafe(trustedLogs);
364 CFReleaseSafe(valid_ocsp);
365 CFReleaseSafe(invalid_ocsp);
366 CFReleaseSafe(bad_hash_ocsp);
368 CFReleaseSafe(date_20150307);
369 CFReleaseSafe(date_20160422);
374 int si_82_sectrust_ct(int argc, char *const *argv)