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
;
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.apple.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 14, 2019 at 10:46:40 PM PDT */
49 CFDateRef date
= CFDateCreate(NULL
, 577000000.0);
50 ok_status(SecTrustSetVerifyDate(trust
, date
), "set date");
52 is(SecTrustGetVerifyTime(trust
), 577000000.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");
67 CFReleaseSafe(policies
);
74 static void test_ocsp_responder_policy() {
75 SecCertificateRef leaf
= NULL
, subCA
= NULL
, responderCert
= NULL
;
76 CFMutableArrayRef certs
= CFArrayCreateMutable(kCFAllocatorDefault
, 0,
77 &kCFTypeArrayCallBacks
);
78 SecTrustRef trust
= NULL
;
79 SecPolicyRef ocspSignerPolicy
= NULL
;
80 SecTrustResultType trustResult
= kSecTrustResultInvalid
;
82 /* August 14, 2018 at 9:26:40 PM PDT */
83 CFDateRef date
= CFDateCreate(NULL
, 556000000.0);
85 isnt(leaf
= SecCertificateCreateWithBytes(NULL
, valid_ist_certificate
,
86 sizeof(valid_ist_certificate
)), NULL
, "create ist leaf");
87 isnt(subCA
= SecCertificateCreateWithBytes(NULL
, ist_intermediate_certificate
,
88 sizeof(ist_intermediate_certificate
)), NULL
, "create ist subCA");
89 CFArrayAppendValue(certs
, leaf
);
90 CFArrayAppendValue(certs
, subCA
);
92 ok(ocspSignerPolicy
= SecPolicyCreateOCSPSigner(),
93 "create ocspSigner policy");
95 ok_status(SecTrustCreateWithCertificates(certs
, ocspSignerPolicy
, &trust
),
96 "create trust for c0 -> c1");
97 ok_status(SecTrustSetVerifyDate(trust
, date
), "set date");
98 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
99 is_status(trustResult
, kSecTrustResultRecoverableTrustFailure
,
100 "trust is kSecTrustResultRecoverableTrustFailure");
102 isnt(responderCert
= SecCertificateCreateWithBytes(NULL
, _responderCert
,
103 sizeof(_responderCert
)), NULL
, "create responderCert");
104 CFArraySetValueAtIndex(certs
, 0, responderCert
);
105 ok_status(SecTrustCreateWithCertificates(certs
, ocspSignerPolicy
, &trust
),
106 "create trust for ocspResponder -> c1");
107 ok_status(SecTrustSetVerifyDate(trust
, date
), "set date");
108 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
109 is_status(trustResult
, kSecTrustResultUnspecified
,
110 "trust is kSecTrustResultUnspecified");
113 CFReleaseNull(subCA
);
114 CFReleaseNull(responderCert
);
115 CFReleaseNull(certs
);
116 CFReleaseNull(trust
);
117 CFReleaseSafe(ocspSignerPolicy
);
121 static void test_revocation() {
123 SecCertificateRef rcert0
, rcert1
;
124 isnt(rcert0
= SecCertificateCreateWithBytes(NULL
,
125 revoked_ist_certificate
, sizeof(revoked_ist_certificate
)),
126 NULL
, "create rcert0");
127 isnt(rcert1
= SecCertificateCreateWithBytes(NULL
,
128 ist_intermediate_certificate
, sizeof(ist_intermediate_certificate
)),
129 NULL
, "create rcert1");
130 CFMutableArrayRef rcerts
= CFArrayCreateMutable(kCFAllocatorDefault
, 0,
131 &kCFTypeArrayCallBacks
);
132 CFArrayAppendValue(rcerts
, rcert0
);
133 CFArrayAppendValue(rcerts
, rcert1
);
135 SecPolicyRef sslPolicy
= SecPolicyCreateSSL(true, CFSTR("revoked.geotrust-global-ca.test-pages.certificatemanager.apple.com"));
136 SecPolicyRef ocspPolicy
= SecPolicyCreateRevocation(kSecRevocationOCSPMethod
);
137 const void *v_policies
[] = { sslPolicy
, ocspPolicy
};
138 CFArrayRef policies
= CFArrayCreate(NULL
, v_policies
,
139 array_size(v_policies
), &kCFTypeArrayCallBacks
);
140 CFRelease(sslPolicy
);
141 CFRelease(ocspPolicy
);
142 ok_status(SecTrustCreateWithCertificates(rcerts
, policies
, &trust
),
145 CFDateRef date
= CFDateCreate(NULL
, 444900000);
146 ok_status(SecTrustSetVerifyDate(trust
, date
), "set date");
149 is(SecTrustGetVerifyTime(trust
), 444900000, "get date");
151 SecTrustResultType trustResult
;
152 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
153 is((trustResult
> kSecTrustResultUnspecified
), true,
154 "trust is %d, expected value greater than 4", (int)trustResult
);
155 CFDictionaryRef results
= SecTrustCopyResult(trust
);
156 CFTypeRef revoked
= NULL
;
158 CFArrayRef perCertResults
= CFDictionaryGetValue(results
, CFSTR("TrustResultDetails"));
159 if (perCertResults
) {
160 CFDictionaryRef leafResults
= CFArrayGetValueAtIndex(perCertResults
, 0);
162 revoked
= CFDictionaryGetValue(leafResults
, CFSTR("Revocation"));
166 is(revoked
!= NULL
, true, "revoked result is %@", revoked
);
167 CFReleaseSafe(results
);
170 /* Now verify the cert at a date in the past relative to the previous
171 date, but still within the cert's validity period. Although the
172 cached response from our prior attempt will appear to have been
173 produced in the future, it should still be honored since it's
177 date
= CFDateCreate(NULL
, 440000000);
178 ok_status(SecTrustSetVerifyDate(trust
, date
), "set date");
181 is(SecTrustGetVerifyTime(trust
), 440000000, "get date");
183 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
184 is((trustResult
> kSecTrustResultUnspecified
), true,
185 "trust is %d, expected value greater than 4", (int)trustResult
);
186 results
= SecTrustCopyResult(trust
);
189 CFArrayRef perCertResults
= CFDictionaryGetValue(results
, CFSTR("TrustResultDetails"));
190 if (perCertResults
) {
191 CFDictionaryRef leafResults
= CFArrayGetValueAtIndex(perCertResults
, 0);
193 revoked
= CFDictionaryGetValue(leafResults
, CFSTR("Revocation"));
197 is(revoked
!= NULL
, true, "revoked result is %@", revoked
);
198 CFReleaseSafe(results
);
200 CFReleaseSafe(trust
);
201 CFReleaseSafe(policies
);
202 CFReleaseSafe(rcerts
);
203 CFReleaseSafe(rcert0
);
204 CFReleaseSafe(rcert1
);
207 static void test_forced_revocation()
210 * Test verification requiring a positive response from the revocation server
214 SecCertificateRef smime_leaf_cert
;
215 SecCertificateRef smime_CA_cert
;
216 SecCertificateRef smime_root_cert
;
218 // Import certificates from byte array above
219 isnt(smime_leaf_cert
= SecCertificateCreateWithBytes(NULL
, ocsp_smime_leaf_certificate
, sizeof(ocsp_smime_leaf_certificate
)),
220 NULL
, "SMIME Leaf Cert");
221 isnt(smime_CA_cert
= SecCertificateCreateWithBytes(NULL
, ocsp_smime_CA_certificate
, sizeof(ocsp_smime_CA_certificate
)),
222 NULL
, "SMIME CA Cert");
223 isnt(smime_root_cert
= SecCertificateCreateWithBytes(NULL
, ocsp_smime_root_certificate
, sizeof(ocsp_smime_root_certificate
)),
224 NULL
, "SMIME Root Cert");
226 SecPolicyRef smimePolicy
= SecPolicyCreateWithProperties(kSecPolicyAppleSMIME
, NULL
);
227 SecPolicyRef revocPolicy
= SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod
| kSecRevocationRequirePositiveResponse
);
228 isnt(smimePolicy
, NULL
, "SMIME Policy");
229 isnt(revocPolicy
, NULL
, "SMIME Revocation Policy");
232 CFMutableArrayRef SMIMEDefaultPolicy
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
233 CFArrayAppendValue(SMIMEDefaultPolicy
, smimePolicy
);
235 // Default Policies + explicit revocation
236 CFMutableArrayRef SMIMEDefaultPolicyWithRevocation
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
237 CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation
, smimePolicy
);
238 CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation
, revocPolicy
);
240 // Valid chain of Cert (leaf + CA)
241 CFMutableArrayRef SMIMECertChain
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
242 CFArrayAppendValue(SMIMECertChain
, smime_leaf_cert
);
243 CFArrayAppendValue(SMIMECertChain
, smime_CA_cert
);
245 // Valid anchor certs
246 CFMutableArrayRef SMIMEAnchors
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
247 CFArrayAppendValue(SMIMEAnchors
, smime_root_cert
);
249 // Free Resources contained in arrays
250 CFReleaseSafe(smime_leaf_cert
);
251 CFReleaseSafe(smime_CA_cert
);
252 CFReleaseSafe(smime_root_cert
);
253 CFReleaseSafe(smimePolicy
);
254 CFReleaseSafe(revocPolicy
);
256 CFDateRef VerifyDate
;
257 isnt(VerifyDate
= CFDateCreate(NULL
, 332900000.0), NULL
, "Create verify date");
258 if (!VerifyDate
) { goto errOut
; }
260 // Standard evaluation for the given verify date
262 SecTrustRef trust
= NULL
;
263 SecTrustResultType trust_result
;
265 ok_status(status
= SecTrustCreateWithCertificates(SMIMECertChain
, SMIMEDefaultPolicy
, &trust
),
266 "SecTrustCreateWithCertificates");
267 ok_status(SecTrustSetVerifyDate(trust
, VerifyDate
), "Set date");
268 ok_status(SecTrustSetAnchorCertificates(trust
, SMIMEAnchors
), "Set anchors");
270 ok_status(status
= SecTrustEvaluate(trust
, &trust_result
), "SecTrustEvaluate");
273 // NOTE: We now expect a fatal error, since the "TC TrustCenter Class 1 L1 CA IX" CA
274 // is revoked. That CA is no longer present in Valid since the TC root was removed
275 // from the trust store, and as of May 2018, its OCSP server no longer resolves in DNS.
276 // However, the OCSP URI for the CA's issuer is still active and reports the CA as revoked.
278 is_status(trust_result
, kSecTrustResultFatalTrustFailure
, "trust is kSecTrustResultFatalTrustFailure");
280 CFReleaseNull(trust
);
283 // Revocation-required evaluation should fail, since this CA's servers no longer exist
284 // and no valid responses are available
286 SecTrustRef trust
= NULL
;
287 SecTrustResultType trust_result
;
289 ok_status(status
= SecTrustCreateWithCertificates(SMIMECertChain
, SMIMEDefaultPolicyWithRevocation
, &trust
),
290 "SecTrustCreateWithCertificates");
291 ok_status(SecTrustSetVerifyDate(trust
, VerifyDate
), "Set date");
292 ok_status(SecTrustSetAnchorCertificates(trust
, SMIMEAnchors
), "Set anchors");
294 ok_status(status
= SecTrustEvaluate(trust
, &trust_result
), "SecTrustEvaluate");
297 // NOTE: We now expect a fatal error, since the "TC TrustCenter Class 1 L1 CA IX" CA
298 // is revoked. That CA is no longer present in Valid since the TC root was removed
299 // from the trust store, and as of May 2018, its OCSP server no longer resolves in DNS.
300 // However, the OCSP URI for the CA's issuer is still active and reports the CA as revoked.
302 is_status(trust_result
, kSecTrustResultFatalTrustFailure
, "trust is kSecTrustResultFatalTrustFailure");
304 CFReleaseNull(trust
);
307 // Free remaining resources
309 CFReleaseSafe(VerifyDate
);
310 CFReleaseSafe(SMIMEDefaultPolicy
);
311 CFReleaseSafe(SMIMEDefaultPolicyWithRevocation
);
312 CFReleaseSafe(SMIMECertChain
);
313 CFReleaseSafe(SMIMEAnchors
);
317 static void hexdump(const uint8_t *bytes
, size_t len
) {
319 printf("#anchor-sha1: ");
320 for (ix
= 0; ix
< len
; ++ix
) {
321 printf("%02X", bytes
[ix
]);
326 static void datadump(const uint8_t *bytes
, size_t len
) {
328 printf("#anchor-sha1: ");
329 for (ix
= 0; ix
< len
; ++ix
) {
330 printf("%c", bytes
[ix
]);
335 static void display_anchor_digest(SecTrustRef trust
) {
336 CFIndex count
= SecTrustGetCertificateCount(trust
);
337 SecCertificateRef anchor
= SecTrustGetCertificateAtIndex(trust
, count
- 1);
338 CFDataRef digest
= SecCertificateGetSHA1Digest(anchor
);
339 CFDataRef xml
= CFPropertyListCreateXMLData(NULL
, digest
);
340 datadump(CFDataGetBytePtr(xml
), CFDataGetLength(xml
));
344 static void test_aia(void) {
345 SecCertificateRef ovh
= NULL
, comodo_ev
= NULL
, comodo_aia
= NULL
;
346 CFMutableArrayRef certs
= NULL
, policies
= NULL
;
347 SecPolicyRef sslPolicy
= NULL
, revPolicy
= NULL
;
348 CFDateRef verifyDate
= NULL
;
349 CFDictionaryRef info
= NULL
;
350 SecTrustRef trust
= NULL
;
351 SecTrustResultType trustResult
= kSecTrustResultInvalid
;
352 CFBooleanRef ev
= NULL
;
354 /* Initialize common variables */
355 isnt(ovh
= SecCertificateCreateWithBytes(NULL
, ovh_certificate
,
356 sizeof(ovh_certificate
)), NULL
, "create ovh cert");
357 isnt(comodo_ev
= SecCertificateCreateWithBytes(NULL
, comodo_ev_certificate
,
358 sizeof(comodo_ev_certificate
)), NULL
, "create comodo_ev cert");
359 isnt(comodo_aia
= SecCertificateCreateWithBytes(NULL
,
360 comodo_aia_certificate
, sizeof(comodo_aia_certificate
)), NULL
,
361 "create comodo_aia cert");
362 certs
= CFArrayCreateMutable(kCFAllocatorDefault
, 0,
363 &kCFTypeArrayCallBacks
);
364 policies
= CFArrayCreateMutable(kCFAllocatorDefault
, 0,
365 &kCFTypeArrayCallBacks
);
366 sslPolicy
= SecPolicyCreateSSL(false, NULL
); // For now, use SSL client policy to avoid SHA-1 deprecation
367 revPolicy
= SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod
);
368 CFArrayAppendValue(policies
, sslPolicy
);
369 CFArrayAppendValue(policies
, revPolicy
);
371 verifyDate
= CFDateCreate(NULL
, 547600500);
373 /* First run with no intermediate and disallow network fetching.
374 * Evaluation should fail because it couldn't get the intermediate. */
375 CFArrayAppendValue(certs
, ovh
);
376 ok_status(SecTrustCreateWithCertificates(certs
, policies
, &trust
),
378 ok_status(SecTrustSetVerifyDate(trust
, verifyDate
), "set date");
379 ok_status(SecTrustSetNetworkFetchAllowed(trust
, false), "set no network");
380 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
381 is_status(trustResult
, kSecTrustResultRecoverableTrustFailure
,
382 "trust is kSecTrustResultRecoverableTrustFailure");
384 /* Now allow networking. Evaluation should succeed after fetching
385 * the intermediate. */
386 ok_status(SecTrustSetNetworkFetchAllowed(trust
, true), "set allow network");
387 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
388 is_status(trustResult
, kSecTrustResultUnspecified
,
389 "trust is kSecTrustResultUnspecified");
390 CFReleaseNull(trust
);
392 /* Now run with the intermediate returned by the ssl server. */
393 CFArrayAppendValue(certs
, comodo_ev
);
394 ok_status(SecTrustCreateWithCertificates(certs
, sslPolicy
, &trust
),
396 ok_status(SecTrustSetVerifyDate(trust
, verifyDate
), "set date");
397 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
398 is_status(trustResult
, kSecTrustResultUnspecified
,
399 "trust is kSecTrustResultUnspecified");
400 info
= SecTrustCopyInfo(trust
);
401 ev
= (CFBooleanRef
)CFDictionaryGetValue(info
,
402 kSecTrustInfoExtendedValidationKey
);
403 ok(ev
, "extended validation succeeded due to caissuers fetch");
404 //display_anchor_digest(trust);
406 CFReleaseSafe(trust
);
408 /* Now run with the intermediate returned by following the url in the
409 Certificate Access Information Authority (AIA) extension of the ovh
411 CFArrayAppendValue(certs
, comodo_aia
);
412 ok_status(SecTrustCreateWithCertificates(certs
, sslPolicy
, &trust
),
413 "re-create trust with aia intermediate");
414 ok_status(SecTrustSetVerifyDate(trust
, verifyDate
), "set date");
415 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
416 is_status(trustResult
, kSecTrustResultUnspecified
,
417 "trust is kSecTrustResultUnspecified");
418 info
= SecTrustCopyInfo(trust
);
419 ev
= (CFBooleanRef
)CFDictionaryGetValue(info
,
420 kSecTrustInfoExtendedValidationKey
);
421 ok(ev
, "extended validation succeeded");
422 //display_anchor_digest(trust);
424 CFReleaseSafe(trust
);
426 /* Now run with the intermediate returned by following the url in the
427 Certificate Access Information Authority (AIA) extension of the ovh
429 CFArrayRemoveValueAtIndex(certs
, 1);
430 ok_status(SecTrustCreateWithCertificates(certs
, sslPolicy
, &trust
),
431 "re-create trust with aia intermediate");
432 ok_status(SecTrustSetVerifyDate(trust
, verifyDate
), "set date");
433 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
434 is_status(trustResult
, kSecTrustResultUnspecified
,
435 "trust is kSecTrustResultUnspecified");
436 info
= SecTrustCopyInfo(trust
);
437 ev
= (CFBooleanRef
)CFDictionaryGetValue(info
,
438 kSecTrustInfoExtendedValidationKey
);
439 ok(ev
, "extended validation succeeded");
440 //display_anchor_digest(trust);
442 CFReleaseSafe(trust
);
444 /* Common variable cleanup. */
445 CFReleaseSafe(sslPolicy
);
446 CFReleaseSafe(revPolicy
);
447 CFReleaseSafe(certs
);
448 CFReleaseSafe(policies
);
449 CFReleaseSafe(comodo_aia
);
450 CFReleaseSafe(comodo_ev
);
452 CFReleaseSafe(verifyDate
);
455 static void test_aia_https(void) {
456 SecCertificateRef leaf
= NULL
;
457 SecPolicyRef policy
= NULL
;
458 SecTrustRef trust
= NULL
;
459 CFArrayRef certs
= NULL
;
460 CFDateRef verifyDate
= NULL
;
461 CFErrorRef error
= NULL
;
463 leaf
= SecCertificateCreateWithBytes(NULL
, _caissuer_https
, sizeof(_caissuer_https
));
464 const void *v_certs
[] = { leaf
};
466 certs
= CFArrayCreate(NULL
, v_certs
, 1, &kCFTypeArrayCallBacks
);
467 policy
= SecPolicyCreateSSL(true, CFSTR("example.com"));
468 require_noerr_action(SecTrustCreateWithCertificates(certs
, policy
, &trust
), errOut
, fail("failed to create trust object"));
470 verifyDate
= CFDateCreate(NULL
, 546700000.0); // April 29, 2018 at 6:06:40 AM PDT
471 require_noerr_action(SecTrustSetVerifyDate(trust
, verifyDate
), errOut
, fail("failed to set verify date"));
473 #pragma clang diagnostic push
474 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
475 /* Evaluate trust. This cert does not chain to anything trusted and we can't fetch an
476 * intermediate because the URI is https. */
477 is(SecTrustEvaluateWithError(trust
, &error
), false, "leaf with missing intermediate and https CAIssuer URI succeeded");
479 is(CFErrorGetCode(error
), errSecCreateChainFailed
, "got wrong error code for revoked cert, got %ld, expected %d",
480 (long)CFErrorGetCode(error
), errSecCreateChainFailed
);
482 fail("expected trust evaluation to fail and it did not.");
484 #pragma clang diagnostic pop
488 CFReleaseNull(policy
);
489 CFReleaseNull(trust
);
490 CFReleaseNull(certs
);
491 CFReleaseNull(verifyDate
);
492 CFReleaseNull(error
);
495 static void test_results_dictionary_revocation_reason(void) {
496 SecCertificateRef leaf
= NULL
, subCA
= NULL
, root
= NULL
;
497 SecPolicyRef policy
= NULL
;
498 SecTrustRef trust
= NULL
;
499 CFArrayRef certs
= NULL
, anchors
= NULL
;
500 CFDateRef verifyDate
= NULL
;
501 CFErrorRef error
= NULL
;
502 CFDataRef ocspResponse
= NULL
;
504 leaf
= SecCertificateCreateWithBytes(NULL
, _probablyRevokedLeaf
, sizeof(_probablyRevokedLeaf
));
505 subCA
= SecCertificateCreateWithBytes(NULL
, _digiCertSha2SubCA
, sizeof(_digiCertSha2SubCA
));
506 root
= SecCertificateCreateWithBytes(NULL
, _digiCertGlobalRoot
, sizeof(_digiCertGlobalRoot
));
508 const void *v_certs
[] = { leaf
, subCA
};
509 const void *v_anchors
[] = { root
};
511 certs
= CFArrayCreate(NULL
, v_certs
, 2, &kCFTypeArrayCallBacks
);
512 policy
= SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
513 require_noerr_action(SecTrustCreateWithCertificates(certs
, policy
, &trust
), errOut
, fail("failed to create trust object"));
515 anchors
= CFArrayCreate(NULL
, v_anchors
, 1, &kCFTypeArrayCallBacks
);
516 require_noerr_action(SecTrustSetAnchorCertificates(trust
, anchors
), errOut
, fail("failed to set anchors"));
518 verifyDate
= CFDateCreate(NULL
, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
519 require_noerr_action(SecTrustSetVerifyDate(trust
, verifyDate
), errOut
, fail("failed to set verify date"));
521 /* Set the stapled response */
522 ocspResponse
= CFDataCreate(NULL
, _digicertOCSPResponse
, sizeof(_digicertOCSPResponse
));
523 ok_status(SecTrustSetOCSPResponse(trust
, ocspResponse
), "failed to set OCSP response");
525 #pragma clang diagnostic push
526 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
527 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
528 * This cert should come back as revoked. */
529 is(SecTrustEvaluateWithError(trust
, &error
), false, "revoked cert succeeded");
531 is(CFErrorGetCode(error
), errSecCertificateRevoked
, "got wrong error code for revoked cert, got %ld, expected %d",
532 (long)CFErrorGetCode(error
), errSecCertificateRevoked
);
534 /* Verify that the results dictionary contains all the right keys for a revoked cert */
535 CFDictionaryRef result
= SecTrustCopyResult(trust
);
536 isnt(result
, NULL
, "failed to copy result dictionary");
539 CFNumberRef cfreason
= CFNumberCreate(NULL
, kCFNumberSInt64Type
, &reason
);
540 is(CFNumberCompare(cfreason
, CFDictionaryGetValue(result
, kSecTrustRevocationReason
), NULL
), kCFCompareEqualTo
, "expected revocation reason -1");
541 CFReleaseNull(cfreason
);
543 CFReleaseNull(result
);
545 fail("expected trust evaluation to fail and it did not.");
547 #pragma clang diagnostic pop
551 CFReleaseNull(subCA
);
553 CFReleaseNull(policy
);
554 CFReleaseNull(trust
);
555 CFReleaseNull(certs
);
556 CFReleaseNull(anchors
);
557 CFReleaseNull(verifyDate
);
558 CFReleaseNull(error
);
559 CFReleaseNull(ocspResponse
);
562 static void test_results_dictionary_revocation_checked(void) {
563 SecCertificateRef leaf
= NULL
, subCA
= NULL
, root
= NULL
;
564 SecPolicyRef sslPolicy
= NULL
, ocspPolicy
= NULL
;
565 SecTrustRef trust
= NULL
;
566 CFArrayRef certs
= NULL
, anchors
= NULL
, policies
= NULL
;
567 CFDateRef verifyDate
= NULL
;
568 CFErrorRef error
= NULL
;
570 leaf
= SecCertificateCreateWithBytes(NULL
, _ocsp_c0
, sizeof(_ocsp_c0
));
571 subCA
= SecCertificateCreateWithBytes(NULL
, _ocsp_c1
, sizeof(_ocsp_c1
));
572 root
= SecCertificateCreateWithBytes(NULL
, _ocsp_c2
, sizeof(_ocsp_c2
));
574 sslPolicy
= SecPolicyCreateSSL(true, CFSTR("www.apple.com"));
575 ocspPolicy
= SecPolicyCreateRevocation(kSecRevocationOCSPMethod
);
577 const void *v_certs
[] = { leaf
, subCA
};
578 const void *v_anchors
[] = { root
};
579 const void *v_policies
[] = { sslPolicy
, ocspPolicy
};
581 certs
= CFArrayCreate(NULL
, v_certs
, 2, &kCFTypeArrayCallBacks
);
582 policies
= CFArrayCreate(NULL
, v_policies
, 2, &kCFTypeArrayCallBacks
);
583 require_noerr_action(SecTrustCreateWithCertificates(certs
, policies
, &trust
), errOut
, fail("failed to create trust object"));
585 anchors
= CFArrayCreate(NULL
, v_anchors
, 1, &kCFTypeArrayCallBacks
);
586 require_noerr_action(SecTrustSetAnchorCertificates(trust
, anchors
), errOut
, fail("failed to set anchors"));
588 verifyDate
= CFDateCreate(NULL
, 577000000.0); // April 14, 2019 at 10:46:40 PM PDT
589 require_noerr_action(SecTrustSetVerifyDate(trust
, verifyDate
), errOut
, fail("failed to set verify date"));
591 #pragma clang diagnostic push
592 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
593 is(SecTrustEvaluateWithError(trust
, &error
), true, "valid cert failed");
595 /* Verify that the results dictionary contains all the right keys for a valid cert where revocation checked */
596 CFDictionaryRef result
= SecTrustCopyResult(trust
);
597 isnt(result
, NULL
, "failed to copy result dictionary");
599 is(CFDictionaryGetValue(result
, kSecTrustRevocationChecked
), kCFBooleanTrue
, "expected revocation checked flag");
600 CFDateRef validUntil
= CFDictionaryGetValue(result
, kSecTrustRevocationValidUntilDate
);
601 isnt(validUntil
, NULL
, "expected revocation valid until date");
603 ok(CFDateGetAbsoluteTime(validUntil
) > CFAbsoluteTimeGetCurrent(), "expected valid until date in the future");
605 fail("did not get valid until date");
608 CFReleaseNull(result
);
609 #pragma clang diagnostic pop
613 CFReleaseNull(subCA
);
615 CFReleaseNull(ocspPolicy
);
616 CFReleaseNull(sslPolicy
);
617 CFReleaseNull(trust
);
618 CFReleaseNull(certs
);
619 CFReleaseNull(anchors
);
620 CFReleaseNull(policies
);
621 CFReleaseNull(verifyDate
);
622 CFReleaseNull(error
);
625 static int ping_host(char *host_name
){
627 struct sockaddr_in pin
;
628 struct hostent
*nlp_host
;
635 //tries 5 times then give up
636 while ((nlp_host
=gethostbyname(host_name
))==0 && retries
--){
637 printf("Resolve Error! (%s) %d\n", host_name
, h_errno
);
644 bzero(&pin
,sizeof(pin
));
645 pin
.sin_family
=AF_INET
;
646 pin
.sin_addr
.s_addr
=htonl(INADDR_ANY
);
647 pin
.sin_addr
.s_addr
=((struct in_addr
*)(nlp_host
->h_addr
))->s_addr
;
648 pin
.sin_port
=htons(port
);
650 sd
=socket(AF_INET
,SOCK_STREAM
,0);
652 if (connect(sd
,(struct sockaddr
*)&pin
,sizeof(pin
))==-1){
653 printf("connect error! (%s) %d\n", host_name
, errno
);
663 int si_23_sectrust_ocsp(int argc
, char *const *argv
)
666 "EVSecure-ocsp.verisign.com",
667 "EVIntl-ocsp.verisign.com",
668 "EVIntl-aia.verisign.com",
675 unsigned host_cnt
= 0;
679 for (host_cnt
= 0; host_cnt
< sizeof(hosts
)/sizeof(hosts
[0]); host_cnt
++) {
680 if(!ping_host(hosts
[host_cnt
])) {
681 printf("Accessing specific server (%s) failed, check the network!\n", hosts
[host_cnt
]);
687 test_ocsp_responder_policy();
691 test_forced_revocation();
692 test_results_dictionary_revocation_reason();
693 test_results_dictionary_revocation_checked();