]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c
Security-58286.260.20.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / secitem / si-23-sectrust-ocsp.c
1 /*
2 * Copyright (c) 2006-2018 Apple Inc. All Rights Reserved.
3 */
4
5 #include <AssertMacros.h>
6 #include <CoreFoundation/CoreFoundation.h>
7 #include <Security/SecCertificate.h>
8 #include <Security/SecCertificatePriv.h>
9 #include <Security/SecPolicyPriv.h>
10 #include <Security/SecTrustPriv.h>
11 #include <utilities/array_size.h>
12 #include <utilities/SecCFRelease.h>
13 #include <stdlib.h>
14 #include <sys/socket.h>
15 #include <sys/types.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <netdb.h>
19 #include <unistd.h>
20 #include <string.h>
21
22 #include "shared_regressions.h"
23
24 #include "si-23-sectrust-ocsp.h"
25
26 static void tests(void)
27 {
28 SecTrustRef trust;
29 SecCertificateRef cert0, cert1;
30 isnt(cert0 = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0)),
31 NULL, "create cert0");
32 isnt(cert1 = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1)),
33 NULL, "create cert1");
34 CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0,
35 &kCFTypeArrayCallBacks);
36 CFArrayAppendValue(certs, cert0);
37 CFArrayAppendValue(certs, cert1);
38
39 SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.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);
44 CFRelease(sslPolicy);
45 CFRelease(ocspPolicy);
46 ok_status(SecTrustCreateWithCertificates(certs, policies, &trust),
47 "create trust");
48 /* August 14, 2018 at 9:26:40 PM PDT */
49 CFDateRef date = CFDateCreate(NULL, 556000000.0);
50 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
51
52 is(SecTrustGetVerifyTime(trust), 556000000.0, "get date");
53
54 SecTrustResultType trustResult;
55 ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
56 is_status(trustResult, kSecTrustResultUnspecified,
57 "trust is kSecTrustResultUnspecified");
58
59 /* Certificates are only EV if they are also CT. */
60 CFDictionaryRef info = SecTrustCopyInfo(trust);
61 CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(info,
62 kSecTrustInfoExtendedValidationKey);
63 ok(ev, "extended validation succeeded");
64
65 CFReleaseSafe(info);
66 CFReleaseSafe(trust);
67 CFReleaseSafe(policies);
68 CFReleaseSafe(certs);
69 CFReleaseSafe(cert0);
70 CFReleaseSafe(cert1);
71 CFReleaseSafe(date);
72 }
73
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;
81
82 /* August 14, 2018 at 9:26:40 PM PDT */
83 CFDateRef date = CFDateCreate(NULL, 556000000.0);
84
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);
91
92 ok(ocspSignerPolicy = SecPolicyCreateOCSPSigner(),
93 "create ocspSigner policy");
94
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");
101
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");
111
112 CFReleaseNull(leaf);
113 CFReleaseNull(subCA);
114 CFReleaseNull(responderCert);
115 CFReleaseNull(certs);
116 CFReleaseNull(trust);
117 CFReleaseSafe(ocspSignerPolicy);
118 CFReleaseNull(date);
119 }
120
121 static void test_revocation() {
122 SecTrustRef trust;
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);
134
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),
143 "create trust");
144 /* Feb 5th 2015. */
145 CFDateRef date = CFDateCreate(NULL, 444900000);
146 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
147 CFReleaseSafe(date);
148
149 is(SecTrustGetVerifyTime(trust), 444900000, "get date");
150
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;
157 if (results) {
158 CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
159 if (perCertResults) {
160 CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
161 if (leafResults) {
162 revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
163 }
164 }
165 }
166 is(revoked != NULL, true, "revoked result is %@", revoked);
167 CFReleaseSafe(results);
168
169
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
174 validly signed.
175 */
176 /* Dec 11th 2014. */
177 date = CFDateCreate(NULL, 440000000);
178 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
179 CFReleaseSafe(date);
180
181 is(SecTrustGetVerifyTime(trust), 440000000, "get date");
182
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);
187 revoked = NULL;
188 if (results) {
189 CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
190 if (perCertResults) {
191 CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
192 if (leafResults) {
193 revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
194 }
195 }
196 }
197 is(revoked != NULL, true, "revoked result is %@", revoked);
198 CFReleaseSafe(results);
199
200 CFReleaseSafe(trust);
201 CFReleaseSafe(policies);
202 CFReleaseSafe(rcerts);
203 CFReleaseSafe(rcert0);
204 CFReleaseSafe(rcert1);
205 }
206
207 static void test_forced_revocation()
208 {
209 /*
210 * Test verification requiring a positive response from the revocation server
211 */
212
213 OSStatus status;
214 SecCertificateRef smime_leaf_cert;
215 SecCertificateRef smime_CA_cert;
216 SecCertificateRef smime_root_cert;
217
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");
225
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");
230
231 // Default Policies
232 CFMutableArrayRef SMIMEDefaultPolicy = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
233 CFArrayAppendValue(SMIMEDefaultPolicy, smimePolicy);
234
235 // Default Policies + explicit revocation
236 CFMutableArrayRef SMIMEDefaultPolicyWithRevocation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
237 CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, smimePolicy);
238 CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, revocPolicy);
239
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);
244
245 // Valid anchor certs
246 CFMutableArrayRef SMIMEAnchors = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
247 CFArrayAppendValue(SMIMEAnchors, smime_root_cert);
248
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);
255
256 CFDateRef VerifyDate;
257 isnt(VerifyDate = CFDateCreate(NULL, 332900000.0), NULL, "Create verify date");
258 if (!VerifyDate) { goto errOut; }
259
260 // Standard evaluation for the given verify date
261 {
262 SecTrustRef trust = NULL;
263 SecTrustResultType trust_result;
264
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");
269
270 ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate");
271
272 // Check results
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.
277 //
278 is_status(trust_result, kSecTrustResultFatalTrustFailure, "trust is kSecTrustResultFatalTrustFailure");
279
280 CFReleaseNull(trust);
281 }
282
283 // Revocation-required evaluation should fail, since this CA's servers no longer exist
284 // and no valid responses are available
285 {
286 SecTrustRef trust = NULL;
287 SecTrustResultType trust_result;
288
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");
293
294 ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate");
295
296 // Check results
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.
301 //
302 is_status(trust_result, kSecTrustResultFatalTrustFailure, "trust is kSecTrustResultFatalTrustFailure");
303
304 CFReleaseNull(trust);
305 }
306
307 // Free remaining resources
308 errOut:
309 CFReleaseSafe(VerifyDate);
310 CFReleaseSafe(SMIMEDefaultPolicy);
311 CFReleaseSafe(SMIMEDefaultPolicyWithRevocation);
312 CFReleaseSafe(SMIMECertChain);
313 CFReleaseSafe(SMIMEAnchors);
314 }
315
316 #if 0
317 static void hexdump(const uint8_t *bytes, size_t len) {
318 size_t ix;
319 printf("#anchor-sha1: ");
320 for (ix = 0; ix < len; ++ix) {
321 printf("%02X", bytes[ix]);
322 }
323 printf("\n");
324 }
325
326 static void datadump(const uint8_t *bytes, size_t len) {
327 size_t ix;
328 printf("#anchor-sha1: ");
329 for (ix = 0; ix < len; ++ix) {
330 printf("%c", bytes[ix]);
331 }
332 printf("\n");
333 }
334
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));
341 }
342 #endif
343
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;
353
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);
370 /* May 9th 2018. */
371 verifyDate = CFDateCreate(NULL, 547600500);
372
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),
377 "create 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");
383
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);
391
392 /* Now run with the intermediate returned by the ssl server. */
393 CFArrayAppendValue(certs, comodo_ev);
394 ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust),
395 "create 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);
405 CFReleaseSafe(info);
406 CFReleaseSafe(trust);
407
408 /* Now run with the intermediate returned by following the url in the
409 Certificate Access Information Authority (AIA) extension of the ovh
410 leaf certificate. */
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);
423 CFReleaseSafe(info);
424 CFReleaseSafe(trust);
425
426 /* Now run with the intermediate returned by following the url in the
427 Certificate Access Information Authority (AIA) extension of the ovh
428 leaf certificate. */
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);
441 CFReleaseSafe(info);
442 CFReleaseSafe(trust);
443
444 /* Common variable cleanup. */
445 CFReleaseSafe(sslPolicy);
446 CFReleaseSafe(revPolicy);
447 CFReleaseSafe(certs);
448 CFReleaseSafe(policies);
449 CFReleaseSafe(comodo_aia);
450 CFReleaseSafe(comodo_ev);
451 CFReleaseSafe(ovh);
452 CFReleaseSafe(verifyDate);
453 }
454
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;
462
463 leaf = SecCertificateCreateWithBytes(NULL, _caissuer_https, sizeof(_caissuer_https));
464 const void *v_certs[] = { leaf };
465
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"));
469
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"));
472
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");
478 if (error) {
479 is(CFErrorGetCode(error), errSecCreateChainFailed, "got wrong error code for revoked cert, got %ld, expected %d",
480 (long)CFErrorGetCode(error), errSecCreateChainFailed);
481 } else {
482 fail("expected trust evaluation to fail and it did not.");
483 }
484 #pragma clang diagnostic pop
485
486 errOut:
487 CFReleaseNull(leaf);
488 CFReleaseNull(policy);
489 CFReleaseNull(trust);
490 CFReleaseNull(certs);
491 CFReleaseNull(verifyDate);
492 CFReleaseNull(error);
493 }
494
495 static void test_set_fetch_allowed(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
503 leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf));
504 subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA));
505 root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot));
506
507 const void *v_certs[] = { leaf, subCA };
508 const void *v_anchors[] = { root };
509
510 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
511 policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
512 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
513
514 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
515 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
516
517 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
518 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
519
520 /* Clear the OCSP cache in case there are old responses for this cert. */
521 ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed");
522 CFReleaseNull(error);
523
524 /* Set no fetch allowed */
525 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
526
527 #pragma clang diagnostic push
528 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
529 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
530 * Since network fetch is not allowed and we fail open, this cert should come back as trusted. */
531 ok(SecTrustEvaluateWithError(trust, &error), "non-definitive revoked cert without network failed");
532 CFReleaseNull(error);
533
534 /* Set fetch allowed */
535 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, true), errOut, fail("failed to set network fetch allowed"));
536
537 /* Evaluate trust. SetFetchAllowed should have reset the trust result, so now we should re-do the evaluation and get a revoked failure. */
538 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
539 if (error) {
540 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
541 (long)CFErrorGetCode(error), errSecCertificateRevoked);
542 } else {
543 fail("expected trust evaluation to fail and it did not.");
544 }
545
546 #pragma clang diagnostic pop
547
548 errOut:
549 CFReleaseNull(leaf);
550 CFReleaseNull(subCA);
551 CFReleaseNull(root);
552 CFReleaseNull(policy);
553 CFReleaseNull(trust);
554 CFReleaseNull(certs);
555 CFReleaseNull(anchors);
556 CFReleaseNull(verifyDate);
557 CFReleaseNull(error);
558 }
559
560 static void test_check_if_trusted(void) {
561 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
562 SecPolicyRef sslPolicy = NULL, revocationPolicy = NULL;
563 SecTrustRef trust = NULL;
564 CFArrayRef certs = NULL, anchors = NULL, policies = NULL;
565 CFDateRef verifyDate = NULL, badVerifyDate = NULL;
566 CFErrorRef error = NULL;
567
568 leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf));
569 subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA));
570 root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot));
571
572 sslPolicy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
573 revocationPolicy = SecPolicyCreateRevocation(kSecRevocationCheckIfTrusted);
574
575 const void *v_certs[] = { leaf, subCA };
576 const void *v_anchors[] = { root };
577 const void *v_policies[] = { sslPolicy, revocationPolicy };
578
579 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
580 policies = CFArrayCreate(NULL, v_policies, 2, &kCFTypeArrayCallBacks);
581 require_noerr_action(SecTrustCreateWithCertificates(certs, policies, &trust), errOut, fail("failed to create trust object"));
582
583 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
584 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
585 badVerifyDate = CFDateCreate(NULL, 490000000.0); // July 12, 2016 at 12:06:40 AM PDT (before cert issued)
586 require_noerr_action(SecTrustSetVerifyDate(trust, badVerifyDate), errOut, fail("failed to set verify date"));
587
588 /* Clear the OCSP cache in case there are old responses for this cert. */
589 ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed");
590 CFReleaseNull(error);
591
592 /* Set no fetch allowed */
593 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
594
595 #pragma clang diagnostic push
596 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
597 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
598 * Since we are evaluating it at a time before it was issued, it should come back as untrusted
599 * due to the temporal validity failure, but not due to revocation since we couldn't check for this
600 * untrusted chain. */
601 is(SecTrustEvaluateWithError(trust, &error), false, "not yet valid cert succeeded trust evaluation");
602 if (error) {
603 is(CFErrorGetCode(error), errSecCertificateExpired, "got wrong error code for expired cert");
604 } else {
605 fail("expected trust evaluation to fail and it did not.");
606 }
607 CFReleaseNull(error);
608
609 /* Set verify date within validity period */
610 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
611 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
612
613 /* Evaluate trust. Now that we trust the chain, we should do a revocation check and get a revocation failure. */
614 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
615 if (error) {
616 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
617 (long)CFErrorGetCode(error), errSecCertificateRevoked);
618 } else {
619 fail("expected trust evaluation to fail and it did not.");
620 }
621 #pragma clang diagnostic pop
622
623 errOut:
624 CFReleaseNull(leaf);
625 CFReleaseNull(subCA);
626 CFReleaseNull(root);
627 CFReleaseNull(sslPolicy);
628 CFReleaseNull(revocationPolicy);
629 CFReleaseNull(trust);
630 CFReleaseNull(certs);
631 CFReleaseNull(anchors);
632 CFReleaseNull(policies);
633 CFReleaseNull(verifyDate);
634 CFReleaseNull(badVerifyDate);
635 CFReleaseNull(error);
636 }
637
638 static void test_cache(void) {
639 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
640 SecPolicyRef policy = NULL;
641 SecTrustRef trust = NULL;
642 CFArrayRef certs = NULL, anchors = NULL;
643 CFDateRef verifyDate = NULL;
644 CFErrorRef error = NULL;
645
646 leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf));
647 subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA));
648 root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot));
649
650 const void *v_certs[] = { leaf, subCA };
651 const void *v_anchors[] = { root };
652
653 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
654 policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
655 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
656
657 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
658 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
659
660 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
661 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
662
663 /* Clear the OCSP cache in case there are old responses for this cert. */
664 ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed");
665 CFReleaseNull(error);
666
667 #pragma clang diagnostic push
668 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
669 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
670 * This cert should come back as revoked after a network-based fetch. */
671 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded");
672 if (error) {
673 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
674 (long)CFErrorGetCode(error), errSecCertificateRevoked);
675 } else {
676 fail("expected trust evaluation to fail and it did not.");
677 }
678
679 /* Set no fetch allowed, so we're relying on the cached response from above */
680 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
681
682 /* Evaluate trust. Cached response should tell us that it's revoked. */
683 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded");
684 if (error) {
685 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
686 (long)CFErrorGetCode(error), errSecCertificateRevoked);
687 } else {
688 fail("expected trust evaluation to fail and it did not.");
689 }
690
691 #pragma clang diagnostic pop
692
693 errOut:
694 CFReleaseNull(leaf);
695 CFReleaseNull(subCA);
696 CFReleaseNull(root);
697 CFReleaseNull(policy);
698 CFReleaseNull(trust);
699 CFReleaseNull(certs);
700 CFReleaseNull(anchors);
701 CFReleaseNull(verifyDate);
702 CFReleaseNull(error);
703 }
704
705 static void test_stapled_revoked_response(void) {
706 SecCertificateRef leaf = NULL, subCA = NULL, root = NULL;
707 SecPolicyRef policy = NULL;
708 SecTrustRef trust = NULL;
709 CFArrayRef certs = NULL, anchors = NULL;
710 CFDateRef verifyDate = NULL;
711 CFErrorRef error = NULL;
712 CFDataRef ocspResponse = NULL;
713
714 leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf));
715 subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA));
716 root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot));
717
718 const void *v_certs[] = { leaf, subCA };
719 const void *v_anchors[] = { root };
720
721 certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks);
722 policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com"));
723 require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object"));
724
725 anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks);
726 require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors"));
727
728 verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT
729 require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date"));
730
731 /* Set the stapled response */
732 ocspResponse = CFDataCreate(NULL, _digicertOCSPResponse, sizeof(_digicertOCSPResponse));
733 ok_status(SecTrustSetOCSPResponse(trust, ocspResponse), "failed to set OCSP response");
734
735 /* Clear the OCSP cache in case there are old responses for this cert. */
736 ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed");
737 CFReleaseNull(error);
738
739 /* Set no fetch allowed, so we're relying on the stapled response from above */
740 require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed"));
741
742 #pragma clang diagnostic push
743 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
744 /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com.
745 * This cert should come back as revoked because of the stapled revoked response. */
746 is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with stapled response succeeded");
747 if (error) {
748 is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d",
749 (long)CFErrorGetCode(error), errSecCertificateRevoked);
750 } else {
751 fail("expected trust evaluation to fail and it did not.");
752 }
753
754 #pragma clang diagnostic pop
755
756 errOut:
757 CFReleaseNull(leaf);
758 CFReleaseNull(subCA);
759 CFReleaseNull(root);
760 CFReleaseNull(policy);
761 CFReleaseNull(trust);
762 CFReleaseNull(certs);
763 CFReleaseNull(anchors);
764 CFReleaseNull(verifyDate);
765 CFReleaseNull(error);
766 CFReleaseNull(ocspResponse);
767 }
768
769 static int ping_host(char *host_name){
770
771 struct sockaddr_in pin;
772 struct hostent *nlp_host;
773 int sd;
774 int port;
775 int retries = 5;
776
777 port=80;
778
779 //tries 5 times then give up
780 while ((nlp_host=gethostbyname(host_name))==0 && retries--){
781 printf("Resolve Error! (%s) %d\n", host_name, h_errno);
782 sleep(1);
783 }
784
785 if(nlp_host==0)
786 return 0;
787
788 bzero(&pin,sizeof(pin));
789 pin.sin_family=AF_INET;
790 pin.sin_addr.s_addr=htonl(INADDR_ANY);
791 pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr;
792 pin.sin_port=htons(port);
793
794 sd=socket(AF_INET,SOCK_STREAM,0);
795
796 if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){
797 printf("connect error! (%s) %d\n", host_name, errno);
798 close(sd);
799 return 0;
800 }
801 else{
802 close(sd);
803 return 1;
804 }
805 }
806
807 int si_23_sectrust_ocsp(int argc, char *const *argv)
808 {
809 char *hosts[] = {
810 "EVSecure-ocsp.verisign.com",
811 "EVIntl-ocsp.verisign.com",
812 "EVIntl-aia.verisign.com",
813 "ocsp.comodoca.com",
814 "crt.comodoca.com",
815 "ocsp.entrust.net",
816 "ocsp.digicert.com",
817 };
818
819 unsigned host_cnt = 0;
820
821 plan_tests(95);
822
823 for (host_cnt = 0; host_cnt < sizeof(hosts)/sizeof(hosts[0]); host_cnt ++) {
824 if(!ping_host(hosts[host_cnt])) {
825 printf("Accessing specific server (%s) failed, check the network!\n", hosts[host_cnt]);
826 return 0;
827 }
828 }
829
830 tests();
831 test_ocsp_responder_policy();
832 test_aia();
833 test_aia_https();
834 test_revocation();
835 test_forced_revocation();
836 test_set_fetch_allowed();
837 test_check_if_trusted();
838 test_cache();
839 test_stapled_revoked_response();
840
841 return 0;
842 }