2 * Copyright (c) 2017-2019 Apple Inc. All Rights Reserved.
6 #import <XCTest/XCTest.h>
7 #import <Foundation/Foundation.h>
9 #include <Security/Security.h>
10 #include <Security/SecTrust.h>
11 #include <Security/SecPolicy.h>
12 #include <Security/SecCertificatePriv.h>
13 #include <utilities/SecCFWrappers.h>
14 #include "trust/trustd/OTATrustUtilities.h"
16 #import "../TestMacroConversions.h"
17 #import "TrustEvaluationTestCase.h"
24 @interface ValidTests : TrustEvaluationTestCase
27 @implementation ValidTests
30 - (void) run_valid_trust_test:(SecCertificateRef)leaf
31 ca:(SecCertificateRef)ca
32 subca:(SecCertificateRef)subca
33 anchors:(CFArrayRef)anchors
35 policyID:(CFIndex)policyID
36 expected:(SecTrustResultType)expected
37 test_name:(const char *)test_name
39 CFArrayRef policies=NULL;
40 SecPolicyRef policy=NULL;
41 SecTrustRef trust=NULL;
42 SecTrustResultType trustResult;
43 CFMutableArrayRef certs=NULL;
45 printf("Starting %s\n", test_name);
46 isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array");
49 CFArrayAppendValue(certs, leaf);
52 CFArrayAppendValue(certs, ca);
55 CFArrayAppendValue(certs, subca);
59 if (policyID == kSSLServerPolicy) {
60 isnt(policy = SecPolicyCreateSSL(true, NULL), NULL, "create ssl policy");
62 isnt(policy = SecPolicyCreateBasicX509(), NULL, "create basic policy");
64 isnt(policies = CFArrayCreate(kCFAllocatorDefault, (const void **)&policy, 1, &kCFTypeArrayCallBacks), NULL, "create policies");
65 ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust");
67 assert(trust); // silence analyzer
68 ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors");
69 ok_status(SecTrustSetVerifyDate(trust, date), "set date");
70 ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust");
71 ok(trustResult == expected, "trustResult %d expected (got %d) for %s",
72 (int)expected, (int)trustResult, test_name);
75 CFReleaseSafe(policy);
76 CFReleaseSafe(policies);
80 - (SecCertificateRef) CF_RETURNS_RETAINED createCertFromResource:(NSString *)name
82 id cert = [self SecCertificateCreateFromPEMResource:name subdirectory:@"si-88-sectrust-valid-data"];
83 return (__bridge SecCertificateRef)cert;
86 - (void)test_date_constraints
88 SecCertificateRef ca_na=NULL, ca_nb=NULL, root=NULL;
89 SecCertificateRef leaf_na_ok1=NULL, leaf_na_ok2=NULL;
90 SecCertificateRef leaf_nb_ok1=NULL, leaf_nb_ok2=NULL, leaf_nb_revoked1=NULL;
92 isnt(ca_na = [self createCertFromResource:@"ca-na"], NULL, "create ca-na cert");
93 isnt(ca_nb = [self createCertFromResource:@"ca-nb"], NULL, "create ca-nb cert");
94 isnt(root = [self createCertFromResource:@"root"], NULL, "create root cert");
95 isnt(leaf_na_ok1 = [self createCertFromResource:@"leaf-na-ok1"], NULL, "create leaf-na-ok1 cert");
96 isnt(leaf_na_ok2 = [self createCertFromResource:@"leaf-na-ok2"], NULL, "create leaf-na-ok2 cert");
97 isnt(leaf_nb_ok1 = [self createCertFromResource:@"leaf-nb-ok1"], NULL, "create leaf-nb-ok1 cert");
98 isnt(leaf_nb_ok2 = [self createCertFromResource:@"leaf-nb-ok2"], NULL, "create leaf-nb-ok2 cert");
99 isnt(leaf_nb_revoked1 = [self createCertFromResource:@"leaf-nb-revoked1"], NULL, "create leaf-nb-revoked1 cert");
101 CFMutableArrayRef anchors=NULL;
102 isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array");
103 if (anchors && root) {
104 CFArrayAppendValue(anchors, root);
106 CFCalendarRef cal = NULL;
108 CFDateRef date_20180102 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info
110 isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar");
111 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 1, 2), "create verify absolute time 20180102");
112 isnt(date_20180102 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180102");
114 /* Case 0: leaf_na_ok1 (not revoked) */
115 /* -- OK: cert issued 2017-10-20, before the CA not-after date of 2017-10-21 */
116 /* test cert has no SCT, but is expected to be OK since we now only apply the CT restriction for SSL. */
117 [self run_valid_trust_test:leaf_na_ok1 ca:ca_na subca:NULL anchors:anchors date:date_20180102
118 policyID:kBasicPolicy expected:kSecTrustResultUnspecified
119 test_name:"leaf_na_ok1 basic"];
121 /* Case 1: leaf_na_ok1 (not revoked) */
122 /* -- BAD: since a not-after date now requires CT (for SSL) and the test cert has no SCT, this is fatal. */
123 /* Mock a successful mobile asset check-in so that we enforce CT */
124 XCTAssertTrue(UpdateOTACheckInDate(), "failed to set check-in date as now");
125 [self run_valid_trust_test:leaf_na_ok1 ca:ca_na subca:NULL anchors:anchors date:date_20180102
126 policyID:kSSLServerPolicy expected:kSecTrustResultFatalTrustFailure
127 test_name:"leaf_na_ok1 ssl"];
129 /* Case 2: leaf_na_ok2 (revoked) */
130 /* -- BAD: cert issued 2017-10-26, after the CA not-after date of 2017-10-21 */
131 [self run_valid_trust_test:leaf_na_ok2 ca:ca_na subca:NULL anchors:anchors date:date_20180102
132 policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure
133 test_name:"leaf_na_ok2 basic"];
135 /* Case 3: leaf_nb_ok1 (revoked) */
136 /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */
137 [self run_valid_trust_test:leaf_nb_ok1 ca:ca_nb subca:NULL anchors:anchors date:date_20180102
138 policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure
139 test_name:"leaf_nb_ok1 basic"];
141 /* Case 4: leaf_nb_ok2 (not revoked) */
142 /* -- OK: cert issued 2017-10-26, after the CA not-before date of 2017-10-22 */
143 [self run_valid_trust_test:leaf_nb_ok2 ca:ca_nb subca:NULL anchors:anchors date:date_20180102
144 policyID:kBasicPolicy expected:kSecTrustResultUnspecified
145 test_name:"leaf_nb_ok2 basic"];
147 /* Case 5: leaf_nb_revoked1 (revoked) */
148 /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */
149 [self run_valid_trust_test:leaf_nb_revoked1 ca:ca_nb subca:NULL anchors:anchors date:date_20180102
150 policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure
151 test_name:"leaf_nb_revoked1 basic"];
153 CFReleaseSafe(ca_na);
154 CFReleaseSafe(ca_nb);
155 CFReleaseSafe(leaf_na_ok1);
156 CFReleaseSafe(leaf_na_ok2);
157 CFReleaseSafe(leaf_nb_ok1);
158 CFReleaseSafe(leaf_nb_ok2);
159 CFReleaseSafe(leaf_nb_revoked1);
161 CFReleaseSafe(anchors);
163 CFReleaseSafe(date_20180102);
166 - (void)test_known_intermediate
168 SecCertificateRef ca_ki=NULL, root=NULL;
169 SecCertificateRef leaf_ki_ok1=NULL, leaf_ki_revoked1=NULL;
170 SecCertificateRef leaf_unknown=NULL, ca_unknown=NULL;
172 isnt(ca_ki = [self createCertFromResource:@"ca-ki"], NULL, "create ca-ki cert");
173 isnt(root = [self createCertFromResource:@"root"], NULL, "create root cert");
174 isnt(leaf_ki_ok1 = [self createCertFromResource:@"leaf-ki-ok1"], NULL, "create leaf-ki-ok1 cert");
175 isnt(leaf_ki_revoked1 = [self createCertFromResource:@"leaf-ki-revoked1"], NULL, "create leaf-ki-revoked1 cert");
176 isnt(ca_unknown = [self createCertFromResource:@"ca-unknown"], NULL, "create ca-unknown cert");
177 isnt(leaf_unknown = [self createCertFromResource:@"leaf-unknown"], NULL, "create leaf-unknown cert");
179 CFMutableArrayRef anchors=NULL;
180 isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array");
181 if (anchors && root) {
182 CFArrayAppendValue(anchors, root);
184 CFCalendarRef cal = NULL;
186 CFDateRef date_20180310 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info
188 isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar");
189 ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 3, 10), "create verify absolute time 20180310");
190 isnt(date_20180310 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180310");
192 /* Case 1: leaf_ki_ok1 */
193 /* -- OK: cert issued by a known intermediate */
194 [self run_valid_trust_test:leaf_ki_ok1 ca:ca_ki subca:NULL anchors:anchors date:date_20180310 policyID:kBasicPolicy expected:kSecTrustResultUnspecified test_name:"leaf_ki_ok1"];
196 /* Case 2: leaf_ki_revoked1 */
197 /* -- BAD: CA specifies known-only+complete serial blocklist; this cert is on the blocklist. */
198 [self run_valid_trust_test:leaf_ki_revoked1 ca:ca_ki subca:NULL anchors:anchors date:date_20180310 policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure test_name:"leaf_ki_revoked"];
200 /* Case 3: leaf_unknown */
201 /* -- BAD: ca_unknown issued from ca_ki, but is not a known intermediate.
202 * ca_ki has a path len of 0 which would normally result in kSecTrustResultRecoverableTrustFailure;
203 * however, since known-intermediates is asserted for ca_ki (non-overridable), we expect a fatal failure. */
204 [self run_valid_trust_test:leaf_unknown ca:ca_unknown subca:ca_ki anchors:anchors date:date_20180310 policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure test_name:"leaf_unknown test"];
206 CFReleaseSafe(ca_ki);
207 CFReleaseSafe(leaf_ki_ok1);
208 CFReleaseSafe(leaf_ki_revoked1);
209 CFReleaseSafe(ca_unknown);
210 CFReleaseSafe(leaf_unknown);
212 CFReleaseSafe(anchors);
214 CFReleaseSafe(date_20180310);
216 #else /* TARGET_OS_BRIDGE */
217 /* Valid is not supported on bridgeOS */
218 - (void)testSkipTests