2 * Copyright (c) 2006-2019 Apple Inc. All Rights Reserved.
5 #include <AssertMacros.h>
6 #import <XCTest/XCTest.h>
7 #include <CoreFoundation/CoreFoundation.h>
8 #include <Security/SecCertificate.h>
9 #include <Security/SecCertificatePriv.h>
10 #include <Security/SecPolicyPriv.h>
11 #include <Security/SecTrustPriv.h>
12 #include <utilities/array_size.h>
13 #include <utilities/SecCFRelease.h>
14 #include "trust/trustd/SecOCSPCache.h"
16 #import "../TestMacroConversions.h"
17 #import "../TrustEvaluationTestHelpers.h"
18 #import "TrustEvaluationTestCase.h"
20 #include "RevocationTests_data.h"
22 @interface RevocationTests : TrustEvaluationTestCase
25 @implementation RevocationTests
29 // Delete the OCSP cache between each test
31 SecOCSPCacheDeleteContent(nil);
34 #if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE
35 /* watchOS and bridgeOS don't support networking in trustd */
36 - (void)testRevocation
38 if (!ping_host("ocsp.digicert.com")) {
39 XCTAssert(false, "Unable to contact required network resource");
44 SecCertificateRef cert0, cert1;
45 isnt(cert0 = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0)),
46 NULL, "create cert0");
47 isnt(cert1 = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1)),
48 NULL, "create cert1");
49 CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0,
50 &kCFTypeArrayCallBacks);
51 CFArrayAppendValue(certs, cert0);
52 CFArrayAppendValue(certs, cert1);
54 SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.apple.com"));
55 SecPolicyRef ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
56 const void *v_policies[] = { sslPolicy, ocspPolicy };
57 CFArrayRef policies = CFArrayCreate(NULL, v_policies,
58 array_size(v_policies), &kCFTypeArrayCallBacks);
60 CFRelease(ocspPolicy);
61 ok_status(SecTrustCreateWithCertificates(certs, policies, &trust),
63 /* April 14, 2019 at 10:46:40 PM PDT */
64 CFDateRef date = CFDateCreate(NULL, 577000000.0);
65 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
67 is(SecTrustGetVerifyTime(trust), 577000000.0, "get date");
69 SecTrustResultType trustResult;
70 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
71 is_status(trustResult, kSecTrustResultUnspecified,
72 "trust is kSecTrustResultUnspecified");
74 /* Certificates are only EV if they are also CT. */
75 CFDictionaryRef info = SecTrustCopyInfo(trust);
76 CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(info,
77 kSecTrustInfoExtendedValidationKey);
78 ok(ev, "extended validation succeeded");
82 CFReleaseSafe(policies);
89 - (void) test_ocsp_responder_policy
91 SecCertificateRef leaf = NULL, subCA = NULL, responderCert = NULL;
92 CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0,
93 &kCFTypeArrayCallBacks);
94 SecTrustRef trust = NULL;
95 SecPolicyRef ocspSignerPolicy = NULL;
96 SecTrustResultType trustResult = kSecTrustResultInvalid;
98 /* August 14, 2018 at 9:26:40 PM PDT */
99 CFDateRef date = CFDateCreate(NULL, 556000000.0);
101 isnt(leaf = SecCertificateCreateWithBytes(NULL, valid_ist_certificate,
102 sizeof(valid_ist_certificate)), NULL, "create ist leaf");
103 isnt(subCA = SecCertificateCreateWithBytes(NULL, ist_intermediate_certificate,
104 sizeof(ist_intermediate_certificate)), NULL, "create ist subCA");
105 CFArrayAppendValue(certs, leaf);
106 CFArrayAppendValue(certs, subCA);
108 ok(ocspSignerPolicy = SecPolicyCreateOCSPSigner(),
109 "create ocspSigner policy");
111 ok_status(SecTrustCreateWithCertificates(certs, ocspSignerPolicy, &trust),
112 "create trust for c0 -> c1");
113 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
114 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
115 is_status(trustResult, kSecTrustResultRecoverableTrustFailure,
116 "trust is kSecTrustResultRecoverableTrustFailure");
118 isnt(responderCert = SecCertificateCreateWithBytes(NULL, _responderCert,
119 sizeof(_responderCert)), NULL, "create responderCert");
120 CFArraySetValueAtIndex(certs, 0, responderCert);
121 ok_status(SecTrustCreateWithCertificates(certs, ocspSignerPolicy, &trust),
122 "create trust for ocspResponder -> c1");
123 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
124 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
125 is_status(trustResult, kSecTrustResultUnspecified,
126 "trust is kSecTrustResultUnspecified");
129 CFReleaseNull(subCA);
130 CFReleaseNull(responderCert);
131 CFReleaseNull(certs);
132 CFReleaseNull(trust);
133 CFReleaseSafe(ocspSignerPolicy);
137 - (void)test_always_honor_cached_revoked_responses {
138 if (!ping_host("ocsp.apple.com")) {
139 XCTAssert(false, "Unable to contact required network resource");
144 SecCertificateRef rcert0, rcert1;
145 isnt(rcert0 = SecCertificateCreateWithBytes(NULL,
146 revoked_ist_certificate, sizeof(revoked_ist_certificate)),
147 NULL, "create rcert0");
148 isnt(rcert1 = SecCertificateCreateWithBytes(NULL,
149 ist_intermediate_certificate, sizeof(ist_intermediate_certificate)),
150 NULL, "create rcert1");
151 CFMutableArrayRef rcerts = CFArrayCreateMutable(kCFAllocatorDefault, 0,
152 &kCFTypeArrayCallBacks);
153 CFArrayAppendValue(rcerts, rcert0);
154 CFArrayAppendValue(rcerts, rcert1);
156 SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("revoked.geotrust-global-ca.test-pages.certificatemanager.apple.com"));
157 SecPolicyRef ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
158 const void *v_policies[] = { sslPolicy, ocspPolicy };
159 CFArrayRef policies = CFArrayCreate(NULL, v_policies,
160 array_size(v_policies), &kCFTypeArrayCallBacks);
161 CFRelease(sslPolicy);
162 CFRelease(ocspPolicy);
163 ok_status(SecTrustCreateWithCertificates(rcerts, policies, &trust),
166 CFDateRef date = CFDateCreate(NULL, 444900000);
167 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
170 is(SecTrustGetVerifyTime(trust), 444900000, "get date");
172 SecTrustResultType trustResult;
173 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
174 is(trustResult, kSecTrustResultFatalTrustFailure);
175 CFDictionaryRef results = SecTrustCopyResult(trust);
176 CFTypeRef revoked = NULL;
178 CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
179 if (perCertResults) {
180 CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
182 revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
186 is(revoked != NULL, true, "revoked result is %@", revoked);
187 CFReleaseSafe(results);
190 /* Now verify the cert at a date in the past relative to the previous
191 date, but still within the cert's validity period. Although the
192 cached response from our prior attempt will appear to have been
193 produced in the future, it should still be honored since it's
197 date = CFDateCreate(NULL, 440000000);
198 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
201 is(SecTrustGetVerifyTime(trust), 440000000, "get date");
203 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
204 is(trustResult, kSecTrustResultFatalTrustFailure);
205 results = SecTrustCopyResult(trust);
208 CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
209 if (perCertResults) {
210 CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
212 revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
216 is(revoked != NULL, true, "revoked result is %@", revoked);
217 CFReleaseSafe(results);
219 CFReleaseSafe(trust);
220 CFReleaseSafe(policies);
221 CFReleaseSafe(rcerts);
222 CFReleaseSafe(rcert0);
223 CFReleaseSafe(rcert1);
226 - (void) test_require_positive_response
228 if (!ping_host("ocsp.apple.com")) {
229 XCTAssert(false, "Unable to contact required network resource");
233 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
234 SecPolicyRef policy = NULL, revocationPolicy = NULL;
235 SecTrustRef trust = NULL;
236 CFArrayRef certs = NULL, anchors = NULL;
237 CFDateRef verifyDate = NULL;
238 CFErrorRef error = NULL;
240 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
241 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
242 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
244 const void *v_certs[] = { leaf, subCA };
245 const void *v_anchors[] = { root };
247 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
248 policy = SecPolicyCreateAppleExternalDeveloper();
249 revocationPolicy = SecPolicyCreateRevocation(kSecRevocationRequirePositiveResponse | kSecRevocationOCSPMethod);
250 NSArray *policies = @[ (__bridge id)policy, (__bridge id)revocationPolicy ];
251 require_noerr_action(SecTrustCreateWithCertificates(certs, (__bridge CFArrayRef)policies, &trust), errOut,
252 fail("failed to create trust object"));
254 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
255 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
257 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
258 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
260 /* Set no fetch allowed */
261 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
263 /* Evaluate trust. Since we required a response but disabled networking, should fail. */
264 is(SecTrustEvaluateWithError(trust, &error), false, "non-definitive revoked cert without network failed");
266 is(CFErrorGetCode(error), errSecIncompleteCertRevocationCheck, "got wrong error code for revoked cert, got %ld, expected %d",
267 (long)CFErrorGetCode(error), errSecIncompleteCertRevocationCheck);
269 fail("expected trust evaluation to fail and it did not.");
271 CFReleaseNull(error);
273 /* Set fetch allowed */
274 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, true), errOut, fail("failed to set network fetch allowed"));
276 /* Evaluate trust. We should re-do the evaluation and get a revoked failure from the OCSP check. */
277 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
279 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
280 (long)CFErrorGetCode(error), errSecCertificateRevoked);
282 fail("expected trust evaluation to fail and it did not.");
287 CFReleaseNull(subCA);
289 CFReleaseNull(policy);
290 CFReleaseNull(trust);
291 CFReleaseNull(certs);
292 CFReleaseNull(anchors);
293 CFReleaseNull(verifyDate);
294 CFReleaseNull(error);
297 - (void) test_set_fetch_allowed {
298 if (!ping_host("ocsp.apple.com")) {
299 XCTAssert(false, "Unable to contact required network resource");
303 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
304 SecPolicyRef policy = NULL;
305 SecTrustRef trust = NULL;
306 CFArrayRef certs = NULL, anchors = NULL;
307 CFDateRef verifyDate = NULL;
308 CFErrorRef error = NULL;
310 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
311 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
312 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
314 const void *v_certs[] = { leaf, subCA };
315 const void *v_anchors[] = { root };
317 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
318 policy = SecPolicyCreateAppleExternalDeveloper();
319 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
321 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
322 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
324 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
325 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
327 /* Set no fetch allowed */
328 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
330 /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com.
331 * Since network fetch is not allowed and we fail open, this cert should come back as trusted. */
332 ok(SecTrustEvaluateWithError(trust, &error), "non-definitive revoked cert without network failed");
333 CFReleaseNull(error);
335 /* Set fetch allowed */
336 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, true), errOut, fail("failed to set network fetch allowed"));
338 /* Evaluate trust. SetFetchAllowed should have reset the trust result, so now we should re-do the evaluation and get a revoked failure. */
339 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
341 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
342 (long)CFErrorGetCode(error), errSecCertificateRevoked);
344 fail("expected trust evaluation to fail and it did not.");
349 CFReleaseNull(subCA);
351 CFReleaseNull(policy);
352 CFReleaseNull(trust);
353 CFReleaseNull(certs);
354 CFReleaseNull(anchors);
355 CFReleaseNull(verifyDate);
356 CFReleaseNull(error);
359 - (void) test_check_if_trusted {
360 if (!ping_host("ocsp.apple.com")) {
361 XCTAssert(false, "Unable to contact required network resource");
365 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
366 SecPolicyRef codesigningPolicy = NULL, revocationPolicy = NULL;
367 SecTrustRef trust = NULL;
368 CFArrayRef certs = NULL, anchors = NULL, policies = NULL;
369 CFDateRef verifyDate = NULL, badVerifyDate = NULL;
370 CFErrorRef error = NULL;
372 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
373 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
374 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
376 codesigningPolicy = SecPolicyCreateAppleExternalDeveloper();
377 revocationPolicy = SecPolicyCreateRevocation(kSecRevocationCheckIfTrusted);
379 const void *v_certs[] = { leaf, subCA };
380 const void *v_anchors[] = { root };
381 const void *v_policies[] = { codesigningPolicy, revocationPolicy };
383 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
384 policies = CFArrayCreate(NULL, v_policies, 2, &kCFTypeArrayCallBacks);
385 require_noerr_action(SecTrustCreateWithCertificates(certs, policies, &trust), errOut, fail("failed to create trust object"));
387 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
388 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
389 badVerifyDate = CFDateCreate(NULL, 490000000.0); // July 12, 2016 at 12:06:40 AM PDT (before cert issued)
390 require_noerr_action(SecTrustSetVerifyDate(trust, badVerifyDate), errOut, fail("failed to set verify date"));
392 /* Set no fetch allowed */
393 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
395 /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com.
396 * Since we are evaluating it at a time before it was issued, it should come back as untrusted
397 * due to the temporal validity failure, but not due to revocation since we couldn't check for this
398 * untrusted chain. */
399 is(SecTrustEvaluateWithError(trust, &error), false, "not yet valid cert succeeded trust evaluation");
401 is(CFErrorGetCode(error), errSecCertificateExpired, "got wrong error code for expired cert");
403 fail("expected trust evaluation to fail and it did not.");
405 CFReleaseNull(error);
407 /* Set verify date within validity period */
408 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
409 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
411 /* Evaluate trust. Now that we trust the chain, we should do a revocation check and get a revocation failure. */
412 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
414 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
415 (long)CFErrorGetCode(error), errSecCertificateRevoked);
417 fail("expected trust evaluation to fail and it did not.");
422 CFReleaseNull(subCA);
424 CFReleaseNull(codesigningPolicy);
425 CFReleaseNull(revocationPolicy);
426 CFReleaseNull(trust);
427 CFReleaseNull(certs);
428 CFReleaseNull(anchors);
429 CFReleaseNull(policies);
430 CFReleaseNull(verifyDate);
431 CFReleaseNull(badVerifyDate);
432 CFReleaseNull(error);
435 - (void) test_cache {
436 if (!ping_host("ocsp.apple.com")) {
437 XCTAssert(false, "Unable to contact required network resource");
441 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
442 SecPolicyRef policy = NULL;
443 SecTrustRef trust = NULL;
444 CFArrayRef certs = NULL, anchors = NULL;
445 CFDateRef verifyDate = NULL;
446 CFErrorRef error = NULL;
448 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
449 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
450 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
452 const void *v_certs[] = { leaf, subCA };
453 const void *v_anchors[] = { root };
455 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
456 policy = SecPolicyCreateAppleExternalDeveloper();
457 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
459 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
460 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
462 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
463 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
465 /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com.
466 * This cert should come back as revoked after a network-based fetch. */
467 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
469 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
470 (long)CFErrorGetCode(error), errSecCertificateRevoked);
472 fail("expected trust evaluation to fail and it did not.");
475 /* Set no fetch allowed, so we're relying on the cached response from above */
476 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
478 /* Evaluate trust. Cached response should tell us that it's revoked. */
479 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded");
481 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
482 (long)CFErrorGetCode(error), errSecCertificateRevoked);
484 fail("expected trust evaluation to fail and it did not.");
489 CFReleaseNull(subCA);
491 CFReleaseNull(policy);
492 CFReleaseNull(trust);
493 CFReleaseNull(certs);
494 CFReleaseNull(anchors);
495 CFReleaseNull(verifyDate);
496 CFReleaseNull(error);
499 - (void)test_revoked_responses_not_flushed_from_cache
501 if (!ping_host("ocsp.apple.com")) {
502 XCTAssert(false, "Unable to contact required network resource");
506 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
507 SecPolicyRef policy = NULL;
508 SecTrustRef trust = NULL;
509 CFArrayRef certs = NULL, anchors = NULL;
510 CFDateRef verifyDate = NULL;
511 CFErrorRef error = NULL;
513 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
514 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
515 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
517 const void *v_certs[] = { leaf, subCA };
518 const void *v_anchors[] = { root };
520 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
521 policy = SecPolicyCreateAppleExternalDeveloper();
522 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
524 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
525 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
527 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
528 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
530 /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com.
531 * This cert should come back as revoked after a network-based fetch. */
532 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
534 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
535 (long)CFErrorGetCode(error), errSecCertificateRevoked);
537 fail("expected trust evaluation to fail and it did not.");
540 /* Set no fetch allowed, so we're relying on the cached response from above */
541 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
543 /* Evaluate trust. Cached response should tell us that it's revoked. */
544 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded");
546 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
547 (long)CFErrorGetCode(error), errSecCertificateRevoked);
549 fail("expected trust evaluation to fail and it did not.");
552 /* flush the cache and reset the turst, the revoked response should still be present afterwards */
553 XCTAssert(SecTrustFlushResponseCache(NULL));
554 SecTrustSetNeedsEvaluation(trust);
556 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded");
558 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
559 (long)CFErrorGetCode(error), errSecCertificateRevoked);
561 fail("expected trust evaluation to fail and it did not.");
566 CFReleaseNull(subCA);
568 CFReleaseNull(policy);
569 CFReleaseNull(trust);
570 CFReleaseNull(certs);
571 CFReleaseNull(anchors);
572 CFReleaseNull(verifyDate);
573 CFReleaseNull(error);
576 - (void) test_results_dictionary_revocation_checked {
577 if (!ping_host("ocsp.digicert.com")) {
578 XCTAssert(false, "Unable to contact required network resource");
582 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
583 SecPolicyRef sslPolicy = NULL, ocspPolicy = NULL;
584 SecTrustRef trust = NULL;
585 CFArrayRef certs = NULL, anchors = NULL, policies = NULL;
586 CFDateRef verifyDate = NULL;
587 CFErrorRef error = NULL;
589 leaf = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0));
590 subCA = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1));
591 root = SecCertificateCreateWithBytes(NULL, _ocsp_c2, sizeof(_ocsp_c2));
593 sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.apple.com"));
594 ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
596 const void *v_certs[] = { leaf, subCA };
597 const void *v_anchors[] = { root };
598 const void *v_policies[] = { sslPolicy, ocspPolicy };
600 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
601 policies = CFArrayCreate(NULL, v_policies, 2, &kCFTypeArrayCallBacks);
602 require_noerr_action(SecTrustCreateWithCertificates(certs, policies, &trust), errOut, fail("failed to create trust object"));
604 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
605 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
607 verifyDate = CFDateCreate(NULL, 577000000.0); // April 14, 2019 at 10:46:40 PM PDT
608 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
610 is(SecTrustEvaluateWithError(trust, &error), true, "valid cert failed");
612 /* Verify that the results dictionary contains all the right keys for a valid cert where revocation checked */
613 CFDictionaryRef result = SecTrustCopyResult(trust);
614 isnt(result, NULL, "failed to copy result dictionary");
616 is(CFDictionaryGetValue(result, kSecTrustRevocationChecked), kCFBooleanTrue, "expected revocation checked flag");
617 CFDateRef validUntil = CFDictionaryGetValue(result, kSecTrustRevocationValidUntilDate);
618 isnt(validUntil, NULL, "expected revocation valid until date");
620 ok(CFDateGetAbsoluteTime(validUntil) > CFAbsoluteTimeGetCurrent(), "expected valid until date in the future");
622 fail("did not get valid until date");
625 CFReleaseNull(result);
629 CFReleaseNull(subCA);
631 CFReleaseNull(ocspPolicy);
632 CFReleaseNull(sslPolicy);
633 CFReleaseNull(trust);
634 CFReleaseNull(certs);
635 CFReleaseNull(anchors);
636 CFReleaseNull(policies);
637 CFReleaseNull(verifyDate);
638 CFReleaseNull(error);
641 #else /* TARGET_OS_WATCH || TARGET_OS_BRIDGE */
642 - (void)testNoNetworking
644 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
645 SecPolicyRef policy = NULL;
646 SecTrustRef trust = NULL;
647 CFArrayRef certs = NULL, anchors = NULL;
648 CFDateRef verifyDate = NULL;
649 CFErrorRef error = NULL;
651 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
652 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
653 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
655 const void *v_certs[] = { leaf, subCA };
656 const void *v_anchors[] = { root };
658 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
659 policy = SecPolicyCreateAppleExternalDeveloper();
660 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
662 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
663 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
665 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
666 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
668 /* Evaluate trust. Since we aren't allowed to do networking (and this cert is only "Probably Not Revoked" in Valid),
669 * we shouldn't see this cert as revoked */
670 is(SecTrustEvaluateWithError(trust, &error), true, "revoked cert with no network failed");
674 CFReleaseNull(subCA);
676 CFReleaseNull(policy);
677 CFReleaseNull(trust);
678 CFReleaseNull(certs);
679 CFReleaseNull(anchors);
680 CFReleaseNull(verifyDate);
681 CFReleaseNull(error);
685 /* bridgeOS and watchOS do not support networked OCSP but do support stapling */
686 - (void) test_stapled_revoked_response {
687 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
688 SecPolicyRef policy = NULL;
689 SecTrustRef trust = NULL;
690 CFArrayRef certs = NULL, anchors = NULL;
691 CFDateRef verifyDate = NULL;
692 CFErrorRef error = NULL;
693 CFDataRef ocspResponse = NULL;
695 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
696 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
697 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
699 const void *v_certs[] = { leaf, subCA };
700 const void *v_anchors[] = { root };
702 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
703 policy = SecPolicyCreateAppleExternalDeveloper();
704 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
706 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
707 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
709 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
710 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
712 /* Set the stapled response */
713 ocspResponse = CFDataCreate(NULL, _devID_OCSPResponse, sizeof(_devID_OCSPResponse));
714 ok_status(SecTrustSetOCSPResponse(trust, ocspResponse), "failed to set OCSP response");
716 /* Set no fetch allowed, so we're relying on the stapled response from above */
717 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
719 /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com.
720 * This cert should come back as revoked because of the stapled revoked response. */
721 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with stapled response succeeded");
723 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
724 (long)CFErrorGetCode(error), errSecCertificateRevoked);
726 fail("expected trust evaluation to fail and it did not.");
731 CFReleaseNull(subCA);
733 CFReleaseNull(policy);
734 CFReleaseNull(trust);
735 CFReleaseNull(certs);
736 CFReleaseNull(anchors);
737 CFReleaseNull(verifyDate);
738 CFReleaseNull(error);
739 CFReleaseNull(ocspResponse);
742 - (void) test_results_dictionary_revocation_reason {
743 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
744 SecPolicyRef policy = NULL;
745 SecTrustRef trust = NULL;
746 CFArrayRef certs = NULL, anchors = NULL;
747 CFDateRef verifyDate = NULL;
748 CFErrorRef error = NULL;
749 CFDataRef ocspResponse = NULL;
751 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
752 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
753 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
755 const void *v_certs[] = { leaf, subCA };
756 const void *v_anchors[] = { root };
758 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
759 policy = SecPolicyCreateAppleExternalDeveloper();
760 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
762 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
763 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
765 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
766 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
768 /* Set the stapled response */
769 ocspResponse = CFDataCreate(NULL, _devID_OCSPResponse, sizeof(_devID_OCSPResponse));
770 ok_status(SecTrustSetOCSPResponse(trust, ocspResponse), "failed to set OCSP response");
772 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
773 * This cert should come back as revoked. */
774 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert succeeded");
776 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
777 (long)CFErrorGetCode(error), errSecCertificateRevoked);
779 /* Verify that the results dictionary contains all the right keys for a revoked cert */
780 CFDictionaryRef result = SecTrustCopyResult(trust);
781 isnt(result, NULL, "failed to copy result dictionary");
783 int64_t reason = 4; // superceded
784 CFNumberRef cfreason = CFNumberCreate(NULL, kCFNumberSInt64Type, &reason);
785 is(CFNumberCompare(cfreason, CFDictionaryGetValue(result, kSecTrustRevocationReason), NULL), kCFCompareEqualTo, "expected revocation reason 4");
786 CFReleaseNull(cfreason);
788 CFReleaseNull(result);
790 fail("expected trust evaluation to fail and it did not.");
795 CFReleaseNull(subCA);
797 CFReleaseNull(policy);
798 CFReleaseNull(trust);
799 CFReleaseNull(certs);
800 CFReleaseNull(anchors);
801 CFReleaseNull(verifyDate);
802 CFReleaseNull(error);
803 CFReleaseNull(ocspResponse);