]> git.saurik.com Git - apple/security.git/blob - tests/TrustTests/EvaluationTests/RevocationTests.m
Security-59306.80.4.tar.gz
[apple/security.git] / tests / TrustTests / EvaluationTests / RevocationTests.m
1 /*
2 * Copyright (c) 2006-2019 Apple Inc. All Rights Reserved.
3 */
4
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"
15
16 #import "../TestMacroConversions.h"
17 #import "../TrustEvaluationTestHelpers.h"
18 #import "TrustEvaluationTestCase.h"
19
20 #include "RevocationTests_data.h"
21
22 @interface RevocationTests : TrustEvaluationTestCase
23 @end
24
25 @implementation RevocationTests
26
27 - (void)setUp
28 {
29 // Delete the OCSP cache between each test
30 [super setUp];
31 SecOCSPCacheDeleteContent(nil);
32 }
33
34 #if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE
35 /* watchOS and bridgeOS don't support networking in trustd */
36 - (void)testRevocation
37 {
38 if (!ping_host("ocsp.digicert.com")) {
39 XCTAssert(false, "Unable to contact required network resource");
40 return;
41 }
42
43 SecTrustRef trust;
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);
53
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);
59 CFRelease(sslPolicy);
60 CFRelease(ocspPolicy);
61 ok_status(SecTrustCreateWithCertificates(certs, policies, &trust),
62 "create 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");
66
67 is(SecTrustGetVerifyTime(trust), 577000000.0, "get date");
68
69 SecTrustResultType trustResult;
70 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
71 is_status(trustResult, kSecTrustResultUnspecified,
72 "trust is kSecTrustResultUnspecified");
73
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");
79
80 CFReleaseSafe(info);
81 CFReleaseSafe(trust);
82 CFReleaseSafe(policies);
83 CFReleaseSafe(certs);
84 CFReleaseSafe(cert0);
85 CFReleaseSafe(cert1);
86 CFReleaseSafe(date);
87 }
88
89 - (void) test_ocsp_responder_policy
90 {
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;
97
98 /* August 14, 2018 at 9:26:40 PM PDT */
99 CFDateRef date = CFDateCreate(NULL, 556000000.0);
100
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);
107
108 ok(ocspSignerPolicy = SecPolicyCreateOCSPSigner(),
109 "create ocspSigner policy");
110
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");
117
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");
127
128 CFReleaseNull(leaf);
129 CFReleaseNull(subCA);
130 CFReleaseNull(responderCert);
131 CFReleaseNull(certs);
132 CFReleaseNull(trust);
133 CFReleaseSafe(ocspSignerPolicy);
134 CFReleaseNull(date);
135 }
136
137 - (void)test_always_honor_cached_revoked_responses {
138 if (!ping_host("ocsp.apple.com")) {
139 XCTAssert(false, "Unable to contact required network resource");
140 return;
141 }
142
143 SecTrustRef trust;
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);
155
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),
164 "create trust");
165 /* Feb 5th 2015. */
166 CFDateRef date = CFDateCreate(NULL, 444900000);
167 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
168 CFReleaseSafe(date);
169
170 is(SecTrustGetVerifyTime(trust), 444900000, "get date");
171
172 SecTrustResultType trustResult;
173 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
174 is(trustResult, kSecTrustResultFatalTrustFailure);
175 CFDictionaryRef results = SecTrustCopyResult(trust);
176 CFTypeRef revoked = NULL;
177 if (results) {
178 CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
179 if (perCertResults) {
180 CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
181 if (leafResults) {
182 revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
183 }
184 }
185 }
186 is(revoked != NULL, true, "revoked result is %@", revoked);
187 CFReleaseSafe(results);
188
189
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
194 validly signed.
195 */
196 /* Dec 11th 2014. */
197 date = CFDateCreate(NULL, 440000000);
198 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
199 CFReleaseSafe(date);
200
201 is(SecTrustGetVerifyTime(trust), 440000000, "get date");
202
203 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
204 is(trustResult, kSecTrustResultFatalTrustFailure);
205 results = SecTrustCopyResult(trust);
206 revoked = NULL;
207 if (results) {
208 CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
209 if (perCertResults) {
210 CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
211 if (leafResults) {
212 revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
213 }
214 }
215 }
216 is(revoked != NULL, true, "revoked result is %@", revoked);
217 CFReleaseSafe(results);
218
219 CFReleaseSafe(trust);
220 CFReleaseSafe(policies);
221 CFReleaseSafe(rcerts);
222 CFReleaseSafe(rcert0);
223 CFReleaseSafe(rcert1);
224 }
225
226 - (void) test_require_positive_response
227 {
228 if (!ping_host("ocsp.apple.com")) {
229 XCTAssert(false, "Unable to contact required network resource");
230 return;
231 }
232
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;
239
240 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
241 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
242 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
243
244 const void *v_certs[] = { leaf, subCA };
245 const void *v_anchors[] = { root };
246
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"));
253
254 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
255 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
256
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"));
259
260 /* Set no fetch allowed */
261 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
262
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");
265 if (error) {
266 is(CFErrorGetCode(error), errSecIncompleteCertRevocationCheck, "got wrong error code for revoked cert, got %ld, expected %d",
267 (long)CFErrorGetCode(error), errSecIncompleteCertRevocationCheck);
268 } else {
269 fail("expected trust evaluation to fail and it did not.");
270 }
271 CFReleaseNull(error);
272
273 /* Set fetch allowed */
274 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, true), errOut, fail("failed to set network fetch allowed"));
275
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");
278 if (error) {
279 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
280 (long)CFErrorGetCode(error), errSecCertificateRevoked);
281 } else {
282 fail("expected trust evaluation to fail and it did not.");
283 }
284
285 errOut:
286 CFReleaseNull(leaf);
287 CFReleaseNull(subCA);
288 CFReleaseNull(root);
289 CFReleaseNull(policy);
290 CFReleaseNull(trust);
291 CFReleaseNull(certs);
292 CFReleaseNull(anchors);
293 CFReleaseNull(verifyDate);
294 CFReleaseNull(error);
295 }
296
297 - (void) test_set_fetch_allowed {
298 if (!ping_host("ocsp.apple.com")) {
299 XCTAssert(false, "Unable to contact required network resource");
300 return;
301 }
302
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;
309
310 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
311 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
312 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
313
314 const void *v_certs[] = { leaf, subCA };
315 const void *v_anchors[] = { root };
316
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"));
320
321 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
322 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
323
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"));
326
327 /* Set no fetch allowed */
328 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
329
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);
334
335 /* Set fetch allowed */
336 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, true), errOut, fail("failed to set network fetch allowed"));
337
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");
340 if (error) {
341 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
342 (long)CFErrorGetCode(error), errSecCertificateRevoked);
343 } else {
344 fail("expected trust evaluation to fail and it did not.");
345 }
346
347 errOut:
348 CFReleaseNull(leaf);
349 CFReleaseNull(subCA);
350 CFReleaseNull(root);
351 CFReleaseNull(policy);
352 CFReleaseNull(trust);
353 CFReleaseNull(certs);
354 CFReleaseNull(anchors);
355 CFReleaseNull(verifyDate);
356 CFReleaseNull(error);
357 }
358
359 - (void) test_check_if_trusted {
360 if (!ping_host("ocsp.apple.com")) {
361 XCTAssert(false, "Unable to contact required network resource");
362 return;
363 }
364
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;
371
372 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
373 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
374 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
375
376 codesigningPolicy = SecPolicyCreateAppleExternalDeveloper();
377 revocationPolicy = SecPolicyCreateRevocation(kSecRevocationCheckIfTrusted);
378
379 const void *v_certs[] = { leaf, subCA };
380 const void *v_anchors[] = { root };
381 const void *v_policies[] = { codesigningPolicy, revocationPolicy };
382
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"));
386
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"));
391
392 /* Set no fetch allowed */
393 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
394
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");
400 if (error) {
401 is(CFErrorGetCode(error), errSecCertificateExpired, "got wrong error code for expired cert");
402 } else {
403 fail("expected trust evaluation to fail and it did not.");
404 }
405 CFReleaseNull(error);
406
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"));
410
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");
413 if (error) {
414 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
415 (long)CFErrorGetCode(error), errSecCertificateRevoked);
416 } else {
417 fail("expected trust evaluation to fail and it did not.");
418 }
419
420 errOut:
421 CFReleaseNull(leaf);
422 CFReleaseNull(subCA);
423 CFReleaseNull(root);
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);
433 }
434
435 - (void) test_cache {
436 if (!ping_host("ocsp.apple.com")) {
437 XCTAssert(false, "Unable to contact required network resource");
438 return;
439 }
440
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;
447
448 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
449 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
450 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
451
452 const void *v_certs[] = { leaf, subCA };
453 const void *v_anchors[] = { root };
454
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"));
458
459 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
460 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
461
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"));
464
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");
468 if (error) {
469 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
470 (long)CFErrorGetCode(error), errSecCertificateRevoked);
471 } else {
472 fail("expected trust evaluation to fail and it did not.");
473 }
474
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"));
477
478 /* Evaluate trust. Cached response should tell us that it's revoked. */
479 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded");
480 if (error) {
481 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
482 (long)CFErrorGetCode(error), errSecCertificateRevoked);
483 } else {
484 fail("expected trust evaluation to fail and it did not.");
485 }
486
487 errOut:
488 CFReleaseNull(leaf);
489 CFReleaseNull(subCA);
490 CFReleaseNull(root);
491 CFReleaseNull(policy);
492 CFReleaseNull(trust);
493 CFReleaseNull(certs);
494 CFReleaseNull(anchors);
495 CFReleaseNull(verifyDate);
496 CFReleaseNull(error);
497 }
498
499 - (void)test_revoked_responses_not_flushed_from_cache
500 {
501 if (!ping_host("ocsp.apple.com")) {
502 XCTAssert(false, "Unable to contact required network resource");
503 return;
504 }
505
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;
512
513 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
514 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
515 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
516
517 const void *v_certs[] = { leaf, subCA };
518 const void *v_anchors[] = { root };
519
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"));
523
524 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
525 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
526
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"));
529
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");
533 if (error) {
534 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
535 (long)CFErrorGetCode(error), errSecCertificateRevoked);
536 } else {
537 fail("expected trust evaluation to fail and it did not.");
538 }
539
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"));
542
543 /* Evaluate trust. Cached response should tell us that it's revoked. */
544 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded");
545 if (error) {
546 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
547 (long)CFErrorGetCode(error), errSecCertificateRevoked);
548 } else {
549 fail("expected trust evaluation to fail and it did not.");
550 }
551
552 /* flush the cache and reset the turst, the revoked response should still be present afterwards */
553 XCTAssert(SecTrustFlushResponseCache(NULL));
554 SecTrustSetNeedsEvaluation(trust);
555
556 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded");
557 if (error) {
558 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
559 (long)CFErrorGetCode(error), errSecCertificateRevoked);
560 } else {
561 fail("expected trust evaluation to fail and it did not.");
562 }
563
564 errOut:
565 CFReleaseNull(leaf);
566 CFReleaseNull(subCA);
567 CFReleaseNull(root);
568 CFReleaseNull(policy);
569 CFReleaseNull(trust);
570 CFReleaseNull(certs);
571 CFReleaseNull(anchors);
572 CFReleaseNull(verifyDate);
573 CFReleaseNull(error);
574 }
575
576 - (void) test_results_dictionary_revocation_checked {
577 if (!ping_host("ocsp.digicert.com")) {
578 XCTAssert(false, "Unable to contact required network resource");
579 return;
580 }
581
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;
588
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));
592
593 sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.apple.com"));
594 ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
595
596 const void *v_certs[] = { leaf, subCA };
597 const void *v_anchors[] = { root };
598 const void *v_policies[] = { sslPolicy, ocspPolicy };
599
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"));
603
604 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
605 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
606
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"));
609
610 is(SecTrustEvaluateWithError(trust, &error), true, "valid cert failed");
611
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");
615 if (result) {
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");
619 if (validUntil) {
620 ok(CFDateGetAbsoluteTime(validUntil) > CFAbsoluteTimeGetCurrent(), "expected valid until date in the future");
621 } else {
622 fail("did not get valid until date");
623 }
624 }
625 CFReleaseNull(result);
626
627 errOut:
628 CFReleaseNull(leaf);
629 CFReleaseNull(subCA);
630 CFReleaseNull(root);
631 CFReleaseNull(ocspPolicy);
632 CFReleaseNull(sslPolicy);
633 CFReleaseNull(trust);
634 CFReleaseNull(certs);
635 CFReleaseNull(anchors);
636 CFReleaseNull(policies);
637 CFReleaseNull(verifyDate);
638 CFReleaseNull(error);
639 }
640
641 #else /* TARGET_OS_WATCH || TARGET_OS_BRIDGE */
642 - (void)testNoNetworking
643 {
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;
650
651 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
652 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
653 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
654
655 const void *v_certs[] = { leaf, subCA };
656 const void *v_anchors[] = { root };
657
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"));
661
662 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
663 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
664
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"));
667
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");
671
672 errOut:
673 CFReleaseNull(leaf);
674 CFReleaseNull(subCA);
675 CFReleaseNull(root);
676 CFReleaseNull(policy);
677 CFReleaseNull(trust);
678 CFReleaseNull(certs);
679 CFReleaseNull(anchors);
680 CFReleaseNull(verifyDate);
681 CFReleaseNull(error);
682 }
683 #endif
684
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;
694
695 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
696 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
697 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
698
699 const void *v_certs[] = { leaf, subCA };
700 const void *v_anchors[] = { root };
701
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"));
705
706 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
707 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
708
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"));
711
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");
715
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"));
718
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");
722 if (error) {
723 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
724 (long)CFErrorGetCode(error), errSecCertificateRevoked);
725 } else {
726 fail("expected trust evaluation to fail and it did not.");
727 }
728
729 errOut:
730 CFReleaseNull(leaf);
731 CFReleaseNull(subCA);
732 CFReleaseNull(root);
733 CFReleaseNull(policy);
734 CFReleaseNull(trust);
735 CFReleaseNull(certs);
736 CFReleaseNull(anchors);
737 CFReleaseNull(verifyDate);
738 CFReleaseNull(error);
739 CFReleaseNull(ocspResponse);
740 }
741
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;
750
751 leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf));
752 subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA));
753 root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot));
754
755 const void *v_certs[] = { leaf, subCA };
756 const void *v_anchors[] = { root };
757
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"));
761
762 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
763 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
764
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"));
767
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");
771
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");
775 if (error) {
776 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
777 (long)CFErrorGetCode(error), errSecCertificateRevoked);
778
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");
782 if (result) {
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);
787 }
788 CFReleaseNull(result);
789 } else {
790 fail("expected trust evaluation to fail and it did not.");
791 }
792
793 errOut:
794 CFReleaseNull(leaf);
795 CFReleaseNull(subCA);
796 CFReleaseNull(root);
797 CFReleaseNull(policy);
798 CFReleaseNull(trust);
799 CFReleaseNull(certs);
800 CFReleaseNull(anchors);
801 CFReleaseNull(verifyDate);
802 CFReleaseNull(error);
803 CFReleaseNull(ocspResponse);
804 }
805
806 @end