]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c
Security-58286.251.4.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / secitem / si-23-sectrust-ocsp.c
1 /*
2 * Copyright (c) 2006-2018 Apple Inc. All Rights Reserved.
3 */
4
5 #include <AssertMacros.h>
6 #include <CoreFoundation/CoreFoundation.h>
7 #include <Security/SecCertificate.h>
8 #include <Security/SecCertificatePriv.h>
9 #include <Security/SecPolicyPriv.h>
10 #include <Security/SecTrustPriv.h>
11 #include <utilities/array_size.h>
12 #include <utilities/SecCFRelease.h>
13 #include <stdlib.h>
14 #include <sys/socket.h>
15 #include <sys/types.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <netdb.h>
19 #include <unistd.h>
20 #include <string.h>
21
22 #include "shared_regressions.h"
23
24 #include "si-23-sectrust-ocsp.h"
25
26 static void tests(void)
27 {
28 SecTrustRef trust;
29 SecCertificateRef cert0, cert1, responderCert;
30 isnt(cert0 = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0)),
31 NULL, "create cert0");
32 isnt(cert1 = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1)),
33 NULL, "create cert1");
34 CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0,
35 &kCFTypeArrayCallBacks);
36 CFArrayAppendValue(certs, cert0);
37 CFArrayAppendValue(certs, cert1);
38
39 SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.paypal.com"));
40 SecPolicyRef ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
41 const void *v_policies[] = { sslPolicy, ocspPolicy };
42 CFArrayRef policies = CFArrayCreate(NULL, v_policies,
43 array_size(v_policies), &kCFTypeArrayCallBacks);
44 CFRelease(sslPolicy);
45 CFRelease(ocspPolicy);
46 ok_status(SecTrustCreateWithCertificates(certs, policies, &trust),
47 "create trust");
48 /* April 9, 2018 at 1:53:20 PM PDT */
49 CFDateRef date = CFDateCreate(NULL, 545000000.0);
50 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
51
52 is(SecTrustGetVerifyTime(trust), 545000000.0, "get date");
53
54 SecTrustResultType trustResult;
55 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
56 is_status(trustResult, kSecTrustResultUnspecified,
57 "trust is kSecTrustResultUnspecified");
58
59 /* Certificates are only EV if they are also CT. */
60 CFDictionaryRef info = SecTrustCopyInfo(trust);
61 CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(info,
62 kSecTrustInfoExtendedValidationKey);
63 ok(ev, "extended validation succeeded");
64
65 SecPolicyRef ocspSignerPolicy;
66 ok(ocspSignerPolicy = SecPolicyCreateOCSPSigner(),
67 "create ocspSigner policy");
68
69 CFReleaseNull(trust);
70 ok_status(SecTrustCreateWithCertificates(certs, ocspSignerPolicy, &trust),
71 "create trust for c0 -> c1");
72 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
73 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
74 is_status(trustResult, kSecTrustResultRecoverableTrustFailure,
75 "trust is kSecTrustResultRecoverableTrustFailure");
76
77 isnt(responderCert = SecCertificateCreateWithBytes(NULL, _responderCert,
78 sizeof(_responderCert)), NULL, "create responderCert");
79 CFArraySetValueAtIndex(certs, 0, responderCert);
80 CFReleaseNull(trust);
81 ok_status(SecTrustCreateWithCertificates(certs, ocspSignerPolicy, &trust),
82 "create trust for ocspResponder -> c1");
83 CFReleaseNull(date);
84 date = CFDateCreate(NULL, 525000000.0); // August 21, 2017 at 2:20:00 AM PDT
85 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
86 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
87 is_status(trustResult, kSecTrustResultUnspecified,
88 "trust is kSecTrustResultUnspecified");
89
90 CFReleaseSafe(ocspSignerPolicy);
91 CFReleaseSafe(info);
92 CFReleaseSafe(trust);
93 CFReleaseSafe(policies);
94 CFReleaseSafe(certs);
95 CFReleaseSafe(cert0);
96 CFReleaseSafe(cert1);
97 CFReleaseSafe(responderCert);
98 CFReleaseSafe(date);
99 }
100
101 static void test_revocation() {
102 SecTrustRef trust;
103 SecCertificateRef rcert0, rcert1;
104 isnt(rcert0 = SecCertificateCreateWithBytes(NULL,
105 revoked_ist_certificate, sizeof(revoked_ist_certificate)),
106 NULL, "create rcert0");
107 isnt(rcert1 = SecCertificateCreateWithBytes(NULL,
108 ist_intermediate_certificate, sizeof(ist_intermediate_certificate)),
109 NULL, "create rcert1");
110 CFMutableArrayRef rcerts = CFArrayCreateMutable(kCFAllocatorDefault, 0,
111 &kCFTypeArrayCallBacks);
112 CFArrayAppendValue(rcerts, rcert0);
113 CFArrayAppendValue(rcerts, rcert1);
114
115 SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("revoked.geotrust-global-ca.test-pages.certificatemanager.apple.com"));
116 SecPolicyRef ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
117 const void *v_policies[] = { sslPolicy, ocspPolicy };
118 CFArrayRef policies = CFArrayCreate(NULL, v_policies,
119 array_size(v_policies), &kCFTypeArrayCallBacks);
120 CFRelease(sslPolicy);
121 CFRelease(ocspPolicy);
122 ok_status(SecTrustCreateWithCertificates(rcerts, policies, &trust),
123 "create trust");
124 /* Feb 5th 2015. */
125 CFDateRef date = CFDateCreate(NULL, 444900000);
126 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
127 CFReleaseSafe(date);
128
129 is(SecTrustGetVerifyTime(trust), 444900000, "get date");
130
131 SecTrustResultType trustResult;
132 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
133 is((trustResult > kSecTrustResultUnspecified), true,
134 "trust is %d, expected value greater than 4", (int)trustResult);
135 CFDictionaryRef results = SecTrustCopyResult(trust);
136 CFTypeRef revoked = NULL;
137 if (results) {
138 CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
139 if (perCertResults) {
140 CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
141 if (leafResults) {
142 revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
143 }
144 }
145 }
146 is(revoked != NULL, true, "revoked result is %@", revoked);
147 CFReleaseSafe(results);
148
149
150 /* Now verify the cert at a date in the past relative to the previous
151 date, but still within the cert's validity period. Although the
152 cached response from our prior attempt will appear to have been
153 produced in the future, it should still be honored since it's
154 validly signed.
155 */
156 /* Dec 11th 2014. */
157 date = CFDateCreate(NULL, 440000000);
158 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
159 CFReleaseSafe(date);
160
161 is(SecTrustGetVerifyTime(trust), 440000000, "get date");
162
163 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
164 is((trustResult > kSecTrustResultUnspecified), true,
165 "trust is %d, expected value greater than 4", (int)trustResult);
166 results = SecTrustCopyResult(trust);
167 revoked = NULL;
168 if (results) {
169 CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
170 if (perCertResults) {
171 CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
172 if (leafResults) {
173 revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
174 }
175 }
176 }
177 is(revoked != NULL, true, "revoked result is %@", revoked);
178 CFReleaseSafe(results);
179
180 CFReleaseSafe(trust);
181 CFReleaseSafe(policies);
182 CFReleaseSafe(rcerts);
183 CFReleaseSafe(rcert0);
184 CFReleaseSafe(rcert1);
185 }
186
187 static void test_forced_revocation()
188 {
189 /*
190 * Test verification requiring a positive response from the revocation server
191 */
192
193 OSStatus status;
194 SecCertificateRef smime_leaf_cert;
195 SecCertificateRef smime_CA_cert;
196 SecCertificateRef smime_root_cert;
197
198 // Import certificates from byte array above
199 isnt(smime_leaf_cert = SecCertificateCreateWithBytes(NULL, ocsp_smime_leaf_certificate, sizeof(ocsp_smime_leaf_certificate)),
200 NULL, "SMIME Leaf Cert");
201 isnt(smime_CA_cert = SecCertificateCreateWithBytes(NULL, ocsp_smime_CA_certificate, sizeof(ocsp_smime_CA_certificate)),
202 NULL, "SMIME CA Cert");
203 isnt(smime_root_cert = SecCertificateCreateWithBytes(NULL, ocsp_smime_root_certificate, sizeof(ocsp_smime_root_certificate)),
204 NULL, "SMIME Root Cert");
205
206 SecPolicyRef smimePolicy = SecPolicyCreateWithProperties(kSecPolicyAppleSMIME, NULL);
207 SecPolicyRef revocPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod | kSecRevocationRequirePositiveResponse);
208 isnt(smimePolicy, NULL, "SMIME Policy");
209 isnt(revocPolicy, NULL, "SMIME Revocation Policy");
210
211 // Default Policies
212 CFMutableArrayRef SMIMEDefaultPolicy = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
213 CFArrayAppendValue(SMIMEDefaultPolicy, smimePolicy);
214
215 // Default Policies + explicit revocation
216 CFMutableArrayRef SMIMEDefaultPolicyWithRevocation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
217 CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, smimePolicy);
218 CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, revocPolicy);
219
220 // Valid chain of Cert (leaf + CA)
221 CFMutableArrayRef SMIMECertChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
222 CFArrayAppendValue(SMIMECertChain, smime_leaf_cert);
223 CFArrayAppendValue(SMIMECertChain, smime_CA_cert);
224
225 // Valid anchor certs
226 CFMutableArrayRef SMIMEAnchors = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
227 CFArrayAppendValue(SMIMEAnchors, smime_root_cert);
228
229 // Free Resources contained in arrays
230 CFReleaseSafe(smime_leaf_cert);
231 CFReleaseSafe(smime_CA_cert);
232 CFReleaseSafe(smime_root_cert);
233 CFReleaseSafe(smimePolicy);
234 CFReleaseSafe(revocPolicy);
235
236 CFDateRef VerifyDate;
237 isnt(VerifyDate = CFDateCreate(NULL, 332900000.0), NULL, "Create verify date");
238 if (!VerifyDate) { goto errOut; }
239
240 // Standard evaluation for the given verify date
241 {
242 SecTrustRef trust = NULL;
243 SecTrustResultType trust_result;
244
245 ok_status(status = SecTrustCreateWithCertificates(SMIMECertChain, SMIMEDefaultPolicy, &trust),
246 "SecTrustCreateWithCertificates");
247 ok_status(SecTrustSetVerifyDate(trust, VerifyDate), "Set date");
248 ok_status(SecTrustSetAnchorCertificates(trust, SMIMEAnchors), "Set anchors");
249
250 ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate");
251
252 // Check results
253 // NOTE: We now expect a fatal error, since the "TC TrustCenter Class 1 L1 CA IX" CA
254 // is revoked. That CA is no longer present in Valid since the TC root was removed
255 // from the trust store, and as of May 2018, its OCSP server no longer resolves in DNS.
256 // However, the OCSP URI for the CA's issuer is still active and reports the CA as revoked.
257 //
258 is_status(trust_result, kSecTrustResultFatalTrustFailure, "trust is kSecTrustResultFatalTrustFailure");
259
260 CFReleaseNull(trust);
261 }
262
263 // Revocation-required evaluation should fail, since this CA's servers no longer exist
264 // and no valid responses are available
265 {
266 SecTrustRef trust = NULL;
267 SecTrustResultType trust_result;
268
269 ok_status(status = SecTrustCreateWithCertificates(SMIMECertChain, SMIMEDefaultPolicyWithRevocation, &trust),
270 "SecTrustCreateWithCertificates");
271 ok_status(SecTrustSetVerifyDate(trust, VerifyDate), "Set date");
272 ok_status(SecTrustSetAnchorCertificates(trust, SMIMEAnchors), "Set anchors");
273
274 ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate");
275
276 // Check results
277 // NOTE: We now expect a fatal error, since the "TC TrustCenter Class 1 L1 CA IX" CA
278 // is revoked. That CA is no longer present in Valid since the TC root was removed
279 // from the trust store, and as of May 2018, its OCSP server no longer resolves in DNS.
280 // However, the OCSP URI for the CA's issuer is still active and reports the CA as revoked.
281 //
282 is_status(trust_result, kSecTrustResultFatalTrustFailure, "trust is kSecTrustResultFatalTrustFailure");
283
284 CFReleaseNull(trust);
285 }
286
287 // Free remaining resources
288 errOut:
289 CFReleaseSafe(VerifyDate);
290 CFReleaseSafe(SMIMEDefaultPolicy);
291 CFReleaseSafe(SMIMEDefaultPolicyWithRevocation);
292 CFReleaseSafe(SMIMECertChain);
293 CFReleaseSafe(SMIMEAnchors);
294 }
295
296 #if 0
297 static void hexdump(const uint8_t *bytes, size_t len) {
298 size_t ix;
299 printf("#anchor-sha1: ");
300 for (ix = 0; ix < len; ++ix) {
301 printf("%02X", bytes[ix]);
302 }
303 printf("\n");
304 }
305
306 static void datadump(const uint8_t *bytes, size_t len) {
307 size_t ix;
308 printf("#anchor-sha1: ");
309 for (ix = 0; ix < len; ++ix) {
310 printf("%c", bytes[ix]);
311 }
312 printf("\n");
313 }
314
315 static void display_anchor_digest(SecTrustRef trust) {
316 CFIndex count = SecTrustGetCertificateCount(trust);
317 SecCertificateRef anchor = SecTrustGetCertificateAtIndex(trust, count - 1);
318 CFDataRef digest = SecCertificateGetSHA1Digest(anchor);
319 CFDataRef xml = CFPropertyListCreateXMLData(NULL, digest);
320 datadump(CFDataGetBytePtr(xml), CFDataGetLength(xml));
321 }
322 #endif
323
324 static void test_aia(void) {
325 SecCertificateRef ovh = NULL, comodo_ev = NULL, comodo_aia = NULL;
326 CFMutableArrayRef certs = NULL, policies = NULL;
327 SecPolicyRef sslPolicy = NULL, revPolicy = NULL;
328 CFDateRef verifyDate = NULL;
329 CFDictionaryRef info = NULL;
330 SecTrustRef trust = NULL;
331 SecTrustResultType trustResult = kSecTrustResultInvalid;
332 CFBooleanRef ev = NULL;
333
334 /* Initialize common variables */
335 isnt(ovh = SecCertificateCreateWithBytes(NULL, ovh_certificate,
336 sizeof(ovh_certificate)), NULL, "create ovh cert");
337 isnt(comodo_ev = SecCertificateCreateWithBytes(NULL, comodo_ev_certificate,
338 sizeof(comodo_ev_certificate)), NULL, "create comodo_ev cert");
339 isnt(comodo_aia = SecCertificateCreateWithBytes(NULL,
340 comodo_aia_certificate, sizeof(comodo_aia_certificate)), NULL,
341 "create comodo_aia cert");
342 certs = CFArrayCreateMutable(kCFAllocatorDefault, 0,
343 &kCFTypeArrayCallBacks);
344 policies = CFArrayCreateMutable(kCFAllocatorDefault, 0,
345 &kCFTypeArrayCallBacks);
346 sslPolicy = SecPolicyCreateSSL(false, NULL); // For now, use SSL client policy to avoid SHA-1 deprecation
347 revPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod);
348 CFArrayAppendValue(policies, sslPolicy);
349 CFArrayAppendValue(policies, revPolicy);
350 /* May 9th 2018. */
351 verifyDate = CFDateCreate(NULL, 547600500);
352
353 /* First run with no intermediate and disallow network fetching.
354 * Evaluation should fail because it couldn't get the intermediate. */
355 CFArrayAppendValue(certs, ovh);
356 ok_status(SecTrustCreateWithCertificates(certs, policies, &trust),
357 "create trust");
358 ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date");
359 ok_status(SecTrustSetNetworkFetchAllowed(trust, false), "set no network");
360 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
361 is_status(trustResult, kSecTrustResultRecoverableTrustFailure,
362 "trust is kSecTrustResultRecoverableTrustFailure");
363
364 /* Now allow networking. Evaluation should succeed after fetching
365 * the intermediate. */
366 ok_status(SecTrustSetNetworkFetchAllowed(trust, true), "set allow network");
367 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
368 is_status(trustResult, kSecTrustResultUnspecified,
369 "trust is kSecTrustResultUnspecified");
370 CFReleaseNull(trust);
371
372 /* Now run with the intermediate returned by the ssl server. */
373 CFArrayAppendValue(certs, comodo_ev);
374 ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust),
375 "create trust");
376 ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date");
377 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
378 is_status(trustResult, kSecTrustResultUnspecified,
379 "trust is kSecTrustResultUnspecified");
380 info = SecTrustCopyInfo(trust);
381 ev = (CFBooleanRef)CFDictionaryGetValue(info,
382 kSecTrustInfoExtendedValidationKey);
383 ok(ev, "extended validation succeeded due to caissuers fetch");
384 //display_anchor_digest(trust);
385 CFReleaseSafe(info);
386 CFReleaseSafe(trust);
387
388 /* Now run with the intermediate returned by following the url in the
389 Certificate Access Information Authority (AIA) extension of the ovh
390 leaf certificate. */
391 CFArrayAppendValue(certs, comodo_aia);
392 ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust),
393 "re-create trust with aia intermediate");
394 ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date");
395 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
396 is_status(trustResult, kSecTrustResultUnspecified,
397 "trust is kSecTrustResultUnspecified");
398 info = SecTrustCopyInfo(trust);
399 ev = (CFBooleanRef)CFDictionaryGetValue(info,
400 kSecTrustInfoExtendedValidationKey);
401 ok(ev, "extended validation succeeded");
402 //display_anchor_digest(trust);
403 CFReleaseSafe(info);
404 CFReleaseSafe(trust);
405
406 /* Now run with the intermediate returned by following the url in the
407 Certificate Access Information Authority (AIA) extension of the ovh
408 leaf certificate. */
409 CFArrayRemoveValueAtIndex(certs, 1);
410 ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust),
411 "re-create trust with aia intermediate");
412 ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date");
413 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
414 is_status(trustResult, kSecTrustResultUnspecified,
415 "trust is kSecTrustResultUnspecified");
416 info = SecTrustCopyInfo(trust);
417 ev = (CFBooleanRef)CFDictionaryGetValue(info,
418 kSecTrustInfoExtendedValidationKey);
419 ok(ev, "extended validation succeeded");
420 //display_anchor_digest(trust);
421 CFReleaseSafe(info);
422 CFReleaseSafe(trust);
423
424 /* Common variable cleanup. */
425 CFReleaseSafe(sslPolicy);
426 CFReleaseSafe(revPolicy);
427 CFReleaseSafe(certs);
428 CFReleaseSafe(policies);
429 CFReleaseSafe(comodo_aia);
430 CFReleaseSafe(comodo_ev);
431 CFReleaseSafe(ovh);
432 CFReleaseSafe(verifyDate);
433 }
434
435 static void test_aia_https(void) {
436 SecCertificateRef leaf = NULL;
437 SecPolicyRef policy = NULL;
438 SecTrustRef trust = NULL;
439 CFArrayRef certs = NULL;
440 CFDateRef verifyDate = NULL;
441 CFErrorRef error = NULL;
442
443 leaf = SecCertificateCreateWithBytes(NULL, _caissuer_https, sizeof(_caissuer_https));
444 const void *v_certs[] = { leaf };
445
446 certs = CFArrayCreate(NULL, v_certs, 1, &kCFTypeArrayCallBacks);
447 policy = SecPolicyCreateSSL(true, CFSTR("example.com"));
448 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
449
450 verifyDate = CFDateCreate(NULL, 546700000.0); // April 29, 2018 at 6:06:40 AM PDT
451 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
452
453 #pragma clang diagnostic push
454 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
455 /* Evaluate trust. This cert does not chain to anything trusted and we can't fetch an
456 * intermediate because the URI is https. */
457 is(SecTrustEvaluateWithError(trust, &error), false, "leaf with missing intermediate and https CAIssuer URI succeeded");
458 if (error) {
459 is(CFErrorGetCode(error), errSecCreateChainFailed, "got wrong error code for revoked cert, got %ld, expected %d",
460 (long)CFErrorGetCode(error), errSecCreateChainFailed);
461 } else {
462 fail("expected trust evaluation to fail and it did not.");
463 }
464 #pragma clang diagnostic pop
465
466 errOut:
467 CFReleaseNull(leaf);
468 CFReleaseNull(policy);
469 CFReleaseNull(trust);
470 CFReleaseNull(certs);
471 CFReleaseNull(verifyDate);
472 CFReleaseNull(error);
473 }
474
475 static void test_set_fetch_allowed(void) {
476 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
477 SecPolicyRef policy = NULL;
478 SecTrustRef trust = NULL;
479 CFArrayRef certs = NULL, anchors = NULL;
480 CFDateRef verifyDate = NULL;
481 CFErrorRef error = NULL;
482
483 leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf));
484 subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA));
485 root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot));
486
487 const void *v_certs[] = { leaf, subCA };
488 const void *v_anchors[] = { root };
489
490 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
491 policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
492 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
493
494 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
495 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
496
497 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
498 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
499
500 /* Clear the OCSP cache in case there are old responses for this cert. */
501 ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed");
502 CFReleaseNull(error);
503
504 /* Set no fetch allowed */
505 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
506
507 #pragma clang diagnostic push
508 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
509 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
510 * Since network fetch is not allowed and we fail open, this cert should come back as trusted. */
511 ok(SecTrustEvaluateWithError(trust, &error), "non-definitive revoked cert without network failed");
512 CFReleaseNull(error);
513
514 /* Set fetch allowed */
515 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, true), errOut, fail("failed to set network fetch allowed"));
516
517 /* Evaluate trust. SetFetchAllowed should have reset the trust result, so now we should re-do the evaluation and get a revoked failure. */
518 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
519 if (error) {
520 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
521 (long)CFErrorGetCode(error), errSecCertificateRevoked);
522 } else {
523 fail("expected trust evaluation to fail and it did not.");
524 }
525
526 #pragma clang diagnostic pop
527
528 errOut:
529 CFReleaseNull(leaf);
530 CFReleaseNull(subCA);
531 CFReleaseNull(root);
532 CFReleaseNull(policy);
533 CFReleaseNull(trust);
534 CFReleaseNull(certs);
535 CFReleaseNull(anchors);
536 CFReleaseNull(verifyDate);
537 CFReleaseNull(error);
538 }
539
540 static void test_check_if_trusted(void) {
541 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
542 SecPolicyRef sslPolicy = NULL, revocationPolicy = NULL;
543 SecTrustRef trust = NULL;
544 CFArrayRef certs = NULL, anchors = NULL, policies = NULL;
545 CFDateRef verifyDate = NULL, badVerifyDate = NULL;
546 CFErrorRef error = NULL;
547
548 leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf));
549 subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA));
550 root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot));
551
552 sslPolicy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
553 revocationPolicy = SecPolicyCreateRevocation(kSecRevocationCheckIfTrusted);
554
555 const void *v_certs[] = { leaf, subCA };
556 const void *v_anchors[] = { root };
557 const void *v_policies[] = { sslPolicy, revocationPolicy };
558
559 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
560 policies = CFArrayCreate(NULL, v_policies, 2, &kCFTypeArrayCallBacks);
561 require_noerr_action(SecTrustCreateWithCertificates(certs, policies, &trust), errOut, fail("failed to create trust object"));
562
563 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
564 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
565 badVerifyDate = CFDateCreate(NULL, 490000000.0); // July 12, 2016 at 12:06:40 AM PDT (before cert issued)
566 require_noerr_action(SecTrustSetVerifyDate(trust, badVerifyDate), errOut, fail("failed to set verify date"));
567
568 /* Clear the OCSP cache in case there are old responses for this cert. */
569 ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed");
570 CFReleaseNull(error);
571
572 /* Set no fetch allowed */
573 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
574
575 #pragma clang diagnostic push
576 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
577 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
578 * Since we are evaluating it at a time before it was issued, it should come back as untrusted
579 * due to the temporal validity failure, but not due to revocation since we couldn't check for this
580 * untrusted chain. */
581 is(SecTrustEvaluateWithError(trust, &error), false, "not yet valid cert succeeded trust evaluation");
582 if (error) {
583 is(CFErrorGetCode(error), errSecCertificateExpired, "got wrong error code for expired cert");
584 } else {
585 fail("expected trust evaluation to fail and it did not.");
586 }
587 CFReleaseNull(error);
588
589 /* Set verify date within validity period */
590 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
591 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
592
593 /* Evaluate trust. Now that we trust the chain, we should do a revocation check and get a revocation failure. */
594 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
595 if (error) {
596 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
597 (long)CFErrorGetCode(error), errSecCertificateRevoked);
598 } else {
599 fail("expected trust evaluation to fail and it did not.");
600 }
601 #pragma clang diagnostic pop
602
603 errOut:
604 CFReleaseNull(leaf);
605 CFReleaseNull(subCA);
606 CFReleaseNull(root);
607 CFReleaseNull(sslPolicy);
608 CFReleaseNull(revocationPolicy);
609 CFReleaseNull(trust);
610 CFReleaseNull(certs);
611 CFReleaseNull(anchors);
612 CFReleaseNull(policies);
613 CFReleaseNull(verifyDate);
614 CFReleaseNull(badVerifyDate);
615 CFReleaseNull(error);
616 }
617
618 static void test_cache(void) {
619 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
620 SecPolicyRef policy = NULL;
621 SecTrustRef trust = NULL;
622 CFArrayRef certs = NULL, anchors = NULL;
623 CFDateRef verifyDate = NULL;
624 CFErrorRef error = NULL;
625
626 leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf));
627 subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA));
628 root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot));
629
630 const void *v_certs[] = { leaf, subCA };
631 const void *v_anchors[] = { root };
632
633 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
634 policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
635 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
636
637 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
638 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
639
640 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
641 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
642
643 /* Clear the OCSP cache in case there are old responses for this cert. */
644 ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed");
645 CFReleaseNull(error);
646
647 #pragma clang diagnostic push
648 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
649 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
650 * This cert should come back as revoked after a network-based fetch. */
651 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
652 if (error) {
653 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
654 (long)CFErrorGetCode(error), errSecCertificateRevoked);
655 } else {
656 fail("expected trust evaluation to fail and it did not.");
657 }
658
659 /* Set no fetch allowed, so we're relying on the cached response from above */
660 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
661
662 /* Evaluate trust. Cached response should tell us that it's revoked. */
663 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded");
664 if (error) {
665 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
666 (long)CFErrorGetCode(error), errSecCertificateRevoked);
667 } else {
668 fail("expected trust evaluation to fail and it did not.");
669 }
670
671 #pragma clang diagnostic pop
672
673 errOut:
674 CFReleaseNull(leaf);
675 CFReleaseNull(subCA);
676 CFReleaseNull(root);
677 CFReleaseNull(policy);
678 CFReleaseNull(trust);
679 CFReleaseNull(certs);
680 CFReleaseNull(anchors);
681 CFReleaseNull(verifyDate);
682 CFReleaseNull(error);
683 }
684
685 static void test_stapled_revoked_response(void) {
686 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
687 SecPolicyRef policy = NULL;
688 SecTrustRef trust = NULL;
689 CFArrayRef certs = NULL, anchors = NULL;
690 CFDateRef verifyDate = NULL;
691 CFErrorRef error = NULL;
692 CFDataRef ocspResponse = NULL;
693
694 leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf));
695 subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA));
696 root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot));
697
698 const void *v_certs[] = { leaf, subCA };
699 const void *v_anchors[] = { root };
700
701 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
702 policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
703 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
704
705 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
706 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
707
708 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
709 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
710
711 /* Set the stapled response */
712 ocspResponse = CFDataCreate(NULL, _digicertOCSPResponse, sizeof(_digicertOCSPResponse));
713 ok_status(SecTrustSetOCSPResponse(trust, ocspResponse), "failed to set OCSP response");
714
715 /* Clear the OCSP cache in case there are old responses for this cert. */
716 ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed");
717 CFReleaseNull(error);
718
719 /* Set no fetch allowed, so we're relying on the stapled response from above */
720 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
721
722 #pragma clang diagnostic push
723 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
724 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
725 * This cert should come back as revoked because of the stapled revoked response. */
726 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with stapled response succeeded");
727 if (error) {
728 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
729 (long)CFErrorGetCode(error), errSecCertificateRevoked);
730 } else {
731 fail("expected trust evaluation to fail and it did not.");
732 }
733
734 #pragma clang diagnostic pop
735
736 errOut:
737 CFReleaseNull(leaf);
738 CFReleaseNull(subCA);
739 CFReleaseNull(root);
740 CFReleaseNull(policy);
741 CFReleaseNull(trust);
742 CFReleaseNull(certs);
743 CFReleaseNull(anchors);
744 CFReleaseNull(verifyDate);
745 CFReleaseNull(error);
746 CFReleaseNull(ocspResponse);
747 }
748
749 static int ping_host(char *host_name){
750
751 struct sockaddr_in pin;
752 struct hostent *nlp_host;
753 int sd;
754 int port;
755 int retries = 5;
756
757 port=80;
758
759 //tries 5 times then give up
760 while ((nlp_host=gethostbyname(host_name))==0 && retries--){
761 printf("Resolve Error! (%s) %d\n", host_name, h_errno);
762 sleep(1);
763 }
764
765 if(nlp_host==0)
766 return 0;
767
768 bzero(&pin,sizeof(pin));
769 pin.sin_family=AF_INET;
770 pin.sin_addr.s_addr=htonl(INADDR_ANY);
771 pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr;
772 pin.sin_port=htons(port);
773
774 sd=socket(AF_INET,SOCK_STREAM,0);
775
776 if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){
777 printf("connect error! (%s) %d\n", host_name, errno);
778 close(sd);
779 return 0;
780 }
781 else{
782 close(sd);
783 return 1;
784 }
785 }
786
787 int si_23_sectrust_ocsp(int argc, char *const *argv)
788 {
789 char *hosts[] = {
790 "EVSecure-ocsp.verisign.com",
791 "EVIntl-ocsp.verisign.com",
792 "EVIntl-aia.verisign.com",
793 "ocsp.comodoca.com",
794 "crt.comodoca.com",
795 "ocsp.entrust.net",
796 "ocsp.digicert.com",
797 };
798
799 unsigned host_cnt = 0;
800
801 plan_tests(93);
802
803 for (host_cnt = 0; host_cnt < sizeof(hosts)/sizeof(hosts[0]); host_cnt ++) {
804 if(!ping_host(hosts[host_cnt])) {
805 printf("Accessing specific server (%s) failed, check the network!\n", hosts[host_cnt]);
806 return 0;
807 }
808 }
809
810 tests();
811 test_aia();
812 test_aia_https();
813 test_revocation();
814 test_forced_revocation();
815 test_set_fetch_allowed();
816 test_check_if_trusted();
817 test_cache();
818 test_stapled_revoked_response();
819
820 return 0;
821 }