2 * Copyright (c) 2006-2018 Apple Inc. All Rights Reserved.
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>
14 #include <sys/socket.h>
15 #include <sys/types.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
22 #include "shared_regressions.h"
24 #include "si-23-sectrust-ocsp.h"
26 static void tests(void)
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
);
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
);
45 CFRelease(ocspPolicy
);
46 ok_status(SecTrustCreateWithCertificates(certs
, policies
, &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");
52 is(SecTrustGetVerifyTime(trust
), 545000000.0, "get date");
54 SecTrustResultType trustResult
;
55 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
56 is_status(trustResult
, kSecTrustResultUnspecified
,
57 "trust is kSecTrustResultUnspecified");
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");
65 SecPolicyRef ocspSignerPolicy
;
66 ok(ocspSignerPolicy
= SecPolicyCreateOCSPSigner(),
67 "create ocspSigner policy");
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");
77 isnt(responderCert
= SecCertificateCreateWithBytes(NULL
, _responderCert
,
78 sizeof(_responderCert
)), NULL
, "create responderCert");
79 CFArraySetValueAtIndex(certs
, 0, responderCert
);
81 ok_status(SecTrustCreateWithCertificates(certs
, ocspSignerPolicy
, &trust
),
82 "create trust for ocspResponder -> c1");
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");
90 CFReleaseSafe(ocspSignerPolicy
);
93 CFReleaseSafe(policies
);
97 CFReleaseSafe(responderCert
);
101 static void test_revocation() {
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
);
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
),
125 CFDateRef date
= CFDateCreate(NULL
, 444900000);
126 ok_status(SecTrustSetVerifyDate(trust
, date
), "set date");
129 is(SecTrustGetVerifyTime(trust
), 444900000, "get date");
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
;
138 CFArrayRef perCertResults
= CFDictionaryGetValue(results
, CFSTR("TrustResultDetails"));
139 if (perCertResults
) {
140 CFDictionaryRef leafResults
= CFArrayGetValueAtIndex(perCertResults
, 0);
142 revoked
= CFDictionaryGetValue(leafResults
, CFSTR("Revocation"));
146 is(revoked
!= NULL
, true, "revoked result is %@", revoked
);
147 CFReleaseSafe(results
);
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
157 date
= CFDateCreate(NULL
, 440000000);
158 ok_status(SecTrustSetVerifyDate(trust
, date
), "set date");
161 is(SecTrustGetVerifyTime(trust
), 440000000, "get date");
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
);
169 CFArrayRef perCertResults
= CFDictionaryGetValue(results
, CFSTR("TrustResultDetails"));
170 if (perCertResults
) {
171 CFDictionaryRef leafResults
= CFArrayGetValueAtIndex(perCertResults
, 0);
173 revoked
= CFDictionaryGetValue(leafResults
, CFSTR("Revocation"));
177 is(revoked
!= NULL
, true, "revoked result is %@", revoked
);
178 CFReleaseSafe(results
);
180 CFReleaseSafe(trust
);
181 CFReleaseSafe(policies
);
182 CFReleaseSafe(rcerts
);
183 CFReleaseSafe(rcert0
);
184 CFReleaseSafe(rcert1
);
187 static void test_forced_revocation()
190 * Test verification requiring a positive response from the revocation server
194 SecCertificateRef smime_leaf_cert
;
195 SecCertificateRef smime_CA_cert
;
196 SecCertificateRef smime_root_cert
;
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");
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");
212 CFMutableArrayRef SMIMEDefaultPolicy
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
213 CFArrayAppendValue(SMIMEDefaultPolicy
, smimePolicy
);
215 // Default Policies + explicit revocation
216 CFMutableArrayRef SMIMEDefaultPolicyWithRevocation
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
217 CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation
, smimePolicy
);
218 CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation
, revocPolicy
);
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
);
225 // Valid anchor certs
226 CFMutableArrayRef SMIMEAnchors
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
227 CFArrayAppendValue(SMIMEAnchors
, smime_root_cert
);
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
);
236 CFDateRef VerifyDate
;
237 isnt(VerifyDate
= CFDateCreate(NULL
, 332900000.0), NULL
, "Create verify date");
238 if (!VerifyDate
) { goto errOut
; }
240 // Standard evaluation for the given verify date
242 SecTrustRef trust
= NULL
;
243 SecTrustResultType trust_result
;
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");
250 ok_status(status
= SecTrustEvaluate(trust
, &trust_result
), "SecTrustEvaluate");
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.
258 is_status(trust_result
, kSecTrustResultFatalTrustFailure
, "trust is kSecTrustResultFatalTrustFailure");
260 CFReleaseNull(trust
);
263 // Revocation-required evaluation should fail, since this CA's servers no longer exist
264 // and no valid responses are available
266 SecTrustRef trust
= NULL
;
267 SecTrustResultType trust_result
;
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");
274 ok_status(status
= SecTrustEvaluate(trust
, &trust_result
), "SecTrustEvaluate");
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.
282 is_status(trust_result
, kSecTrustResultFatalTrustFailure
, "trust is kSecTrustResultFatalTrustFailure");
284 CFReleaseNull(trust
);
287 // Free remaining resources
289 CFReleaseSafe(VerifyDate
);
290 CFReleaseSafe(SMIMEDefaultPolicy
);
291 CFReleaseSafe(SMIMEDefaultPolicyWithRevocation
);
292 CFReleaseSafe(SMIMECertChain
);
293 CFReleaseSafe(SMIMEAnchors
);
297 static void hexdump(const uint8_t *bytes
, size_t len
) {
299 printf("#anchor-sha1: ");
300 for (ix
= 0; ix
< len
; ++ix
) {
301 printf("%02X", bytes
[ix
]);
306 static void datadump(const uint8_t *bytes
, size_t len
) {
308 printf("#anchor-sha1: ");
309 for (ix
= 0; ix
< len
; ++ix
) {
310 printf("%c", bytes
[ix
]);
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
));
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
;
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
);
351 verifyDate
= CFDateCreate(NULL
, 547600500);
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
),
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");
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
);
372 /* Now run with the intermediate returned by the ssl server. */
373 CFArrayAppendValue(certs
, comodo_ev
);
374 ok_status(SecTrustCreateWithCertificates(certs
, sslPolicy
, &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);
386 CFReleaseSafe(trust
);
388 /* Now run with the intermediate returned by following the url in the
389 Certificate Access Information Authority (AIA) extension of the ovh
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);
404 CFReleaseSafe(trust
);
406 /* Now run with the intermediate returned by following the url in the
407 Certificate Access Information Authority (AIA) extension of the ovh
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);
422 CFReleaseSafe(trust
);
424 /* Common variable cleanup. */
425 CFReleaseSafe(sslPolicy
);
426 CFReleaseSafe(revPolicy
);
427 CFReleaseSafe(certs
);
428 CFReleaseSafe(policies
);
429 CFReleaseSafe(comodo_aia
);
430 CFReleaseSafe(comodo_ev
);
432 CFReleaseSafe(verifyDate
);
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
;
443 leaf
= SecCertificateCreateWithBytes(NULL
, _caissuer_https
, sizeof(_caissuer_https
));
444 const void *v_certs
[] = { leaf
};
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"));
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"));
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");
459 is(CFErrorGetCode(error
), errSecCreateChainFailed
, "got wrong error code for revoked cert, got %ld, expected %d",
460 (long)CFErrorGetCode(error
), errSecCreateChainFailed
);
462 fail("expected trust evaluation to fail and it did not.");
464 #pragma clang diagnostic pop
468 CFReleaseNull(policy
);
469 CFReleaseNull(trust
);
470 CFReleaseNull(certs
);
471 CFReleaseNull(verifyDate
);
472 CFReleaseNull(error
);
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
;
483 leaf
= SecCertificateCreateWithBytes(NULL
, _probablyRevokedLeaf
, sizeof(_probablyRevokedLeaf
));
484 subCA
= SecCertificateCreateWithBytes(NULL
, _digiCertSha2SubCA
, sizeof(_digiCertSha2SubCA
));
485 root
= SecCertificateCreateWithBytes(NULL
, _digiCertGlobalRoot
, sizeof(_digiCertGlobalRoot
));
487 const void *v_certs
[] = { leaf
, subCA
};
488 const void *v_anchors
[] = { root
};
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"));
494 anchors
= CFArrayCreate(NULL
, v_anchors
, 1, &kCFTypeArrayCallBacks
);
495 require_noerr_action(SecTrustSetAnchorCertificates(trust
, anchors
), errOut
, fail("failed to set anchors"));
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"));
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
);
504 /* Set no fetch allowed */
505 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust
, false), errOut
, fail("failed to set network fetch disallowed"));
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
);
514 /* Set fetch allowed */
515 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust
, true), errOut
, fail("failed to set network fetch allowed"));
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");
520 is(CFErrorGetCode(error
), errSecCertificateRevoked
, "got wrong error code for revoked cert, got %ld, expected %d",
521 (long)CFErrorGetCode(error
), errSecCertificateRevoked
);
523 fail("expected trust evaluation to fail and it did not.");
526 #pragma clang diagnostic pop
530 CFReleaseNull(subCA
);
532 CFReleaseNull(policy
);
533 CFReleaseNull(trust
);
534 CFReleaseNull(certs
);
535 CFReleaseNull(anchors
);
536 CFReleaseNull(verifyDate
);
537 CFReleaseNull(error
);
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
;
548 leaf
= SecCertificateCreateWithBytes(NULL
, _probablyRevokedLeaf
, sizeof(_probablyRevokedLeaf
));
549 subCA
= SecCertificateCreateWithBytes(NULL
, _digiCertSha2SubCA
, sizeof(_digiCertSha2SubCA
));
550 root
= SecCertificateCreateWithBytes(NULL
, _digiCertGlobalRoot
, sizeof(_digiCertGlobalRoot
));
552 sslPolicy
= SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
553 revocationPolicy
= SecPolicyCreateRevocation(kSecRevocationCheckIfTrusted
);
555 const void *v_certs
[] = { leaf
, subCA
};
556 const void *v_anchors
[] = { root
};
557 const void *v_policies
[] = { sslPolicy
, revocationPolicy
};
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"));
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"));
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
);
572 /* Set no fetch allowed */
573 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust
, false), errOut
, fail("failed to set network fetch disallowed"));
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");
583 is(CFErrorGetCode(error
), errSecCertificateExpired
, "got wrong error code for expired cert");
585 fail("expected trust evaluation to fail and it did not.");
587 CFReleaseNull(error
);
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"));
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");
596 is(CFErrorGetCode(error
), errSecCertificateRevoked
, "got wrong error code for revoked cert, got %ld, expected %d",
597 (long)CFErrorGetCode(error
), errSecCertificateRevoked
);
599 fail("expected trust evaluation to fail and it did not.");
601 #pragma clang diagnostic pop
605 CFReleaseNull(subCA
);
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
);
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
;
626 leaf
= SecCertificateCreateWithBytes(NULL
, _probablyRevokedLeaf
, sizeof(_probablyRevokedLeaf
));
627 subCA
= SecCertificateCreateWithBytes(NULL
, _digiCertSha2SubCA
, sizeof(_digiCertSha2SubCA
));
628 root
= SecCertificateCreateWithBytes(NULL
, _digiCertGlobalRoot
, sizeof(_digiCertGlobalRoot
));
630 const void *v_certs
[] = { leaf
, subCA
};
631 const void *v_anchors
[] = { root
};
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"));
637 anchors
= CFArrayCreate(NULL
, v_anchors
, 1, &kCFTypeArrayCallBacks
);
638 require_noerr_action(SecTrustSetAnchorCertificates(trust
, anchors
), errOut
, fail("failed to set anchors"));
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"));
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
);
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");
653 is(CFErrorGetCode(error
), errSecCertificateRevoked
, "got wrong error code for revoked cert, got %ld, expected %d",
654 (long)CFErrorGetCode(error
), errSecCertificateRevoked
);
656 fail("expected trust evaluation to fail and it did not.");
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"));
662 /* Evaluate trust. Cached response should tell us that it's revoked. */
663 is(SecTrustEvaluateWithError(trust
, &error
), false, "revoked cert with cached response succeeded");
665 is(CFErrorGetCode(error
), errSecCertificateRevoked
, "got wrong error code for revoked cert, got %ld, expected %d",
666 (long)CFErrorGetCode(error
), errSecCertificateRevoked
);
668 fail("expected trust evaluation to fail and it did not.");
671 #pragma clang diagnostic pop
675 CFReleaseNull(subCA
);
677 CFReleaseNull(policy
);
678 CFReleaseNull(trust
);
679 CFReleaseNull(certs
);
680 CFReleaseNull(anchors
);
681 CFReleaseNull(verifyDate
);
682 CFReleaseNull(error
);
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
;
694 leaf
= SecCertificateCreateWithBytes(NULL
, _probablyRevokedLeaf
, sizeof(_probablyRevokedLeaf
));
695 subCA
= SecCertificateCreateWithBytes(NULL
, _digiCertSha2SubCA
, sizeof(_digiCertSha2SubCA
));
696 root
= SecCertificateCreateWithBytes(NULL
, _digiCertGlobalRoot
, sizeof(_digiCertGlobalRoot
));
698 const void *v_certs
[] = { leaf
, subCA
};
699 const void *v_anchors
[] = { root
};
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"));
705 anchors
= CFArrayCreate(NULL
, v_anchors
, 1, &kCFTypeArrayCallBacks
);
706 require_noerr_action(SecTrustSetAnchorCertificates(trust
, anchors
), errOut
, fail("failed to set anchors"));
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"));
711 /* Set the stapled response */
712 ocspResponse
= CFDataCreate(NULL
, _digicertOCSPResponse
, sizeof(_digicertOCSPResponse
));
713 ok_status(SecTrustSetOCSPResponse(trust
, ocspResponse
), "failed to set OCSP response");
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
);
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"));
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");
728 is(CFErrorGetCode(error
), errSecCertificateRevoked
, "got wrong error code for revoked cert, got %ld, expected %d",
729 (long)CFErrorGetCode(error
), errSecCertificateRevoked
);
731 fail("expected trust evaluation to fail and it did not.");
734 #pragma clang diagnostic pop
738 CFReleaseNull(subCA
);
740 CFReleaseNull(policy
);
741 CFReleaseNull(trust
);
742 CFReleaseNull(certs
);
743 CFReleaseNull(anchors
);
744 CFReleaseNull(verifyDate
);
745 CFReleaseNull(error
);
746 CFReleaseNull(ocspResponse
);
749 static int ping_host(char *host_name
){
751 struct sockaddr_in pin
;
752 struct hostent
*nlp_host
;
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
);
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
);
774 sd
=socket(AF_INET
,SOCK_STREAM
,0);
776 if (connect(sd
,(struct sockaddr
*)&pin
,sizeof(pin
))==-1){
777 printf("connect error! (%s) %d\n", host_name
, errno
);
787 int si_23_sectrust_ocsp(int argc
, char *const *argv
)
790 "EVSecure-ocsp.verisign.com",
791 "EVIntl-ocsp.verisign.com",
792 "EVIntl-aia.verisign.com",
799 unsigned host_cnt
= 0;
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
]);
814 test_forced_revocation();
815 test_set_fetch_allowed();
816 test_check_if_trusted();
818 test_stapled_revoked_response();