]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/secitem/si-97-sectrust-path-scoring.m
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / secitem / si-97-sectrust-path-scoring.m
1 /*
2 * Copyright (c) 2016 Apple Inc. All Rights Reserved.
3 */
4
5 #include <AssertMacros.h>
6 #import <Foundation/Foundation.h>
7 #include <Security/SecCertificate.h>
8 #include <Security/SecCertificatePriv.h>
9 #include <Security/SecPolicyPriv.h>
10 #include <Security/SecTrust.h>
11 #include <utilities/SecCFRelease.h>
12
13 #include "shared_regressions.h"
14
15 #include "si-97-sectrust-path-scoring.h"
16
17 static SecCertificateRef leaf = NULL;
18 static SecCertificateRef intSHA2 = NULL;
19 static SecCertificateRef intSHA1 = NULL;
20 static SecCertificateRef int1024 = NULL;
21 static SecCertificateRef rootSHA2 = NULL;
22 static SecCertificateRef rootSHA1 = NULL;
23 static SecCertificateRef root1024 = NULL;
24 static SecCertificateRef crossSHA2_SHA1 = NULL;
25 static SecCertificateRef crossSHA2_SHA2 = NULL;
26 static SecCertificateRef rootSHA2_2 = NULL;
27 static SecPolicyRef basicPolicy = NULL;
28 static SecPolicyRef sslPolicy = NULL;
29 static NSDate *verifyDate1 = nil;
30 static NSDate *verifyDate2 = nil;
31
32 static void setup_globals(void) {
33 leaf = SecCertificateCreateWithBytes(NULL, _pathScoringLeaf, sizeof(_pathScoringLeaf));
34 intSHA2 = SecCertificateCreateWithBytes(NULL, _pathScoringIntSHA2, sizeof(_pathScoringIntSHA2));
35 intSHA1 = SecCertificateCreateWithBytes(NULL, _pathScoringIntSHA1, sizeof(_pathScoringIntSHA1));
36 int1024 = SecCertificateCreateWithBytes(NULL, _pathScoringInt1024, sizeof(_pathScoringInt1024));
37 rootSHA2 = SecCertificateCreateWithBytes(NULL, _pathScoringSHA2Root, sizeof(_pathScoringSHA2Root));
38 rootSHA1 = SecCertificateCreateWithBytes(NULL, _pathScoringSHA1Root, sizeof(_pathScoringSHA1Root));
39 root1024 = SecCertificateCreateWithBytes(NULL, _pathScoring1024Root, sizeof(_pathScoring1024Root));
40 crossSHA2_SHA1 = SecCertificateCreateWithBytes(NULL, _pathScoringSHA2CrossSHA1, sizeof(_pathScoringSHA2CrossSHA1));
41 crossSHA2_SHA2 = SecCertificateCreateWithBytes(NULL, _pathScoringSHA2CrossSHA2, sizeof(_pathScoringSHA2CrossSHA2));
42 rootSHA2_2 = SecCertificateCreateWithBytes(NULL, _pathScoringSHA2Root2, sizeof(_pathScoringSHA2Root2));
43
44 basicPolicy = SecPolicyCreateBasicX509();
45 sslPolicy = SecPolicyCreateSSL(true, NULL);
46
47 // May 1, 2016 at 5:53:20 AM PDT
48 verifyDate1 = [NSDate dateWithTimeIntervalSinceReferenceDate:483800000.0];
49 // May 27, 2016 at 4:20:50 PM PDT
50 verifyDate2 = [NSDate dateWithTimeIntervalSinceReferenceDate:486084050.0];
51 }
52
53 static void cleanup_globals(void) {
54 CFReleaseNull(leaf);
55 CFReleaseNull(intSHA2);
56 CFReleaseNull(intSHA1);
57 CFReleaseNull(int1024);
58 CFReleaseNull(rootSHA2);
59 CFReleaseNull(rootSHA1);
60 CFReleaseNull(root1024);
61 CFReleaseNull(crossSHA2_SHA1);
62 CFReleaseNull(crossSHA2_SHA2);
63 CFReleaseNull(rootSHA2_2);
64
65 CFReleaseNull(basicPolicy);
66 CFReleaseNull(sslPolicy);
67 }
68
69 static bool testTrust(NSArray *certs, NSArray *anchors, SecPolicyRef policy,
70 NSDate *verifyDate, SecTrustResultType expectedResult,
71 NSArray *expectedChain) {
72 bool testPassed = false;
73 SecTrustRef trust = NULL;
74 SecTrustResultType trustResult = kSecTrustResultInvalid;
75 require_noerr_string(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs,
76 policy,
77 &trust),
78 errOut, "failed to create trust ref");
79 if (anchors) {
80 require_noerr_string(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors),
81 errOut, "failed to set anchors");
82 }
83 require_noerr_string(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate),
84 errOut, "failed to set verify date");
85 require_noerr_string(SecTrustEvaluate(trust, &trustResult),
86 errOut, "failed to evaluate trust");
87
88 /* check result */
89 if (expectedResult == kSecTrustResultUnspecified) {
90 require_string(trustResult == expectedResult,
91 errOut, "unexpected untrusted chain");
92 } else if (expectedResult == kSecTrustResultRecoverableTrustFailure) {
93 require_string(trustResult == expectedResult,
94 errOut, "unexpected trusted chain");
95 }
96
97 /* check the chain that returned */
98 require_string((NSUInteger)SecTrustGetCertificateCount(trust) == [expectedChain count],
99 errOut, "wrong number of certs in result chain");
100 NSUInteger ix, count = [expectedChain count];
101 for (ix = 0; ix < count; ix++) {
102 require_string(CFEqual(SecTrustGetCertificateAtIndex(trust, ix),
103 (__bridge SecCertificateRef)[expectedChain objectAtIndex:ix]),
104 errOut, "chain didn't match expected");
105 }
106 testPassed = true;
107
108 errOut:
109 CFReleaseNull(trust);
110 return testPassed;
111 }
112
113 /* Path Scoring Hierarchy
114 * leaf
115 * ^ ^ ^
116 * / | \
117 * intSHA2 intSHA1 int1024
118 * ^ ^ ^ ^ ^
119 * / | \ | |
120 * rootSHA2 crossSHA2_SHA1 crossSHA2_SHA2 rootSHA1 root1024
121 * ^ ^
122 * | |
123 * rootSHA1 rootSHA2_2
124 */
125
126 static void tests(SecPolicyRef policy) {
127 NSArray *certs = nil;
128 NSArray *anchors = nil;
129 NSArray *chain = nil;
130 SecTrustResultType expectedTrustResult = ((policy == basicPolicy) ? kSecTrustResultUnspecified :
131 kSecTrustResultRecoverableTrustFailure);
132
133 /* Choose a short chain over a long chain, when ending in a self-signed cert */
134 certs = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)crossSHA2_SHA2];
135 anchors = @[(__bridge id)rootSHA2, (__bridge id)rootSHA2_2];
136 chain = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)rootSHA2];
137 ok(testTrust(certs, anchors, policy, verifyDate1, expectedTrustResult, chain),
138 "%s test: choose shorter chain over longer chain, SHA-2",
139 (policy == basicPolicy) ? "accept" : "reject");
140
141 certs = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)intSHA1, (__bridge id)crossSHA2_SHA1];
142 anchors = @[(__bridge id)rootSHA1];
143 chain = @[(__bridge id)leaf, (__bridge id)intSHA1, (__bridge id)rootSHA1];
144 ok(testTrust(certs, anchors, policy, verifyDate1, expectedTrustResult, chain),
145 "%s test: choose shorter chain over longer chain, SHA-1",
146 (policy == basicPolicy) ? "accept" : "reject");
147
148 /* Choose a SHA-2 chain over a SHA-1 chain */
149 certs = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)intSHA1];
150 anchors = @[(__bridge id)rootSHA1, (__bridge id)rootSHA2];
151 chain = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)rootSHA2];
152 ok(testTrust(certs, anchors, policy, verifyDate1, expectedTrustResult, chain),
153 "%s test: choose SHA-2 chain over SHA-1 chain, order 1",
154 (policy == basicPolicy) ? "accept" : "reject");
155
156 certs = @[(__bridge id)leaf, (__bridge id)intSHA1, (__bridge id)intSHA2];
157 anchors = @[(__bridge id)rootSHA2, (__bridge id)rootSHA1];
158 ok(testTrust(certs, anchors, policy, verifyDate1, expectedTrustResult, chain),
159 "%s test: choose SHA-2 chain over SHA-1 chain, order 2",
160 (policy == basicPolicy) ? "accept" : "reject");
161
162 /* Choose a longer SHA-2 chain over the shorter SHA-1 chain */
163 certs = @[(__bridge id)leaf, (__bridge id)intSHA1, (__bridge id)intSHA2, (__bridge id)crossSHA2_SHA2];
164 anchors = @[(__bridge id)rootSHA1, (__bridge id)rootSHA2_2];
165 chain = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)crossSHA2_SHA2, (__bridge id)rootSHA2_2];
166 ok(testTrust(certs, anchors, policy, verifyDate1, expectedTrustResult, chain),
167 "%s test: choose longer SHA-2 chain over shorter SHA-1 chain",
168 (policy == basicPolicy) ? "accept" : "reject");
169
170 /* Choose 1024-bit temporally valid chain over 2048-bit invalid chain */
171 certs = @[(__bridge id)leaf, (__bridge id)int1024, (__bridge id)intSHA1];
172 anchors = @[(__bridge id)root1024, (__bridge id)rootSHA1];
173 chain = @[(__bridge id)leaf, (__bridge id)int1024, (__bridge id)root1024];
174 ok(testTrust(certs, anchors, policy, verifyDate2, expectedTrustResult, chain),
175 "%s test: choose temporally valid chain over invalid chain",
176 (policy == basicPolicy) ? "accept" : "reject");
177
178 /* Choose an anchored chain over an unanchored chain */
179 certs = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)intSHA1, (__bridge id)rootSHA2];
180 anchors = @[(__bridge id)rootSHA1];
181 chain = @[(__bridge id)leaf, (__bridge id)intSHA1, (__bridge id)rootSHA1];
182 ok(testTrust(certs, anchors, policy, verifyDate1, expectedTrustResult, chain),
183 "%s test: choose an anchored chain over an unanchored chain",
184 (policy == basicPolicy) ? "accept" : "reject");
185
186 /* Choose an anchored SHA-1 chain over an unanchored SHA-2 chain */
187 certs = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)intSHA1, (__bridge id)rootSHA2];
188 anchors = @[(__bridge id)rootSHA1];
189 chain = @[(__bridge id)leaf, (__bridge id)intSHA1, (__bridge id)rootSHA1];
190 ok(testTrust(certs, anchors, policy, verifyDate1, expectedTrustResult, chain),
191 "%s test: choose anchored SHA-1 chain over unanchored SHA-2 chain",
192 (policy == basicPolicy) ? "accept" : "reject");
193
194 /* Choose an anchored SHA-1 cross-signed chain over unanchored SHA-2 chains */
195 certs = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)rootSHA2,
196 (__bridge id)crossSHA2_SHA1, (__bridge id)crossSHA2_SHA2, (__bridge id)rootSHA2_2];
197 chain = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)crossSHA2_SHA1, (__bridge id)rootSHA1];
198 ok(testTrust(certs, anchors, policy, verifyDate1, expectedTrustResult, chain),
199 "%s test: choose anchored cross-signed chain over unanchored chains",
200 (policy == basicPolicy) ? "accept" : "reject");
201 }
202
203 static void accept_tests(void) {
204 tests(basicPolicy);
205
206 }
207
208 static void reject_tests(void) {
209 /* The leaf certificate is a client SSL certificate, and will fail the sslPolicy. */
210 tests(sslPolicy);
211
212 /* reject only tests */
213 NSArray *certs = nil;
214 NSArray *anchors = nil;
215 NSArray *chain = nil;
216
217 /* Choose a 2048-bit chain over a 1024-bit chain */
218 certs = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)int1024];
219 anchors = @[(__bridge id)rootSHA2, (__bridge id)root1024];
220 chain = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)rootSHA2];
221 ok(testTrust(certs, anchors, sslPolicy, verifyDate1, kSecTrustResultRecoverableTrustFailure, chain),
222 "reject test: choose 2048-bit chain over 1024-bit chain, order 1");
223
224 certs = @[(__bridge id)leaf, (__bridge id)int1024, (__bridge id)intSHA2];
225 anchors = @[(__bridge id)root1024, (__bridge id)rootSHA2];
226 ok(testTrust(certs, anchors, sslPolicy, verifyDate1, kSecTrustResultRecoverableTrustFailure, chain),
227 "reject test: choose 2048-bit chain over 1024-bit chain, order 2");
228
229 /* Choose a complete chain over an incomplete chain */
230 certs = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)intSHA1, (__bridge id)rootSHA1];
231 anchors = @[];
232 chain = @[(__bridge id)leaf, (__bridge id)intSHA1, (__bridge id)rootSHA1];
233 ok(testTrust(certs, anchors, sslPolicy, verifyDate1, kSecTrustResultRecoverableTrustFailure, chain),
234 "reject test: choose a chain that ends in a self-signed cert over one that doesn't");
235
236 /* Choose a long chain over a short chain when not ending with a self-signed cert */
237 certs = @[(__bridge id)leaf, (__bridge id)crossSHA2_SHA2, (__bridge id)intSHA2];
238 anchors = nil;
239 chain = @[(__bridge id)leaf, (__bridge id)intSHA2, (__bridge id)crossSHA2_SHA2];
240 ok(testTrust(certs, anchors, sslPolicy, verifyDate1, kSecTrustResultRecoverableTrustFailure, chain),
241 "reject test: choose longer chain over shorter chain, no roots");
242 }
243
244 int si_97_sectrust_path_scoring(int argc, char *const *argv)
245 {
246 plan_tests(2*9 + 4);
247
248 @autoreleasepool {
249 setup_globals();
250 accept_tests();
251 reject_tests();
252 cleanup_globals();
253 }
254
255 return 0;
256 }