1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/cert/cert_verify_proc_android.h"
6
7 #include <memory>
8 #include <vector>
9
10 #include "net/cert/cert_net_fetcher.h"
11 #include "net/cert/cert_verify_proc_android.h"
12 #include "net/cert/cert_verify_result.h"
13 #include "net/cert/crl_set.h"
14 #include "net/cert/internal/test_helpers.h"
15 #include "net/cert/mock_cert_net_fetcher.h"
16 #include "net/cert/test_root_certs.h"
17 #include "net/cert/x509_certificate.h"
18 #include "net/cert/x509_util.h"
19 #include "net/log/net_log_with_source.h"
20 #include "net/test/cert_builder.h"
21 #include "net/test/cert_test_util.h"
22 #include "net/test/test_certificate_data.h"
23 #include "net/test/test_data_directory.h"
24 #include "testing/gmock/include/gmock/gmock-matchers.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "url/gurl.h"
28
29 using ::testing::ByMove;
30 using ::testing::Return;
31 using ::testing::_;
32
33 namespace net {
34
35 namespace {
36
37 const char kHostname[] = "example.com";
38 const GURL kRootURL("http://aia.test/root");
39 const GURL kIntermediateURL("http://aia.test/intermediate");
40
41 std::unique_ptr<CertNetFetcher::Request>
CreateMockRequestWithInvalidCertificate()42 CreateMockRequestWithInvalidCertificate() {
43 return MockCertNetFetcherRequest::Create(std::vector<uint8_t>({1, 2, 3}));
44 }
45
46 // A test fixture for testing CertVerifyProcAndroid AIA fetching. It creates,
47 // sets up, and shuts down a MockCertNetFetcher for CertVerifyProcAndroid to
48 // use, and enables the field trial for AIA fetching.
49 class CertVerifyProcAndroidTestWithAIAFetching : public testing::Test {
50 public:
SetUp()51 void SetUp() override {
52 fetcher_ = base::MakeRefCounted<MockCertNetFetcher>();
53
54 // Generate a certificate chain with AIA pointers. Tests can modify these
55 // if testing a different scenario.
56 std::tie(leaf_, intermediate_, root_) = CertBuilder::CreateSimpleChain3();
57 root_->SetCaIssuersUrl(kRootURL);
58 intermediate_->SetCaIssuersUrl(kRootURL);
59 leaf_->SetCaIssuersUrl(kIntermediateURL);
60 leaf_->SetSubjectAltName(kHostname);
61 }
62
TearDown()63 void TearDown() override {
64 // Ensure that mock expectations are checked, since the CertNetFetcher is
65 // global and leaky.
66 ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(fetcher_.get()));
67 }
68
LeafOnly()69 scoped_refptr<X509Certificate> LeafOnly() {
70 return leaf_->GetX509Certificate();
71 }
72
LeafWithIntermediate()73 scoped_refptr<X509Certificate> LeafWithIntermediate() {
74 return leaf_->GetX509CertificateChain();
75 }
76
77 protected:
TrustTestRoot()78 void TrustTestRoot() {
79 scoped_test_root_.Reset({root_->GetX509Certificate()});
80 }
81
82 scoped_refptr<MockCertNetFetcher> fetcher_;
83 std::unique_ptr<CertBuilder> root_;
84 std::unique_ptr<CertBuilder> intermediate_;
85 std::unique_ptr<CertBuilder> leaf_;
86
87 private:
88 ScopedTestRoot scoped_test_root_;
89 };
90
91 } // namespace
92
93 // Tests that if the proper intermediates are supplied in the server-sent chain,
94 // no AIA fetch occurs.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,NoFetchIfProperIntermediatesSupplied)95 TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
96 NoFetchIfProperIntermediatesSupplied) {
97 TrustTestRoot();
98 scoped_refptr<CertVerifyProcAndroid> proc =
99 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
100 CRLSet::BuiltinCRLSet());
101 CertVerifyResult verify_result;
102 EXPECT_EQ(OK, proc->Verify(LeafWithIntermediate().get(), kHostname,
103 /*ocsp_response=*/std::string(),
104 /*sct_list=*/std::string(), 0, &verify_result,
105 NetLogWithSource()));
106 }
107
108 // Tests that if the certificate does not contain an AIA URL, no AIA fetch
109 // occurs.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,NoAIAURL)110 TEST_F(CertVerifyProcAndroidTestWithAIAFetching, NoAIAURL) {
111 leaf_->SetCaIssuersAndOCSPUrls(/*ca_issuers_urls=*/{}, /*ocsp_urls=*/{});
112 TrustTestRoot();
113 scoped_refptr<CertVerifyProcAndroid> proc =
114 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
115 CRLSet::BuiltinCRLSet());
116 CertVerifyResult verify_result;
117 EXPECT_EQ(
118 ERR_CERT_AUTHORITY_INVALID,
119 proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
120 /*sct_list=*/std::string(), 0, &verify_result,
121 NetLogWithSource()));
122 }
123
124 // Tests that if a certificate contains one file:// URL and one http:// URL,
125 // there are two fetches, with the latter resulting in a successful
126 // verification.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,OneFileAndOneHTTPURL)127 TEST_F(CertVerifyProcAndroidTestWithAIAFetching, OneFileAndOneHTTPURL) {
128 const GURL kFileURL("file:///dev/null");
129 leaf_->SetCaIssuersAndOCSPUrls(
130 /*ca_issuers_urls=*/{kFileURL, kIntermediateURL},
131 /*ocsp_urls=*/{});
132 TrustTestRoot();
133 scoped_refptr<CertVerifyProcAndroid> proc =
134 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
135 CRLSet::BuiltinCRLSet());
136
137 // Expect two fetches: the file:// URL (which returns an error), and the
138 // http:// URL that returns a valid intermediate signed by |root_|. Though the
139 // intermediate itself contains an AIA URL, it should not be fetched because
140 // |root_| is in the test trust store.
141 EXPECT_CALL(*fetcher_, FetchCaIssuers(kFileURL, _, _))
142 .WillOnce(Return(ByMove(
143 MockCertNetFetcherRequest::Create(ERR_DISALLOWED_URL_SCHEME))));
144 EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
145 .WillOnce(Return(ByMove(
146 MockCertNetFetcherRequest::Create(intermediate_->GetCertBuffer()))));
147
148 CertVerifyResult verify_result;
149 EXPECT_EQ(OK, proc->Verify(LeafOnly().get(), kHostname,
150 /*ocsp_response=*/std::string(),
151 /*sct_list=*/std::string(), 0, &verify_result,
152 NetLogWithSource()));
153 }
154
155 // Tests that if an AIA request returns the wrong intermediate, certificate
156 // verification should fail.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,UnsuccessfulVerificationWithLeafOnly)157 TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
158 UnsuccessfulVerificationWithLeafOnly) {
159 TrustTestRoot();
160 scoped_refptr<CertVerifyProcAndroid> proc =
161 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
162 CRLSet::BuiltinCRLSet());
163 const scoped_refptr<X509Certificate> bad_intermediate =
164 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
165
166 EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
167 .WillOnce(Return(ByMove(
168 MockCertNetFetcherRequest::Create(bad_intermediate->cert_buffer()))));
169
170 CertVerifyResult verify_result;
171 EXPECT_EQ(
172 ERR_CERT_AUTHORITY_INVALID,
173 proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
174 /*sct_list=*/std::string(), 0, &verify_result,
175 NetLogWithSource()));
176 }
177
178 // Tests that if an AIA request returns an error, certificate verification
179 // should fail.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,UnsuccessfulVerificationWithLeafOnlyAndErrorOnFetch)180 TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
181 UnsuccessfulVerificationWithLeafOnlyAndErrorOnFetch) {
182 TrustTestRoot();
183 scoped_refptr<CertVerifyProcAndroid> proc =
184 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
185 CRLSet::BuiltinCRLSet());
186
187 EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
188 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))));
189
190 CertVerifyResult verify_result;
191 EXPECT_EQ(
192 ERR_CERT_AUTHORITY_INVALID,
193 proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
194 /*sct_list=*/std::string(), 0, &verify_result,
195 NetLogWithSource()));
196 }
197
198 // Tests that if an AIA request returns an unparseable cert, certificate
199 // verification should fail.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,UnsuccessfulVerificationWithLeafOnlyAndUnparseableFetch)200 TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
201 UnsuccessfulVerificationWithLeafOnlyAndUnparseableFetch) {
202 TrustTestRoot();
203 scoped_refptr<CertVerifyProcAndroid> proc =
204 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
205 CRLSet::BuiltinCRLSet());
206
207 EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
208 .WillOnce(Return(ByMove(CreateMockRequestWithInvalidCertificate())));
209
210 CertVerifyResult verify_result;
211 EXPECT_EQ(
212 ERR_CERT_AUTHORITY_INVALID,
213 proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
214 /*sct_list=*/std::string(), 0, &verify_result,
215 NetLogWithSource()));
216 }
217
218 // Tests that if a certificate has two HTTP AIA URLs, they are both fetched. If
219 // one serves an unrelated certificate and one serves a proper intermediate, the
220 // latter should be used to build a valid chain.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,TwoHTTPURLs)221 TEST_F(CertVerifyProcAndroidTestWithAIAFetching, TwoHTTPURLs) {
222 const GURL kUnrelatedURL("http://aia.test/unrelated");
223 leaf_->SetCaIssuersAndOCSPUrls(
224 /*ca_issuers_urls=*/{kUnrelatedURL, kIntermediateURL},
225 /*ocsp_urls=*/{});
226 scoped_refptr<X509Certificate> unrelated =
227 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
228 ASSERT_TRUE(unrelated);
229
230 TrustTestRoot();
231 scoped_refptr<CertVerifyProcAndroid> proc =
232 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
233 CRLSet::BuiltinCRLSet());
234
235 // Expect two fetches, the first of which returns an unrelated certificate
236 // that is not useful in chain-building, and the second of which returns a
237 // valid intermediate signed by |root_|. Though the intermediate itself
238 // contains an AIA URL, it should not be fetched because |root_| is in the
239 // trust store.
240 EXPECT_CALL(*fetcher_, FetchCaIssuers(kUnrelatedURL, _, _))
241 .WillOnce(Return(
242 ByMove(MockCertNetFetcherRequest::Create(unrelated->cert_buffer()))));
243 EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
244 .WillOnce(Return(ByMove(
245 MockCertNetFetcherRequest::Create(intermediate_->GetCertBuffer()))));
246
247 CertVerifyResult verify_result;
248 EXPECT_EQ(OK, proc->Verify(LeafOnly().get(), kHostname,
249 /*ocsp_response=*/std::string(),
250 /*sct_list=*/std::string(), 0, &verify_result,
251 NetLogWithSource()));
252 }
253
254 // Tests that if an intermediate is fetched via AIA, and the intermediate itself
255 // has an AIA URL, that URL is fetched if necessary.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,AIAFetchForFetchedIntermediate)256 TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
257 AIAFetchForFetchedIntermediate) {
258 // Do not set up the test root to be trusted. If the test root were trusted,
259 // then the intermediate would not require an AIA fetch. With the test root
260 // untrusted, the intermediate does not verify and so it will trigger an AIA
261 // fetch.
262 scoped_refptr<CertVerifyProcAndroid> proc =
263 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
264 CRLSet::BuiltinCRLSet());
265
266 // Expect two fetches, the first of which returns an intermediate that itself
267 // has an AIA URL.
268 EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
269 .WillOnce(Return(ByMove(
270 MockCertNetFetcherRequest::Create(intermediate_->GetCertBuffer()))));
271 EXPECT_CALL(*fetcher_, FetchCaIssuers(kRootURL, _, _))
272 .WillOnce(Return(
273 ByMove(MockCertNetFetcherRequest::Create(root_->GetCertBuffer()))));
274
275 CertVerifyResult verify_result;
276 // This chain results in an AUTHORITY_INVALID root because |root_| is not
277 // trusted.
278 EXPECT_EQ(
279 ERR_CERT_AUTHORITY_INVALID,
280 proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
281 /*sct_list=*/std::string(), 0, &verify_result,
282 NetLogWithSource()));
283 }
284
285 // Tests that if a certificate contains six AIA URLs, only the first five are
286 // fetched, since the maximum number of fetches per Verify() call is five.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,MaxAIAFetches)287 TEST_F(CertVerifyProcAndroidTestWithAIAFetching, MaxAIAFetches) {
288 leaf_->SetCaIssuersAndOCSPUrls(
289 /*ca_issuers_urls=*/{GURL("http://aia.test/1"), GURL("http://aia.test/2"),
290 GURL("http://aia.test/3"), GURL("http://aia.test/4"),
291 GURL("http://aia.test/5"),
292 GURL("http://aia.test/6")},
293 /*ocsp_urls=*/{});
294 TrustTestRoot();
295 scoped_refptr<CertVerifyProcAndroid> proc =
296 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
297 CRLSet::BuiltinCRLSet());
298
299 EXPECT_CALL(*fetcher_, FetchCaIssuers(_, _, _))
300 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))))
301 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))))
302 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))))
303 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))))
304 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))));
305
306 CertVerifyResult verify_result;
307 EXPECT_EQ(
308 ERR_CERT_AUTHORITY_INVALID,
309 proc->Verify(LeafOnly().get(), kHostname, /*ocsp_response=*/std::string(),
310 /*sct_list=*/std::string(), 0, &verify_result,
311 NetLogWithSource()));
312 }
313
314 // Tests that if the supplied chain contains an intermediate with an AIA URL,
315 // that AIA URL is fetched if necessary.
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,FetchForSuppliedIntermediate)316 TEST_F(CertVerifyProcAndroidTestWithAIAFetching, FetchForSuppliedIntermediate) {
317 // Do not set up the test root to be trusted. If the test root were trusted,
318 // then the intermediate would not require an AIA fetch. With the test root
319 // untrusted, the intermediate does not verify and so it will trigger an AIA
320 // fetch.
321 scoped_refptr<CertVerifyProcAndroid> proc =
322 base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
323 CRLSet::BuiltinCRLSet());
324
325 EXPECT_CALL(*fetcher_, FetchCaIssuers(kRootURL, _, _))
326 .WillOnce(Return(
327 ByMove(MockCertNetFetcherRequest::Create(root_->GetCertBuffer()))));
328
329 CertVerifyResult verify_result;
330 // This chain results in an AUTHORITY_INVALID root because |root_| is not
331 // trusted.
332 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID,
333 proc->Verify(LeafWithIntermediate().get(), kHostname,
334 /*ocsp_response=*/std::string(),
335 /*sct_list=*/std::string(), 0, &verify_result,
336 NetLogWithSource()));
337 }
338
339 } // namespace net
340