]> git.saurik.com Git - apple/security.git/blob - tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m
Security-59754.41.1.tar.gz
[apple/security.git] / tests / TrustTests / EvaluationTests / AllowlistBlocklistTests.m
1 /*
2 * Copyright (c) 2011-2019 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <AssertMacros.h>
25 #import <XCTest/XCTest.h>
26 #import <Foundation/Foundation.h>
27 #include <Security/SecCertificate.h>
28 #include <Security/SecCertificatePriv.h>
29 #include <Security/SecPolicyPriv.h>
30 #include <Security/SecTrust.h>
31 #include <Security/SecTrustPriv.h>
32 #include <utilities/SecCFRelease.h>
33
34 #import "../TestMacroConversions.h"
35 #import "TrustEvaluationTestCase.h"
36
37 #import "AllowlistBlocklistTests_data.h"
38
39 @interface BlocklistTests :TrustEvaluationTestCase
40 @end
41
42 @implementation BlocklistTests
43
44 - (void)validate_one_cert:(uint8_t *)data length:(size_t)len chain_length:(int)chain_length trustResult:(SecTrustResultType)trust_result
45 {
46 SecTrustRef trust = NULL;
47 SecCertificateRef cert = NULL, root = NULL;
48 SecPolicyRef policy = SecPolicyCreateSSL(false, NULL);
49 CFArrayRef certs = NULL;
50
51 isnt(cert = SecCertificateCreateWithBytes(NULL, data, len),
52 NULL, "create cert");
53 isnt(root = SecCertificateCreateWithBytes(NULL, UTNHardware_cer, sizeof(UTNHardware_cer)), NULL);
54 certs = CFArrayCreate(NULL, (const void **)&cert, 1, NULL);
55 ok_status(SecTrustCreateWithCertificates(certs, policy, &trust),
56 "create trust with single cert");
57 ok_status(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)@[(__bridge id)root]));
58
59 SecTrustResultType trustResult;
60 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
61 is(SecTrustGetCertificateCount(trust), chain_length, "cert count");
62 is_status(trustResult, trust_result, "correct trustResult");
63 CFRelease(trust);
64 CFRelease(policy);
65 CFRelease(certs);
66 CFRelease(cert);
67 CFReleaseNull(root);
68 }
69
70 - (void)testBlocklistedCerts
71 {
72 [self validate_one_cert:Global_Trustee_cer length:sizeof(Global_Trustee_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure];
73 [self validate_one_cert:login_yahoo_com_1_cer length:sizeof(login_yahoo_com_1_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure];
74
75 /* this is the root, which isn't ok for ssl and fails here, but at the
76 same time it proves that kSecTrustResultFatalTrustFailure isn't
77 returned for policy failures that aren't blocklisting */
78 [self validate_one_cert:login_yahoo_com_2_cer length:sizeof(login_yahoo_com_2_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure];
79 [self validate_one_cert:addons_mozilla_org_cer length:sizeof(addons_mozilla_org_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure];
80 [self validate_one_cert:login_yahoo_com_cer length:sizeof(login_yahoo_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure];
81 [self validate_one_cert:login_live_com_cer length:sizeof(login_live_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure];
82 [self validate_one_cert:mail_google_com_cer length:sizeof(mail_google_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure];
83 [self validate_one_cert:login_skype_com_cer length:sizeof(login_skype_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure];
84 [self validate_one_cert:www_google_com_cer length:sizeof(www_google_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure];
85 }
86
87 @end
88
89 @interface AllowlistTests : TrustEvaluationTestCase
90 @end
91
92 @implementation AllowlistTests
93
94 #if !TARGET_OS_BRIDGE
95 static SecCertificateRef createCertFromStaticData(const UInt8 *certData, CFIndex certLength)
96 {
97 SecCertificateRef cert = NULL;
98 CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, certData, certLength, kCFAllocatorNull);
99 if (data) {
100 cert = SecCertificateCreateWithData(NULL, data);
101 CFRelease(data);
102 }
103 return cert;
104 }
105
106 - (void)testLeafOnAllowList
107 {
108 SecCertificateRef certs[3];
109 SecPolicyRef policy = NULL;
110 SecTrustRef trust = NULL;
111 CFDateRef date = NULL;
112 CFArrayRef certArray = NULL;
113 CFArrayRef anchorsArray = NULL;
114
115 isnt(certs[0] = createCertFromStaticData(leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)),
116 NULL, "allowlist: create leaf cert");
117 isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)),
118 NULL, "allowlist: create intermediate ca 1");
119 isnt(certs[2] = createCertFromStaticData(root_Cert, sizeof(root_Cert)),
120 NULL, "allowlist: create root");
121
122 isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 3, &kCFTypeArrayCallBacks),
123 NULL, "allowlist: create cert array");
124
125 /* create a trust reference with ssl policy */
126 isnt(policy = SecPolicyCreateBasicX509(), NULL, "allowlist: create policy");
127 ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "allowlist: create trust");
128
129 /* set evaluate date: January 6, 2020 at 2:40:00 AM PST */
130 isnt(date = CFDateCreate(NULL, 600000000.0), NULL, "allowlist: create date");
131 ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "allowlist: set verify date");
132
133 /* use a known root CA at this point in time to anchor the chain */
134 isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[2], 1, &kCFTypeArrayCallBacks),
135 NULL, "allowlist: create anchors array");
136 ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "allowlist: set anchors");
137
138 SecTrustResultType trustResult = kSecTrustResultInvalid;
139 ok_status(SecTrustGetTrustResult(trust, &trustResult), "allowlist: evaluate");
140
141 /* expected result is kSecTrustResultUnspecified since cert is on allow list and its issuer chains to a trusted root */
142 ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)",
143 (int)trustResult);
144
145 /* clean up */
146 for(CFIndex idx=0; idx < 3; idx++) {
147 if (certs[idx]) { CFRelease(certs[idx]); }
148 }
149 if (policy) { CFRelease(policy); }
150 if (trust) { CFRelease(trust); }
151 if (date) { CFRelease(date); }
152 if (certArray) { CFRelease(certArray); }
153 if (anchorsArray) { CFRelease(anchorsArray); }
154 }
155
156 - (void)testLeafNotOnAllowList
157 {
158 SecCertificateRef certs[3];
159 SecPolicyRef policy = NULL;
160 SecTrustRef trust = NULL;
161 CFDateRef date = NULL;
162 CFArrayRef certArray = NULL;
163 CFArrayRef anchorsArray = NULL;
164
165 isnt(certs[0] = createCertFromStaticData(leafNotOnAllowList_Cert, sizeof(leafNotOnAllowList_Cert)),
166 NULL, "!allowlist: create leaf cert");
167 isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)),
168 NULL, "!allowlist: create intermediate ca 1");
169 isnt(certs[2] = createCertFromStaticData(root_Cert, sizeof(root_Cert)),
170 NULL, "!allowlist: create root");
171
172 isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 3, &kCFTypeArrayCallBacks),
173 NULL, "!allowlist: create cert array");
174
175 /* create a trust reference with basic policy */
176 isnt(policy = SecPolicyCreateBasicX509(), NULL, "!allowlist: create policy");
177 ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "!allowlist: create trust");
178
179 /* set evaluate date: January 6, 2020 at 2:40:00 AM PST */
180 isnt(date = CFDateCreate(NULL, 600000000.0), NULL, "allowlist: create date");
181 ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "!allowlist: set verify date");
182
183 /* use a known root CA at this point in time to anchor the chain */
184 isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[2], 1, &kCFTypeArrayCallBacks),
185 NULL, "allowlist: create anchors array");
186 ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "!allowlist: set anchors");
187
188 SecTrustResultType trustResult = kSecTrustResultInvalid;
189 ok_status(SecTrustGetTrustResult(trust, &trustResult), "!allowlist: evaluate");
190
191 /* expected result is kSecTrustResultFatalTrustFailure, since cert is not on allow list */
192 ok(trustResult == kSecTrustResultFatalTrustFailure,
193 "trustResult 6 expected (got %d)", (int)trustResult);
194
195 /* clean up */
196 for(CFIndex idx=0; idx < 3; idx++) {
197 if (certs[idx]) { CFRelease(certs[idx]); }
198 }
199 if (policy) { CFRelease(policy); }
200 if (trust) { CFRelease(trust); }
201 if (date) { CFRelease(date); }
202 if (certArray) { CFRelease(certArray); }
203 if (anchorsArray) { CFRelease(anchorsArray); }
204 }
205
206 - (void)testAllowListForRootCA
207 {
208 SecCertificateRef certs[3];
209 SecPolicyRef policy = NULL;
210 SecTrustRef trust = NULL;
211 CFDateRef date = NULL;
212 CFArrayRef certArray = NULL;
213 CFArrayRef anchorsArray = NULL;
214
215 isnt(certs[0] = createCertFromStaticData(leaf_subCANotOnAllowlist_Cert, sizeof(leaf_subCANotOnAllowlist_Cert)),
216 NULL, "!allowlist: create leaf cert");
217 isnt(certs[1] = createCertFromStaticData(subCANotOnAllowlist_Cert, sizeof(subCANotOnAllowlist_Cert)),
218 NULL, "!allowlist: create intermediate ca 1");
219 isnt(certs[2] = createCertFromStaticData(root_Cert, sizeof(root_Cert)),
220 NULL, "!allowlist: create root");
221
222 isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 3, &kCFTypeArrayCallBacks),
223 NULL, "!allowlist: create cert array");
224
225 /* create a trust reference with basic policy */
226 isnt(policy = SecPolicyCreateBasicX509(), NULL, "!allowlist: create policy");
227 ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "!allowlist: create trust");
228
229 /* set evaluate date: January 6, 2020 at 2:40:00 AM PST */
230 isnt(date = CFDateCreate(NULL, 600000000.0), NULL, "allowlist: create date");
231 ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "!allowlist: set verify date");
232
233 /* use a known root CA at this point in time to anchor the chain */
234 isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[2], 1, &kCFTypeArrayCallBacks),
235 NULL, "allowlist: create anchors array");
236 ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "!allowlist: set anchors");
237
238 SecTrustResultType trustResult = kSecTrustResultInvalid;
239 ok_status(SecTrustGetTrustResult(trust, &trustResult), "!allowlist: evaluate");
240
241 /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted)
242 or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */
243 ok(trustResult == kSecTrustResultFatalTrustFailure,
244 "trustResult 6 expected (got %d)", (int)trustResult);
245
246 /* clean up */
247 for(CFIndex idx=0; idx < 3; idx++) {
248 if (certs[idx]) { CFRelease(certs[idx]); }
249 }
250 if (policy) { CFRelease(policy); }
251 if (trust) { CFRelease(trust); }
252 if (date) { CFRelease(date); }
253 if (certArray) { CFRelease(certArray); }
254 if (anchorsArray) { CFRelease(anchorsArray); }
255 }
256
257 - (void)testDateBasedAllowListForRootCA
258 {
259 SecCertificateRef root = NULL, beforeInt = NULL, afterInt = NULL,
260 beforeLeaf = NULL, afterLeaf = NULL;
261 SecPolicyRef policy = NULL;
262 SecTrustRef trust = NULL;
263 NSArray *anchors = nil, *certs = nil;
264 NSDate *verifyDate = nil;
265 SecTrustResultType trustResult = kSecTrustResultInvalid;
266
267 require(root = SecCertificateCreateWithBytes(NULL, _datetest_root, sizeof(_datetest_root)), out);
268 require(beforeInt = SecCertificateCreateWithBytes(NULL, _datetest_before_int, sizeof(_datetest_before_int)), out);
269 require(afterInt = SecCertificateCreateWithBytes(NULL, _datetest_after_int, sizeof(_datetest_after_int)), out);
270 require(beforeLeaf = SecCertificateCreateWithBytes(NULL, _datetest_before_leaf, sizeof(_datetest_before_leaf)), out);
271 require(afterLeaf = SecCertificateCreateWithBytes(NULL, _datetest_after_leaf, sizeof(_datetest_after_leaf)), out);
272
273 anchors = @[(__bridge id)root];
274 require(policy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com")), out);
275 verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:504000000.0]; /* 21 Dec 2016 */
276
277 /* Leaf issued before cutoff should pass */
278 certs = @[(__bridge id)beforeLeaf, (__bridge id)beforeInt];
279 require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out);
280 require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out);
281 require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out);
282 require_noerr(SecTrustGetTrustResult(trust, &trustResult), out);
283 is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation");
284 CFReleaseNull(trust);
285 trustResult = kSecTrustResultInvalid;
286
287 /* Leaf issued after cutoff should fail */
288 certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt];
289 require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out);
290 require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out);
291 require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out);
292 require_noerr(SecTrustGetTrustResult(trust, &trustResult), out);
293 is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation");
294 CFReleaseNull(trust);
295 trustResult = kSecTrustResultInvalid;
296
297 /* Intermediate issued after cutoff should fail (even for leaf issued before) */
298 certs = @[(__bridge id)beforeLeaf, (__bridge id)afterInt];
299 require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out);
300 require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out);
301 require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out);
302 require_noerr(SecTrustGetTrustResult(trust, &trustResult), out);
303 is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued after cutoff succeeded evaluation");
304 CFReleaseNull(trust);
305 trustResult = kSecTrustResultInvalid;
306
307 /* Intermediate issued after cutoff should fail */
308 certs = @[(__bridge id)afterLeaf, (__bridge id)afterInt];
309 require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out);
310 require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out);
311 require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out);
312 require_noerr(SecTrustGetTrustResult(trust, &trustResult), out);
313 is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued before cutoff succeeded evaluation");
314 CFReleaseNull(trust);
315 trustResult = kSecTrustResultInvalid;
316
317 /* Leaf issued before cutoff should choose acceptable path */
318 certs = @[(__bridge id)beforeLeaf, (__bridge id) afterInt, (__bridge id)beforeInt];
319 require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out);
320 require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out);
321 require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out);
322 require_noerr(SecTrustGetTrustResult(trust, &trustResult), out);
323 is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation (multi-path)");
324 CFReleaseNull(trust);
325 trustResult = kSecTrustResultInvalid;
326
327 /* No good path for leaf issued after cutoff */
328 certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt, (__bridge id)afterInt];
329 require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out);
330 require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out);
331 require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out);
332 require_noerr(SecTrustGetTrustResult(trust, &trustResult), out);
333 is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation (multi-path)");
334
335 out:
336 CFReleaseNull(root);
337 CFReleaseNull(beforeInt);
338 CFReleaseNull(afterInt);
339 CFReleaseNull(beforeLeaf);
340 CFReleaseNull(afterLeaf);
341 CFReleaseNull(policy);
342 CFReleaseNull(trust);
343 }
344
345 - (void)testLeafOnAllowListOtherFailures
346 {
347 SecCertificateRef certs[3];
348 SecPolicyRef policy = NULL;
349 SecTrustRef trust = NULL;
350 NSArray *anchors = nil, *certArray = nil;
351 NSDate *verifyDate = nil;
352 SecTrustResultType trustResult = kSecTrustResultInvalid;
353
354 memset(certs, 0, 3 * sizeof(SecCertificateRef));
355
356 require(certs[0] = SecCertificateCreateWithBytes(NULL, leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)), out);
357 require(certs[1] = SecCertificateCreateWithBytes(NULL, ca1_Cert, sizeof(ca1_Cert)), out);
358 require(certs[2] = SecCertificateCreateWithBytes(NULL, root_Cert, sizeof(root_Cert)), out);
359
360 anchors = @[(__bridge id)certs[2]];
361 certArray = @[(__bridge id)certs[0], (__bridge id)certs[1], (__bridge id)certs[2]];
362 verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]; // January 6, 2020 at 2:40:00 AM PST
363
364 /* Mismatched policy, should fail */
365 require(policy = SecPolicyCreateSSL(true, (__bridge CFStringRef)@"example.com"), out);
366 require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certArray, policy, &trust), out);
367 require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out);
368 require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out);
369 require_noerr(SecTrustGetTrustResult(trust, &trustResult), out);
370 ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure,
371 "hostname failure with cert on allow list succeeded evaluation");
372 CFReleaseNull(policy);
373 trustResult = kSecTrustResultInvalid;
374
375 /* Expired, should fail */
376 verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:500000000.0]; // November 4, 2016 at 5:53:20 PM PDT
377 require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out);
378 require_noerr(SecTrustSetPolicies(trust, policy), out);
379 require_noerr(SecTrustGetTrustResult(trust, &trustResult), out);
380 ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure,
381 "EKU failure with cert on allow list succeeded evaluation");
382 CFReleaseNull(policy);
383 trustResult = kSecTrustResultInvalid;
384
385 /* Apple pinning policy, should fail */
386 require(policy = SecPolicyCreateAppleSSLPinned((__bridge CFStringRef)@"aPolicy",
387 (__bridge CFStringRef)@"example.com", NULL,
388 (__bridge CFStringRef)@"1.2.840.113635.100.6.27.12"), out);
389 require_noerr(SecTrustSetPolicies(trust, policy), out);
390 require_noerr(SecTrustGetTrustResult(trust, &trustResult), out);
391 ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure,
392 "Apple pinning policy with cert on allow list succeeded evaluation");
393
394 out:
395 CFReleaseNull(certs[0]);
396 CFReleaseNull(certs[1]);
397 CFReleaseNull(certs[2]);
398 CFReleaseNull(policy);
399 CFReleaseNull(trust);
400 }
401 #else /* TARGET_OS_BRIDGE */
402 /* Allowlists are provided by Valid, which is not supported on bridgeOS */
403 - (void)testSkipTests
404 {
405 XCTAssert(true);
406 }
407 #endif
408
409 @end