xref: /aosp_15_r20/external/cronet/net/cert/cert_verify_proc_android_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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