2 * Copyright (c) 2006-2010,2012-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 <Security/SecTrust.h>
12 #include <Security/SecItem.h>
13 #include <utilities/array_size.h>
14 #include <utilities/SecCFWrappers.h>
17 #include <Security/SecTrustSettings.h>
20 #include <Security/SecInternal.h>
21 #include <ipc/securityd_client.h>
24 #include "shared_regressions.h"
25 #include "si-20-sectrust.h"
27 /* Test SecTrust API. */
28 static void basic_tests(void)
30 SecTrustRef trust
= NULL
;
31 CFArrayRef _anchors
= NULL
, certs
= NULL
, anchors
= NULL
, replacementPolicies
;
32 SecCertificateRef cert0
= NULL
, cert1
= NULL
, _root
= NULL
, cert_xedge2
= NULL
, garthc2
= NULL
;
33 SecPolicyRef policy
= NULL
, replacementPolicy
= NULL
, replacementPolicy2
= NULL
;
34 CFDateRef date
= NULL
;
35 CFDataRef c0_serial
= NULL
, serial
= NULL
;
36 CFDictionaryRef query
= NULL
;
38 isnt(cert0
= SecCertificateCreateWithBytes(NULL
, _c0
, sizeof(_c0
)),
39 NULL
, "create cert0");
40 isnt(cert1
= SecCertificateCreateWithBytes(NULL
, _c1
, sizeof(_c1
)),
41 NULL
, "create cert1");
42 const void *v_certs
[] = {
46 policy
= SecPolicyCreateSSL(false, NULL
);
47 certs
= CFArrayCreate(NULL
, v_certs
,
48 array_size(v_certs
), &kCFTypeArrayCallBacks
);
50 /* SecTrustCreateWithCertificates failures. */
51 is_status(SecTrustCreateWithCertificates(kCFBooleanTrue
, policy
, &trust
),
52 errSecParam
, "create trust with boolean instead of cert");
53 is_status(SecTrustCreateWithCertificates(cert0
, kCFBooleanTrue
, &trust
),
54 errSecParam
, "create trust with boolean instead of policy");
56 /* SecTrustCreateWithCertificates using array of certs. */
57 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
), "create trust");
59 /* NOTE: prior to <rdar://11810677 SecTrustGetCertificateCount would return 1 at this point.
60 * Now, however, we do an implicit SecTrustEvaluate to build the chain if it has not yet been
61 * evaluated, so we now expect the full chain length.
63 is(SecTrustGetCertificateCount(trust
), 3, "cert count is 3");
64 is(SecTrustGetCertificateAtIndex(trust
, 0), cert0
, "cert 0 is leaf");
67 isnt(date
= CFDateCreateForGregorianZuluMoment(NULL
, 2018, 4, 14, 12, 0, 0),
68 NULL
, "create verify date");
69 if (!date
) { goto errOut
; }
70 ok_status(SecTrustSetVerifyDate(trust
, date
), "set date");
72 SecTrustResultType trustResult
;
77 skip("Can't fail to connect to securityd in NO_SERVER mode", 4, false);
79 // Test Restore OS environment
80 SecServerSetTrustdMachServiceName("com.apple.security.doesn't-exist");
81 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust without securityd running");
82 is_status(trustResult
, kSecTrustResultInvalid
, "trustResult is kSecTrustResultInvalid");
83 is(SecTrustGetCertificateCount(trust
), 1, "cert count is 1 without securityd running");
84 SecKeyRef pubKey
= NULL
;
85 ok(pubKey
= SecTrustCopyPublicKey(trust
), "copy public key without securityd running");
86 CFReleaseNull(pubKey
);
87 SecServerSetTrustdMachServiceName("com.apple.trustd");
88 // End of Restore OS environment tests
92 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
93 is_status(trustResult
, kSecTrustResultUnspecified
,
94 "trustResult is kSecTrustResultUnspecified");
96 is(SecTrustGetCertificateCount(trust
), 3, "cert count is 3");
98 if (!cert0
) { goto errOut
; }
99 c0_serial
= CFDataCreate(NULL
, _c0_serial
, sizeof(_c0_serial
));
101 ok(serial
= SecCertificateCopySerialNumber(cert0
), "copy cert0 serial");
103 CFErrorRef error
= NULL
;
104 ok(serial
= SecCertificateCopySerialNumber(cert0
, &error
), "copy cert0 serial");
105 CFReleaseNull(error
);
107 ok(CFEqual(c0_serial
, serial
), "serial matches");
108 CFReleaseNull(serial
);
109 CFReleaseNull(c0_serial
);
111 anchors
= CFArrayCreate(NULL
, (const void **)&cert1
, 1, &kCFTypeArrayCallBacks
);
112 ok_status(SecTrustSetAnchorCertificates(trust
, anchors
), "set anchors");
113 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
114 is_status(trustResult
, kSecTrustResultUnspecified
,
115 "trust is kSecTrustResultUnspecified");
116 is(SecTrustGetCertificateCount(trust
), 2, "cert count is 2");
118 CFArrayRef certArray
;
119 ok_status(SecTrustCopyAnchorCertificates(&certArray
), "copy anchors");
120 CFReleaseSafe(certArray
);
121 ok_status(SecTrustSettingsCopyCertificates(kSecTrustSettingsDomainSystem
, &certArray
), "copy certificates");
122 CFReleaseSafe(certArray
);
124 CFReleaseNull(anchors
);
125 anchors
= CFArrayCreate(NULL
, NULL
, 0, NULL
);
126 ok_status(SecTrustSetAnchorCertificates(trust
, anchors
), "set empty anchors list");
127 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
128 is_status(trustResult
, kSecTrustResultRecoverableTrustFailure
,
129 "trust is kSecTrustResultRecoverableTrustFailure");
130 CFReleaseNull(anchors
);
132 ok_status(SecTrustSetAnchorCertificatesOnly(trust
, false), "trust passed in anchors and system anchors");
133 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
134 is_status(trustResult
, kSecTrustResultUnspecified
,
135 "trust is kSecTrustResultUnspecified");
137 ok_status(SecTrustSetAnchorCertificatesOnly(trust
, true), "only trust passed in anchors (default)");
138 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
139 is_status(trustResult
, kSecTrustResultRecoverableTrustFailure
,
140 "trust is kSecTrustResultRecoverableTrustFailure");
142 /* Test cert_1 intermediate from the keychain. */
143 CFReleaseNull(trust
);
144 ok_status(SecTrustCreateWithCertificates(cert0
, policy
, &trust
),
145 "create trust with single cert0");
146 ok_status(SecTrustSetVerifyDate(trust
, date
), "set date");
149 query
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
,
150 kSecClass
, kSecClassCertificate
, kSecValueRef
, cert1
, NULL
);
151 ok_status(SecItemAdd(query
, NULL
), "add cert1 to keychain");
152 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
153 // Cleanup added cert1.
154 ok_status(SecItemDelete(query
), "remove cert1 from keychain");
155 CFReleaseNull(query
);
156 is_status(trustResult
, kSecTrustResultUnspecified
,
157 "trust is kSecTrustResultUnspecified");
158 is(SecTrustGetCertificateCount(trust
), 3, "cert count is 3");
160 /* Set certs to be the xedge2 leaf. */
161 CFReleaseNull(certs
);
162 isnt(cert_xedge2
= SecCertificateCreateWithBytes(NULL
, xedge2_certificate
,
163 sizeof(xedge2_certificate
)), NULL
, "create cert_xedge2");
164 certs
= CFArrayCreate(NULL
, (const void **)&cert_xedge2
, 1, &kCFTypeArrayCallBacks
);
166 CFReleaseNull(trust
);
167 CFReleaseNull(policy
);
170 policy
= SecPolicyCreateSSL(server
, CFSTR("xedge2.apple.com"));
171 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
),
172 "create trust for ssl server xedge2.apple.com");
174 /* This test uses a cert whose root is no longer in our trust store,
175 * so we need to explicitly set it as a trusted anchor
177 isnt(_root
= SecCertificateCreateWithBytes(NULL
, entrust1024RootCA
, sizeof(entrust1024RootCA
)),
178 NULL
, "create root");
179 const void *v_roots
[] = { _root
};
180 isnt(_anchors
= CFArrayCreate(NULL
, v_roots
, array_size(v_roots
), &kCFTypeArrayCallBacks
),
181 NULL
, "create anchors");
182 if (!_anchors
) { goto errOut
; }
183 ok_status(SecTrustSetAnchorCertificates(trust
, _anchors
), "set anchors");
186 date
= CFDateCreate(NULL
, 252288000.0);
187 ok_status(SecTrustSetVerifyDate(trust
, date
), "set xedge2 trust date to Jan 1st 2009");
188 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate xedge2 trust");
189 is_status(trustResult
, kSecTrustResultUnspecified
,
190 "trust is kSecTrustResultUnspecified");
192 CFReleaseNull(trust
);
193 CFReleaseNull(policy
);
195 policy
= SecPolicyCreateSSL(server
, CFSTR("xedge2.apple.com"));
196 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
),
197 "create trust for ssl client xedge2.apple.com");
198 ok_status(SecTrustSetAnchorCertificates(trust
, _anchors
), "set anchors");
199 ok_status(SecTrustSetVerifyDate(trust
, date
), "set xedge2 trust date to Jan 1st 2009");
200 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate xedge2 trust");
201 is_status(trustResult
, kSecTrustResultRecoverableTrustFailure
,
202 "trust is kSecTrustResultRecoverableTrustFailure");
204 CFReleaseNull(trust
);
205 CFReleaseNull(policy
);
207 policy
= SecPolicyCreateIPSec(server
, CFSTR("xedge2.apple.com"));
208 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
),
209 "create trust for ip server xedge2.apple.com");
210 ok_status(SecTrustSetAnchorCertificates(trust
, _anchors
), "set anchors");
211 ok_status(SecTrustSetVerifyDate(trust
, date
), "set xedge2 trust date to Jan 1st 2009");
212 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate xedge2 trust");
214 /* Although this shouldn't be a valid ipsec cert, since we no longer
215 check for ekus in the ipsec policy it is. */
216 is_status(trustResult
, kSecTrustResultRecoverableTrustFailure
,
217 "trust is kSecTrustResultRecoverableTrustFailure");
219 is_status(trustResult
, kSecTrustResultUnspecified
,
220 "trust is kSecTrustResultUnspecified");
223 CFReleaseNull(trust
);
224 CFReleaseNull(policy
);
226 policy
= SecPolicyCreateSSL(server
, CFSTR("nowhere.com"));
227 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
),
228 "create trust for ssl server nowhere.com");
229 replacementPolicy
= SecPolicyCreateSSL(server
, CFSTR("xedge2.apple.com"));
230 SecTrustSetPolicies(trust
, replacementPolicy
);
231 CFReleaseNull(replacementPolicy
);
232 ok_status(SecTrustSetAnchorCertificates(trust
, _anchors
), "set anchors");
233 ok_status(SecTrustSetVerifyDate(trust
, date
), "set xedge2 trust date to Jan 1st 2009");
234 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate xedge2 trust");
235 is_status(trustResult
, kSecTrustResultUnspecified
,
236 "trust is kSecTrustResultUnspecified");
238 CFReleaseNull(trust
);
239 CFReleaseNull(policy
);
241 policy
= SecPolicyCreateSSL(server
, CFSTR("nowhere.com"));
242 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
),
243 "create trust for ssl server nowhere.com");
244 replacementPolicy2
= SecPolicyCreateSSL(server
, CFSTR("xedge2.apple.com"));
245 replacementPolicies
= CFArrayCreate(kCFAllocatorDefault
, (CFTypeRef
*)&replacementPolicy2
, 1, &kCFTypeArrayCallBacks
);
246 SecTrustSetPolicies(trust
, replacementPolicies
);
247 CFReleaseNull(replacementPolicy2
);
248 CFReleaseNull(replacementPolicies
);
249 ok_status(SecTrustSetAnchorCertificates(trust
, _anchors
), "set anchors");
250 ok_status(SecTrustSetVerifyDate(trust
, date
), "set xedge2 trust date to Jan 1st 2009");
251 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate xedge2 trust");
252 is_status(trustResult
, kSecTrustResultUnspecified
,
253 "trust is kSecTrustResultUnspecified");
255 /* Test self signed ssl cert with cert itself set as anchor. */
256 CFReleaseNull(trust
);
257 CFReleaseNull(policy
);
258 CFReleaseNull(certs
);
261 isnt(garthc2
= SecCertificateCreateWithBytes(NULL
, garthc2_certificate
,
262 sizeof(garthc2_certificate
)), NULL
, "create garthc2");
263 certs
= CFArrayCreate(NULL
, (const void **)&garthc2
, 1, &kCFTypeArrayCallBacks
);
264 policy
= SecPolicyCreateSSL(server
, CFSTR("garthc2.apple.com"));
265 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
),
266 "create trust for ip server garthc2.apple.com");
267 date
= CFDateCreate(NULL
, 269568000.0);
268 ok_status(SecTrustSetVerifyDate(trust
, date
),
269 "set garthc2 trust date to Aug 2009");
270 ok_status(SecTrustSetAnchorCertificates(trust
, certs
),
271 "set garthc2 as anchor");
272 ok_status(SecTrustEvaluate(trust
, &trustResult
),
273 "evaluate self signed cert with cert as anchor");
274 is_status(trustResult
, kSecTrustResultUnspecified
,
275 "trust is kSecTrustResultUnspecified");
279 CFReleaseSafe(garthc2
);
280 CFReleaseSafe(cert_xedge2
);
281 CFReleaseSafe(anchors
);
282 CFReleaseSafe(trust
);
283 CFReleaseSafe(serial
);
284 CFReleaseSafe(c0_serial
);
285 CFReleaseSafe(policy
);
286 CFReleaseSafe(certs
);
287 CFReleaseSafe(cert0
);
288 CFReleaseSafe(cert1
);
291 CFReleaseSafe(_root
);
292 CFReleaseSafe(_anchors
);
295 static void negative_integer_tests(void)
297 /* Test that we can handle and fix up negative integer value(s) in ECDSA signature */
298 const void *negIntSigLeaf
;
299 isnt(negIntSigLeaf
= SecCertificateCreateWithBytes(NULL
, _leaf_NegativeIntInSig
,
300 sizeof(_leaf_NegativeIntInSig
)), NULL
, "create negIntSigLeaf");
301 CFArrayRef certs
= NULL
;
302 isnt(certs
= CFArrayCreate(NULL
, &negIntSigLeaf
, 1, &kCFTypeArrayCallBacks
), NULL
, "failed to create certs array");
303 SecPolicyRef policy
= NULL
;
304 isnt(policy
= SecPolicyCreateiAP(), NULL
, "failed to create policy");
305 SecTrustRef trust
= NULL
;
306 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
),
307 "create trust for negIntSigLeaf");
309 const void *rootAACA2
;
310 isnt(rootAACA2
= SecCertificateCreateWithBytes(NULL
, _root_AACA2
,
311 sizeof(_root_AACA2
)), NULL
, "create rootAACA2");
312 CFArrayRef anchors
= NULL
;
313 isnt(anchors
= CFArrayCreate(NULL
, &rootAACA2
, 1, &kCFTypeArrayCallBacks
), NULL
, "failed to create anchors array");
314 if (!anchors
) { goto errOut
; }
315 ok_status(SecTrustSetAnchorCertificates(trust
, anchors
), "set anchor certificates");
317 SecTrustResultType trustResult
;
318 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust");
319 is_status(trustResult
, kSecTrustResultUnspecified
, "expected kSecTrustResultUnspecified");
322 CFReleaseNull(trust
);
323 CFReleaseNull(certs
);
324 CFReleaseNull(anchors
);
325 CFReleaseNull(negIntSigLeaf
);
326 CFReleaseNull(rootAACA2
);
327 CFReleaseNull(policy
);
330 static void rsa8k_tests(void)
332 /* Test prt_forest_fi that have a 8k RSA key */
333 const void *prt_forest_fi
;
334 isnt(prt_forest_fi
= SecCertificateCreateWithBytes(NULL
, prt_forest_fi_certificate
,
335 sizeof(prt_forest_fi_certificate
)), NULL
, "create prt_forest_fi");
336 CFArrayRef certs
= NULL
;
337 isnt(certs
= CFArrayCreate(NULL
, &prt_forest_fi
, 1, &kCFTypeArrayCallBacks
), NULL
, "failed to create cert array");
338 SecPolicyRef policy
= NULL
;
339 isnt(policy
= SecPolicyCreateSSL(false, CFSTR("owa.prt-forest.fi")), NULL
, "failed to create policy");
340 SecTrustRef trust
= NULL
;
341 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
),
342 "create trust for ip client owa.prt-forest.fi");
343 CFDateRef date
= CFDateCreate(NULL
, 391578321.0);
344 ok_status(SecTrustSetVerifyDate(trust
, date
),
345 "set owa.prt-forest.fi trust date to May 2013");
347 SecKeyRef pubkey
= SecTrustCopyPublicKey(trust
);
348 isnt(pubkey
, NULL
, "pubkey returned");
350 CFReleaseNull(certs
);
351 CFReleaseNull(prt_forest_fi
);
352 CFReleaseNull(policy
);
353 CFReleaseNull(trust
);
354 CFReleaseNull(pubkey
);
358 static void date_tests(void)
360 /* Test long-lived cert chain that expires in 9999 */
361 CFDateRef date
= NULL
;
362 const void *leaf
, *root
;
363 isnt(leaf
= SecCertificateCreateWithBytes(NULL
, longleaf
, sizeof(longleaf
)), NULL
, "create leaf");
364 isnt(root
= SecCertificateCreateWithBytes(NULL
, longroot
, sizeof(longroot
)), NULL
, "create root");
366 CFArrayRef certs
= NULL
;
367 isnt(certs
= CFArrayCreate(NULL
, &leaf
, 1, &kCFTypeArrayCallBacks
), NULL
, "failed to create cert array");
368 CFArrayRef anchors
= NULL
;
369 isnt(anchors
= CFArrayCreate(NULL
, &root
, 1, &kCFTypeArrayCallBacks
), NULL
, "failed to create anchors array");
371 SecPolicyRef policy
= NULL
;
372 isnt(policy
= SecPolicyCreateBasicX509(), NULL
, "failed to create policy");
373 SecTrustRef trust
= NULL
;
374 SecTrustResultType trustResult
;
375 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
), "create trust");
376 if (!anchors
) { goto errOut
; }
377 ok_status(SecTrustSetAnchorCertificates(trust
, anchors
), "set anchors");
379 /* September 4, 2013 (prior to "notBefore" date of 2 April 2014, should fail) */
380 isnt(date
= CFDateCreate(NULL
, 400000000), NULL
, "failed to create date");
381 if (!date
) { goto errOut
; }
382 ok_status(SecTrustSetVerifyDate(trust
, date
), "set trust date to 23 Sep 2013");
383 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust on 23 Sep 2013");
384 is_status(trustResult
, kSecTrustResultRecoverableTrustFailure
, "expected kSecTrustResultRecoverableTrustFailure");
387 /* January 17, 2016 (recent date within validity period, should succeed) */
388 isnt(date
= CFDateCreate(NULL
, 474747474), NULL
, "failed to create date");
389 if (!date
) { goto errOut
; }
390 ok_status(SecTrustSetVerifyDate(trust
, date
), "set trust date to 17 Jan 2016");
391 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust on 17 Jan 2016");
392 is_status(trustResult
, kSecTrustResultUnspecified
, "expected kSecTrustResultUnspecified");
395 /* December 20, 9999 (far-future date within validity period, should succeed) */
396 isnt(date
= CFDateCreate(NULL
, 252423000000), NULL
, "failed to create date");
397 if (!date
) { goto errOut
; }
398 ok_status(SecTrustSetVerifyDate(trust
, date
), "set trust date to 20 Dec 9999");
399 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust on 20 Dec 9999");
400 is_status(trustResult
, kSecTrustResultUnspecified
, "expected kSecTrustResultUnspecified");
403 /* January 12, 10000 (after the "notAfter" date of 31 Dec 9999, should fail) */
404 isnt(date
= CFDateCreate(NULL
, 252425000000), NULL
, "failed to create date");
405 if (!date
) { goto errOut
; }
406 ok_status(SecTrustSetVerifyDate(trust
, date
), "set trust date to 12 Jan 10000");
407 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate trust on 12 Jan 10000");
408 is_status(trustResult
, kSecTrustResultRecoverableTrustFailure
, "expected kSecTrustResultRecoverableTrustFailure");
412 CFReleaseNull(trust
);
413 CFReleaseNull(policy
);
414 CFReleaseNull(anchors
);
415 CFReleaseNull(certs
);
420 static bool test_chain_of_three(uint8_t *cert0
, size_t cert0len
,
421 uint8_t *cert1
, size_t cert1len
,
422 uint8_t *root
, size_t rootlen
,
423 bool should_succeed
, CF_RETURNS_RETAINED CFStringRef
*failureReason
)
427 const void *secCert0
, *secCert1
, *secRoot
;
428 isnt(secCert0
= SecCertificateCreateWithBytes(NULL
, cert0
, cert0len
), NULL
, "create leaf");
429 isnt(secCert1
= SecCertificateCreateWithBytes(NULL
, cert1
, cert1len
), NULL
, "create subCA");
430 isnt(secRoot
= SecCertificateCreateWithBytes(NULL
, root
, rootlen
), NULL
, "create root");
432 const void *v_certs
[] = { secCert0
, secCert1
};
433 CFArrayRef certs
= NULL
;
434 isnt(certs
= CFArrayCreate(NULL
, v_certs
, sizeof(v_certs
)/sizeof(*v_certs
), &kCFTypeArrayCallBacks
),
435 NULL
, "failed to create cert array");
436 CFArrayRef anchors
= NULL
;
437 isnt(anchors
= CFArrayCreate(NULL
, &secRoot
, 1, &kCFTypeArrayCallBacks
), NULL
, "failed to create anchors array");
439 SecPolicyRef policy
= NULL
;
440 isnt(policy
= SecPolicyCreateBasicX509(), NULL
, "failed to create policy");
441 CFDateRef date
= NULL
;
442 isnt(date
= CFDateCreate(NULL
, 472100000.0), NULL
, "failed to create date"); // 17 Dec 2015
444 SecTrustRef trust
= NULL
;
445 SecTrustResultType trustResult
;
446 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
), "failed to create trust");
447 if (!date
) { goto errOut
; }
448 ok_status(SecTrustSetVerifyDate(trust
, date
), "failed to set verify date");
449 if (!anchors
) { goto errOut
; }
450 ok_status(SecTrustSetAnchorCertificates(trust
, anchors
), "failed to set anchors");
452 ok_status(SecTrustEvaluate(trust
, &trustResult
), "evaluate chain");
453 is(SecTrustGetCertificateCount(trust
), 3, "expected chain of 3");
454 bool did_succeed
= (trustResult
== kSecTrustResultUnspecified
|| trustResult
== kSecTrustResultProceed
);
456 if (failureReason
&& should_succeed
&& !did_succeed
) {
457 *failureReason
= SecTrustCopyFailureDescription(trust
);
458 } else if (failureReason
&& !should_succeed
&& did_succeed
) {
459 *failureReason
= CFSTR("expected kSecTrustResultFatalTrustFailure");
462 if ((should_succeed
&& did_succeed
) || (!should_succeed
&& !did_succeed
)) {
467 CFReleaseNull(secCert0
);
468 CFReleaseNull(secCert1
);
469 CFReleaseNull(secRoot
);
470 CFReleaseNull(certs
);
471 CFReleaseNull(anchors
);
473 CFReleaseNull(policy
);
474 CFReleaseNull(trust
);
479 static void rsa_key_size_tests() {
481 ok(test_chain_of_three(_leaf2048A
, sizeof(_leaf2048A
),_int2048A
, sizeof(_int2048A
), _root512
, sizeof(_root512
),
482 false, NULL
), "SECURITY: failed to detect weak root");
483 ok(test_chain_of_three(_leaf2048B
, sizeof(_leaf2048B
), _int512
, sizeof(_int512
), _root2048
, sizeof(_root2048
),
484 false, NULL
), "SECURITY: failed to detect weak intermediate");
485 ok(test_chain_of_three(_leaf512
, sizeof(_leaf512
), _int2048B
, sizeof(_int2048B
), _root2048
, sizeof(_root2048
),
486 false, NULL
), "SECURITY: failed to detect weak leaf");
488 CFStringRef failureReason
= NULL
;
489 ok(test_chain_of_three(_leaf1024
, sizeof(_leaf1024
), _int2048B
, sizeof(_int2048B
), _root2048
, sizeof(_root2048
),
490 true, &failureReason
), "REGRESSION: key size test 1024-bit leaf: %@", failureReason
);
491 CFReleaseNull(failureReason
);
492 ok(test_chain_of_three(_leaf2048C
, sizeof(_leaf2048C
), _int2048B
, sizeof(_int2048B
), _root2048
, sizeof(_root2048
),
493 true, &failureReason
), "REGRESSION: key size test 2048-bit leaf: %@", failureReason
);
494 CFReleaseNull(failureReason
);
498 static void ec_key_size_tests() {
500 /* Because CoreCrypto does not support P128, we fail to chain if any CAs use weakly sized curves */
501 ok(test_chain_of_three(_leaf128
, sizeof(_leaf128
), _int384B
, sizeof(_int384B
), _root384
, sizeof(_root384
),
502 false, NULL
), "SECURITY: failed to detect weak leaf");
504 CFStringRef failureReason
= NULL
;
505 ok(test_chain_of_three(_leaf192
, sizeof(_leaf192
), _int384B
, sizeof(_int384B
), _root384
, sizeof(_root384
),
506 true, &failureReason
), "REGRESSION: key size test 192-bit leaf: %@", failureReason
);
507 CFReleaseNull(failureReason
);
508 ok(test_chain_of_three(_leaf384C
, sizeof(_leaf384C
), _int384B
, sizeof(_int384B
), _root384
, sizeof(_root384
),
509 true, &failureReason
), "REGRESSION: key size test 384-bit leaf: %@", failureReason
);
510 CFReleaseNull(failureReason
);
514 static void test_input_certificates() {
515 SecCertificateRef cert0
= NULL
, cert1
= NULL
;
516 SecPolicyRef policy
= NULL
;
517 SecTrustRef trust
= NULL
;
518 CFArrayRef certificates
= NULL
;
520 require(cert0
= SecCertificateCreateWithBytes(NULL
, _c0
, sizeof(_c0
)), errOut
);
521 require(cert1
= SecCertificateCreateWithBytes(NULL
, _c1
, sizeof(_c1
)), errOut
);
522 require(policy
= SecPolicyCreateBasicX509(), errOut
);
523 require_noerr(SecTrustCreateWithCertificates(cert0
, policy
, &trust
), errOut
);
525 ok_status(SecTrustCopyInputCertificates(trust
, &certificates
), "SecTrustCopyInputCertificates failed");
526 is(CFArrayGetCount(certificates
), 1, "got too many input certs back");
527 is(CFArrayGetValueAtIndex(certificates
, 0), cert0
, "wrong input cert");
528 CFReleaseNull(certificates
);
530 ok_status(SecTrustAddToInputCertificates(trust
, cert1
), "SecTrustAddToInputCertificates failed");
531 ok_status(SecTrustCopyInputCertificates(trust
, &certificates
), "SecTrustCopyInputCertificates failed");
532 is(CFArrayGetCount(certificates
), 2, "got wrong number of input certs back");
533 is(CFArrayGetValueAtIndex(certificates
, 0), cert0
, "wrong input cert0");
534 is(CFArrayGetValueAtIndex(certificates
, 1), cert1
, "wrong input cert1");
535 is(SecTrustGetCertificateCount(trust
), 3, "output number of certs is 3");
538 CFReleaseNull(cert0
);
539 CFReleaseNull(cert1
);
540 CFReleaseNull(policy
);
541 CFReleaseNull(trust
);
542 CFReleaseNull(certificates
);
545 static void test_async_trust() {
546 SecCertificateRef cert0
= NULL
, cert1
= NULL
;
547 SecPolicyRef policy
= NULL
;
548 SecTrustRef trust
= NULL
;
549 CFArrayRef certificates
= NULL
;
550 CFDateRef date
= NULL
;
552 require(cert0
= SecCertificateCreateWithBytes(NULL
, _c0
, sizeof(_c0
)), errOut
);
553 require(cert1
= SecCertificateCreateWithBytes(NULL
, _c1
, sizeof(_c1
)), errOut
);
554 const void *v_certs
[] = {
558 certificates
= CFArrayCreate(NULL
, v_certs
,
560 &kCFTypeArrayCallBacks
);
562 require(policy
= SecPolicyCreateBasicX509(), errOut
);
563 require_noerr(SecTrustCreateWithCertificates(certificates
, policy
, &trust
), errOut
);
566 require(date
= CFDateCreateForGregorianZuluMoment(NULL
, 2014, 7, 30, 12, 0, 0), errOut
);
567 require_noerr(SecTrustSetVerifyDate(trust
, date
), errOut
);
569 /* This shouldn't crash. */
570 ok_status(SecTrustEvaluateAsync(trust
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0),
571 ^(SecTrustRef _Nonnull trustRef
, SecTrustResultType trustResult
) {
572 if ((trustResult
== kSecTrustResultProceed
) ||
573 (trustResult
== kSecTrustResultUnspecified
))
575 // Evaluation succeeded!
576 SecKeyRef publicKey
= SecTrustCopyPublicKey(trustRef
);
578 CFReleaseSafe(publicKey
);
580 } else if (trustResult
== kSecTrustResultRecoverableTrustFailure
) {
581 // Evaluation failed, but may be able to recover . . .
585 }), "evaluate trust asynchronously");
586 CFReleaseNull(trust
);
589 CFReleaseNull(cert0
);
590 CFReleaseNull(cert1
);
591 CFReleaseNull(policy
);
592 CFReleaseNull(certificates
);
596 static void test_expired_only() {
597 SecCertificateRef cert0
= NULL
, cert1
= NULL
, cert2
= NULL
;
598 SecPolicyRef policy
= NULL
;
599 SecTrustRef trust
= NULL
;
600 CFArrayRef certificates
= NULL
, roots
= NULL
;
601 CFDateRef date
= NULL
;
603 require(cert0
= SecCertificateCreateWithBytes(NULL
, _expired_badssl
, sizeof(_expired_badssl
)), errOut
);
604 require(cert1
= SecCertificateCreateWithBytes(NULL
, _comodo_rsa_dvss
, sizeof(_comodo_rsa_dvss
)), errOut
);
605 require(cert2
= SecCertificateCreateWithBytes(NULL
, _comodo_rsa_root
, sizeof(_comodo_rsa_root
)), errOut
);
607 const void *v_certs
[] = {
611 certificates
= CFArrayCreate(NULL
, v_certs
,
613 &kCFTypeArrayCallBacks
);
615 const void *v_roots
[] = {
618 roots
= CFArrayCreate(NULL
, v_roots
,
620 &kCFTypeArrayCallBacks
);
622 require(policy
= SecPolicyCreateSSL(true, CFSTR("expired.badssl.com")), errOut
);
623 require_noerr(SecTrustCreateWithCertificates(certificates
, policy
, &trust
), errOut
);
624 require_noerr(SecTrustSetAnchorCertificates(trust
, roots
), errOut
);
626 /* Mar 21 2017 (cert expired in 2015, so this will cause a validity error.) */
627 require(date
= CFDateCreateForGregorianZuluMoment(NULL
, 2017, 3, 21, 12, 0, 0), errOut
);
628 require_noerr(SecTrustSetVerifyDate(trust
, date
), errOut
);
630 /* SecTrustIsExpiredOnly implicitly evaluates the trust */
631 ok(SecTrustIsExpiredOnly(trust
), "REGRESSION: has new error as well as expiration");
633 CFReleaseNull(policy
);
634 require(policy
= SecPolicyCreateSSL(true, CFSTR("expired.terriblessl.com")), errOut
);
635 require_noerr(SecTrustSetPolicies(trust
, policy
), errOut
);
636 /* expect a hostname mismatch as well as expiration */
637 ok(!SecTrustIsExpiredOnly(trust
), "REGRESSION: should have found multiple errors");
640 CFReleaseNull(trust
);
641 CFReleaseNull(cert0
);
642 CFReleaseNull(cert1
);
643 CFReleaseNull(cert2
);
644 CFReleaseNull(policy
);
645 CFReleaseNull(certificates
);
646 CFReleaseNull(roots
);
650 static void test_evaluate_with_error(void) {
651 #pragma clang diagnostic push
652 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
654 SecCertificateRef cert0
= NULL
, cert1
= NULL
, cert2
= NULL
;
655 SecPolicyRef policy
= NULL
;
656 SecTrustRef trust
= NULL
;
657 CFArrayRef certificates
= NULL
, roots
= NULL
;
658 CFDateRef date
= NULL
, validDate
= NULL
;
659 CFErrorRef error
= NULL
;
661 require(cert0
= SecCertificateCreateWithBytes(NULL
, _expired_badssl
, sizeof(_expired_badssl
)), errOut
);
662 require(cert1
= SecCertificateCreateWithBytes(NULL
, _comodo_rsa_dvss
, sizeof(_comodo_rsa_dvss
)), errOut
);
663 require(cert2
= SecCertificateCreateWithBytes(NULL
, _comodo_rsa_root
, sizeof(_comodo_rsa_root
)), errOut
);
665 const void *v_certs
[] = {
669 certificates
= CFArrayCreate(NULL
, v_certs
,
671 &kCFTypeArrayCallBacks
);
673 const void *v_roots
[] = {
676 roots
= CFArrayCreate(NULL
, v_roots
,
678 &kCFTypeArrayCallBacks
);
680 require(policy
= SecPolicyCreateSSL(true, CFSTR("expired.badssl.com")), errOut
);
681 require_noerr(SecTrustCreateWithCertificates(certificates
, policy
, &trust
), errOut
);
682 require_noerr(SecTrustSetAnchorCertificates(trust
, roots
), errOut
);
684 /* April 10 2015 (cert expired in 2015) */
685 require(validDate
= CFDateCreateForGregorianZuluMoment(NULL
, 2015, 4, 10, 12, 0, 0), errOut
);
686 require_noerr(SecTrustSetVerifyDate(trust
, validDate
), errOut
);
688 is(SecTrustEvaluateWithError(trust
, &error
), true, "wrong result for valid cert");
689 is(error
, NULL
, "set error for passing trust evaluation");
690 CFReleaseNull(error
);
692 /* Mar 21 2017 (cert expired in 2015, so this will cause a validity error.) */
693 require(date
= CFDateCreateForGregorianZuluMoment(NULL
, 2017, 3, 21, 12, 0, 0), errOut
);
694 require_noerr(SecTrustSetVerifyDate(trust
, date
), errOut
);
696 /* expect expiration error */
697 is(SecTrustEvaluateWithError(trust
, &error
), false, "wrong result for expired cert");
698 isnt(error
, NULL
, "failed to set error for failing trust evaluation");
699 is(CFErrorGetCode(error
), errSecCertificateExpired
, "Got wrong error code for evaluation");
700 CFReleaseNull(error
);
702 CFReleaseNull(policy
);
703 require(policy
= SecPolicyCreateSSL(true, CFSTR("expired.terriblessl.com")), errOut
);
704 require_noerr(SecTrustSetPolicies(trust
, policy
), errOut
);
706 /* expect a hostname mismatch as well as expiration; hostname mismatch must be a higher priority */
707 is(SecTrustEvaluateWithError(trust
, &error
), false, "wrong result for expired cert with hostname mismatch");
708 isnt(error
, NULL
, "failed to set error for failing trust evaluation");
709 is(CFErrorGetCode(error
), errSecHostNameMismatch
, "Got wrong error code for evaluation");
710 CFReleaseNull(error
);
712 /* expect only a hostname mismatch*/
713 require_noerr(SecTrustSetVerifyDate(trust
, validDate
), errOut
);
714 is(SecTrustEvaluateWithError(trust
, &error
), false, "wrong result for valid cert with hostname mismatch");
715 isnt(error
, NULL
, "failed to set error for failing trust evaluation");
716 is(CFErrorGetCode(error
), errSecHostNameMismatch
, "Got wrong error code for evaluation");
717 CFReleaseNull(error
);
719 /* pinning failure */
720 CFReleaseNull(policy
);
721 require(policy
= SecPolicyCreateAppleSSLPinned(CFSTR("test"), CFSTR("expired.badssl.com"),
722 NULL
, CFSTR("1.2.840.113635.100.6.27.1")), errOut
);
723 require_noerr(SecTrustSetPolicies(trust
, policy
), errOut
);
725 is(SecTrustEvaluateWithError(trust
, &error
), false, "wrong result for valid cert with pinning failure");
726 isnt(error
, NULL
, "failed to set error for failing trust evaluation");
727 CFIndex errorCode
= CFErrorGetCode(error
);
728 // failed checks: AnchorApple, LeafMarkerOid, or IntermediateMarkerOid
729 ok(errorCode
== errSecMissingRequiredExtension
|| errorCode
== errSecInvalidRoot
, "Got wrong error code for evaluation");
730 CFReleaseNull(error
);
732 /* trust nothing, trust errors higher priority than hostname mismatch */
733 CFReleaseNull(policy
);
734 require(policy
= SecPolicyCreateSSL(true, CFSTR("expired.terriblessl.com")), errOut
);
735 require_noerr(SecTrustSetPolicies(trust
, policy
), errOut
);
737 CFReleaseNull(roots
);
738 roots
= CFArrayCreate(NULL
, NULL
, 0, &kCFTypeArrayCallBacks
);
739 require_noerr(SecTrustSetAnchorCertificates(trust
, roots
), errOut
);
740 is(SecTrustEvaluateWithError(trust
, &error
), false, "wrong result for expired cert with hostname mismatch");
741 isnt(error
, NULL
, "failed to set error for failing trust evaluation");
742 is(CFErrorGetCode(error
), errSecNotTrusted
, "Got wrong error code for evaluation");
743 CFReleaseNull(error
);
746 CFReleaseNull(trust
);
747 CFReleaseNull(cert0
);
748 CFReleaseNull(cert1
);
749 CFReleaseNull(cert2
);
750 CFReleaseNull(policy
);
751 CFReleaseNull(certificates
);
752 CFReleaseNull(roots
);
754 CFReleaseNull(validDate
);
755 CFReleaseNull(error
);
757 #pragma clang diagnostic pop
760 static void test_optional_policy_check(void) {
761 SecCertificateRef cert0
= NULL
, cert1
= NULL
, root
= NULL
;
762 SecTrustRef trust
= NULL
;
763 SecPolicyRef policy
= NULL
;
764 CFArrayRef certs
= NULL
, anchors
= NULL
;
765 CFDateRef date
= NULL
;
767 require_action(cert0
= SecCertificateCreateWithBytes(NULL
, _leaf384C
, sizeof(_leaf384C
)), errOut
,
768 fail("unable to create cert"));
769 require_action(cert1
= SecCertificateCreateWithBytes(NULL
, _int384B
, sizeof(_int384B
)), errOut
,
770 fail("unable to create cert"));
771 require_action(root
= SecCertificateCreateWithBytes(NULL
, _root384
, sizeof(_root384
)), errOut
,
772 fail("unable to create cert"));
774 const void *v_certs
[] = { cert0
, cert1
};
775 require_action(certs
= CFArrayCreate(NULL
, v_certs
, array_size(v_certs
), &kCFTypeArrayCallBacks
), errOut
,
776 fail("unable to create array"));
777 require_action(anchors
= CFArrayCreate(NULL
, (const void **)&root
, 1, &kCFTypeArrayCallBacks
), errOut
,
778 fail("unable to create anchors array"));
779 require_action(date
= CFDateCreate(NULL
, 472100000.0), errOut
, fail("unable to create date"));
781 require_action(policy
= SecPolicyCreateBasicX509(), errOut
, fail("unable to create policy"));
782 SecPolicySetOptionsValue(policy
, CFSTR("not-a-policy-check"), kCFBooleanTrue
);
784 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
), "failed to create trust");
785 require_noerr_action(SecTrustSetAnchorCertificates(trust
, anchors
), errOut
,
786 fail("unable to set anchors"));
787 require_noerr_action(SecTrustSetVerifyDate(trust
, date
), errOut
, fail("unable to set verify date"));
789 #pragma clang diagnostic push
790 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
792 ok(SecTrustEvaluateWithError(trust
, NULL
), "Trust evaluation failed");
794 is(SecTrustEvaluateWithError(trust
, NULL
), false, "Expect failure in Debug config");
796 #pragma clang diagnostic pop
799 CFReleaseNull(cert0
);
800 CFReleaseNull(cert1
);
802 CFReleaseNull(certs
);
803 CFReleaseNull(anchors
);
805 CFReleaseNull(policy
);
806 CFReleaseNull(trust
);
809 static void test_serialization(void) {
810 SecCertificateRef cert0
= NULL
, cert1
= NULL
, root
= NULL
;
811 SecTrustRef trust
= NULL
, deserializedTrust
= NULL
;
812 SecPolicyRef policy
= NULL
;
813 CFArrayRef certs
= NULL
, anchors
= NULL
, deserializedCerts
= NULL
;
814 CFDateRef date
= NULL
;
815 CFDataRef serializedTrust
= NULL
;
816 CFErrorRef error
= NULL
;
818 require_action(cert0
= SecCertificateCreateWithBytes(NULL
, _leaf384C
, sizeof(_leaf384C
)), errOut
,
819 fail("unable to create cert"));
820 require_action(cert1
= SecCertificateCreateWithBytes(NULL
, _int384B
, sizeof(_int384B
)), errOut
,
821 fail("unable to create cert"));
822 require_action(root
= SecCertificateCreateWithBytes(NULL
, _root384
, sizeof(_root384
)), errOut
,
823 fail("unable to create cert"));
825 const void *v_certs
[] = { cert0
, cert1
};
826 require_action(certs
= CFArrayCreate(NULL
, v_certs
, array_size(v_certs
), &kCFTypeArrayCallBacks
), errOut
,
827 fail("unable to create array"));
828 require_action(anchors
= CFArrayCreate(NULL
, (const void **)&root
, 1, &kCFTypeArrayCallBacks
), errOut
,
829 fail("unable to create anchors array"));
830 require_action(date
= CFDateCreate(NULL
, 472100000.0), errOut
, fail("unable to create date"));
832 require_action(policy
= SecPolicyCreateBasicX509(), errOut
, fail("unable to create policy"));
834 ok_status(SecTrustCreateWithCertificates(certs
, policy
, &trust
), "failed to create trust");
835 require_noerr_action(SecTrustSetAnchorCertificates(trust
, anchors
), errOut
,
836 fail("unable to set anchors"));
837 require_noerr_action(SecTrustSetVerifyDate(trust
, date
), errOut
, fail("unable to set verify date"));
839 ok(serializedTrust
= SecTrustSerialize(trust
, NULL
), "failed to serialize trust");
840 ok(deserializedTrust
= SecTrustDeserialize(serializedTrust
, NULL
), "Failed to deserialize trust");
841 CFReleaseNull(serializedTrust
);
843 require_noerr_action(SecTrustCopyCustomAnchorCertificates(deserializedTrust
, &deserializedCerts
), errOut
,
844 fail("unable to get anchors from deserialized trust"));
845 ok(CFEqual(anchors
, deserializedCerts
), "Failed to get the same anchors after serialization/deserialization");
846 CFReleaseNull(deserializedCerts
);
848 require_noerr_action(SecTrustCopyInputCertificates(trust
, &deserializedCerts
), errOut
,
849 fail("unable to get input certificates from deserialized trust"));
850 ok(CFEqual(certs
, deserializedCerts
), "Failed to get same input certificates after serialization/deserialization");
851 CFReleaseNull(deserializedCerts
);
853 /* correct API behavior */
854 #pragma clang diagnostic push
855 #pragma clang diagnostic ignored "-Wnonnull"
856 is(SecTrustSerialize(NULL
, &error
), NULL
, "serialize succeeded with null input");
857 is(CFErrorGetCode(error
), errSecParam
, "Incorrect error code for bad serialization input");
858 CFReleaseNull(error
);
859 is(SecTrustDeserialize(NULL
, &error
), NULL
, "deserialize succeeded with null input");
860 is(CFErrorGetCode(error
), errSecParam
, "Incorrect error code for bad deserialization input");
861 CFReleaseNull(error
);
862 #pragma clang diagnostic pop
865 CFReleaseNull(cert0
);
866 CFReleaseNull(cert1
);
868 CFReleaseNull(certs
);
869 CFReleaseNull(anchors
);
871 CFReleaseNull(policy
);
872 CFReleaseNull(trust
);
873 CFReleaseNull(deserializedTrust
);
876 static void test_tls_analytics_report(void)
878 xpc_object_t metric
= xpc_dictionary_create(NULL
, NULL
, 0);
881 const char *TLS_METRIC_PROCESS_IDENTIFIER
= "process";
882 const char *TLS_METRIC_CIPHERSUITE
= "cipher_name";
883 const char *TLS_METRIC_PROTOCOL_VERSION
= "version";
884 const char *TLS_METRIC_SESSION_RESUMED
= "resumed";
886 xpc_dictionary_set_string(metric
, TLS_METRIC_PROCESS_IDENTIFIER
, "super awesome unit tester");
887 xpc_dictionary_set_uint64(metric
, TLS_METRIC_CIPHERSUITE
, 0x0304);
888 xpc_dictionary_set_uint64(metric
, TLS_METRIC_PROTOCOL_VERSION
, 0x0304);
889 xpc_dictionary_set_bool(metric
, TLS_METRIC_SESSION_RESUMED
, false);
890 // ... TLS would fill in the rest
892 // Invoke the callback
893 CFErrorRef error
= NULL
;
894 bool reported
= SecTrustReportTLSAnalytics(CFSTR("TLSConnectionEvent"), metric
, &error
);
895 ok(reported
, "Failed to report analytics with error %@", error
);
898 int si_20_sectrust(int argc
, char *const *argv
)
901 plan_tests(101+9+(8*13)+9+1+2+17+2+9+2);
903 plan_tests(97+9+(8*13)+9+1+2+2+17+2+9+2);
907 negative_integer_tests();
910 rsa_key_size_tests();
912 test_input_certificates();
915 test_evaluate_with_error();
916 test_optional_policy_check();
917 test_serialization();
918 test_tls_analytics_report();