1 // Copyright 2014 The Chromium Authors. All rights reserved.
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 "services/network/cert_verifier_with_trust_anchors.h"
6 
7 #include <memory>
8 #include <string>
9 #include <utility>
10 
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/callback.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/run_loop.h"
16 #include "base/test/task_environment.h"
17 #include "crypto/nss_util_internal.h"
18 #include "crypto/scoped_test_nss_chromeos_user.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/cert/cert_net_fetcher.h"
21 #include "net/cert/cert_verify_proc_builtin.h"
22 #include "net/cert/cert_verify_result.h"
23 #include "net/cert/nss_cert_database_chromeos.h"
24 #include "net/cert/x509_certificate.h"
25 #include "net/cert/x509_util_nss.h"
26 #include "net/log/net_log_with_source.h"
27 #include "net/test/cert_test_util.h"
28 #include "net/test/test_data_directory.h"
29 #include "services/network/cert_verify_proc_chromeos.h"
30 #include "services/network/system_trust_store_provider_chromeos.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 
33 namespace network {
34 
35 class CertVerifierWithTrustAnchorsTest : public testing::TestWithParam<bool> {
36  public:
CertVerifierWithTrustAnchorsTest()37   CertVerifierWithTrustAnchorsTest()
38       : trust_anchor_used_(false),
39         test_nss_user_("user1"),
40         task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
41 
~CertVerifierWithTrustAnchorsTest()42   ~CertVerifierWithTrustAnchorsTest() override {}
43 
SetUp()44   void SetUp() override {
45     ASSERT_TRUE(test_nss_user_.constructed_successfully());
46     test_nss_user_.FinishInit();
47 
48     test_cert_db_ = std::make_unique<net::NSSCertDatabaseChromeOS>(
49         crypto::GetPublicSlotForChromeOSUser(test_nss_user_.username_hash()),
50         crypto::GetPrivateSlotForChromeOSUser(
51             test_nss_user_.username_hash(),
52             base::RepeatingCallback<void(crypto::ScopedPK11Slot)>()));
53 
54     cert_verifier_ =
55         std::make_unique<CertVerifierWithTrustAnchors>(base::BindRepeating(
56             &CertVerifierWithTrustAnchorsTest::OnTrustAnchorUsed,
57             base::Unretained(this)));
58     if (GetParam()) {
59       cert_verify_proc_ = net::CreateCertVerifyProcBuiltin(
60           /*net_fetcher=*/nullptr,
61           std::make_unique<SystemTrustStoreProviderChromeOS>(
62               crypto::GetPublicSlotForChromeOSUser(
63                   test_nss_user_.username_hash())));
64     } else {
65       cert_verify_proc_ = base::MakeRefCounted<network::CertVerifyProcChromeOS>(
66           crypto::GetPublicSlotForChromeOSUser(test_nss_user_.username_hash()));
67     }
68     cert_verifier_->InitializeOnIOThread(cert_verify_proc_);
69 
70     test_ca_cert_ = LoadCertificate("root_ca_cert.pem", net::CA_CERT);
71     ASSERT_TRUE(test_ca_cert_);
72     test_ca_cert_list_.push_back(
73         net::x509_util::DupCERTCertificate(test_ca_cert_.get()));
74 
75     net::ScopedCERTCertificate test_server_cert =
76         LoadCertificate("ok_cert.pem", net::SERVER_CERT);
77     ASSERT_TRUE(test_server_cert);
78     test_server_cert_ =
79         net::x509_util::CreateX509CertificateFromCERTCertificate(
80             test_server_cert.get());
81     ASSERT_TRUE(test_server_cert_);
82   }
83 
TearDown()84   void TearDown() override {
85     // Destroy |cert_verifier_| before destroying the TaskEnvironment, otherwise
86     // BrowserThread::CurrentlyOn checks fail.
87     cert_verifier_.reset();
88   }
89 
90  protected:
VerifyTestServerCert(net::CompletionOnceCallback test_callback,net::CertVerifyResult * verify_result,std::unique_ptr<net::CertVerifier::Request> * request)91   int VerifyTestServerCert(
92       net::CompletionOnceCallback test_callback,
93       net::CertVerifyResult* verify_result,
94       std::unique_ptr<net::CertVerifier::Request>* request) {
95     return cert_verifier_->Verify(net::CertVerifier::RequestParams(
96                                       test_server_cert_.get(), "127.0.0.1", 0,
97                                       /*ocsp_response=*/std::string(),
98                                       /*sct_list=*/std::string()),
99                                   verify_result, std::move(test_callback),
100                                   request, net::NetLogWithSource());
101   }
102 
SupportsAdditionalTrustAnchors()103   bool SupportsAdditionalTrustAnchors() {
104     return cert_verify_proc_->SupportsAdditionalTrustAnchors();
105   }
106 
107   // Returns whether |cert_verifier| signalled usage of one of the additional
108   // trust anchors (i.e. of |test_ca_cert_|) for the first time or since the
109   // last call of this function.
WasTrustAnchorUsedAndReset()110   bool WasTrustAnchorUsedAndReset() {
111     base::RunLoop().RunUntilIdle();
112     bool result = trust_anchor_used_;
113     trust_anchor_used_ = false;
114     return result;
115   }
116 
117   // |test_ca_cert_| is the issuer of |test_server_cert_|.
118   net::ScopedCERTCertificate test_ca_cert_;
119   scoped_refptr<net::X509Certificate> test_server_cert_;
120   net::ScopedCERTCertificateList test_ca_cert_list_;
121   std::unique_ptr<net::NSSCertDatabaseChromeOS> test_cert_db_;
122   std::unique_ptr<CertVerifierWithTrustAnchors> cert_verifier_;
123   scoped_refptr<net::CertVerifyProc> cert_verify_proc_;
124 
125  private:
OnTrustAnchorUsed()126   void OnTrustAnchorUsed() { trust_anchor_used_ = true; }
127 
LoadCertificate(const std::string & name,net::CertType type)128   net::ScopedCERTCertificate LoadCertificate(const std::string& name,
129                                              net::CertType type) {
130     net::ScopedCERTCertificate cert =
131         net::ImportCERTCertificateFromFile(net::GetTestCertsDirectory(), name);
132     if (!cert)
133       return cert;
134 
135     // No certificate is trusted right after it's loaded.
136     net::NSSCertDatabase::TrustBits trust =
137         test_cert_db_->GetCertTrust(cert.get(), type);
138     EXPECT_EQ(net::NSSCertDatabase::TRUST_DEFAULT, trust);
139 
140     return cert;
141   }
142 
143   bool trust_anchor_used_;
144   crypto::ScopedTestNSSChromeOSUser test_nss_user_;
145   base::test::TaskEnvironment task_environment_;
146 };
147 
148 INSTANTIATE_TEST_SUITE_P(All,
149                          CertVerifierWithTrustAnchorsTest,
150                          testing::Bool());
151 
TEST_P(CertVerifierWithTrustAnchorsTest,VerifyUntrustedCert)152 TEST_P(CertVerifierWithTrustAnchorsTest, VerifyUntrustedCert) {
153   // |test_server_cert_| is untrusted, so Verify() fails.
154   {
155     net::CertVerifyResult verify_result;
156     net::TestCompletionCallback callback;
157     std::unique_ptr<net::CertVerifier::Request> request;
158     int error =
159         VerifyTestServerCert(callback.callback(), &verify_result, &request);
160     ASSERT_EQ(net::ERR_IO_PENDING, error);
161     EXPECT_TRUE(request);
162     error = callback.WaitForResult();
163     EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
164   }
165 
166   // Issuing the same request again hits the cache. This tests the synchronous
167   // path.
168   {
169     net::CertVerifyResult verify_result;
170     net::TestCompletionCallback callback;
171     std::unique_ptr<net::CertVerifier::Request> request;
172     int error =
173         VerifyTestServerCert(callback.callback(), &verify_result, &request);
174     EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
175   }
176 
177   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
178 }
179 
TEST_P(CertVerifierWithTrustAnchorsTest,VerifyTrustedCert)180 TEST_P(CertVerifierWithTrustAnchorsTest, VerifyTrustedCert) {
181   // Make the database trust |test_ca_cert_|.
182   net::NSSCertDatabase::ImportCertFailureList failure_list;
183   ASSERT_TRUE(test_cert_db_->ImportCACerts(
184       test_ca_cert_list_, net::NSSCertDatabase::TRUSTED_SSL, &failure_list));
185   ASSERT_TRUE(failure_list.empty());
186 
187   // Verify that it is now trusted.
188   net::NSSCertDatabase::TrustBits trust =
189       test_cert_db_->GetCertTrust(test_ca_cert_.get(), net::CA_CERT);
190   EXPECT_EQ(net::NSSCertDatabase::TRUSTED_SSL, trust);
191 
192   // Verify() successfully verifies |test_server_cert_| after it was imported.
193   net::CertVerifyResult verify_result;
194   net::TestCompletionCallback callback;
195   std::unique_ptr<net::CertVerifier::Request> request;
196   int error =
197       VerifyTestServerCert(callback.callback(), &verify_result, &request);
198   ASSERT_EQ(net::ERR_IO_PENDING, error);
199   EXPECT_TRUE(request);
200   error = callback.WaitForResult();
201   EXPECT_EQ(net::OK, error);
202 
203   // The additional trust anchors were not used, since the certificate is
204   // trusted from the database.
205   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
206 }
207 
TEST_P(CertVerifierWithTrustAnchorsTest,VerifyUsingAdditionalTrustAnchor)208 TEST_P(CertVerifierWithTrustAnchorsTest, VerifyUsingAdditionalTrustAnchor) {
209   ASSERT_TRUE(SupportsAdditionalTrustAnchors());
210 
211   // |test_server_cert_| is untrusted, so Verify() fails.
212   {
213     net::CertVerifyResult verify_result;
214     net::TestCompletionCallback callback;
215     std::unique_ptr<net::CertVerifier::Request> request;
216     int error =
217         VerifyTestServerCert(callback.callback(), &verify_result, &request);
218     ASSERT_EQ(net::ERR_IO_PENDING, error);
219     EXPECT_TRUE(request);
220     error = callback.WaitForResult();
221     EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
222   }
223   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
224 
225   net::CertificateList test_ca_x509cert_list =
226       net::x509_util::CreateX509CertificateListFromCERTCertificates(
227           test_ca_cert_list_);
228   ASSERT_FALSE(test_ca_x509cert_list.empty());
229 
230   // Verify() again with the additional trust anchors.
231   cert_verifier_->SetTrustAnchors(test_ca_x509cert_list);
232   {
233     net::CertVerifyResult verify_result;
234     net::TestCompletionCallback callback;
235     std::unique_ptr<net::CertVerifier::Request> request;
236     int error =
237         VerifyTestServerCert(callback.callback(), &verify_result, &request);
238     ASSERT_EQ(net::ERR_IO_PENDING, error);
239     EXPECT_TRUE(request);
240     error = callback.WaitForResult();
241     EXPECT_EQ(net::OK, error);
242   }
243   EXPECT_TRUE(WasTrustAnchorUsedAndReset());
244 
245   // Verify() again with the additional trust anchors will hit the cache.
246   cert_verifier_->SetTrustAnchors(test_ca_x509cert_list);
247   {
248     net::CertVerifyResult verify_result;
249     net::TestCompletionCallback callback;
250     std::unique_ptr<net::CertVerifier::Request> request;
251     int error =
252         VerifyTestServerCert(callback.callback(), &verify_result, &request);
253     EXPECT_EQ(net::OK, error);
254   }
255   EXPECT_TRUE(WasTrustAnchorUsedAndReset());
256 
257   // Verifying after removing the trust anchors should now fail.
258   cert_verifier_->SetTrustAnchors(net::CertificateList());
259   {
260     net::CertVerifyResult verify_result;
261     net::TestCompletionCallback callback;
262     std::unique_ptr<net::CertVerifier::Request> request;
263     int error =
264         VerifyTestServerCert(callback.callback(), &verify_result, &request);
265     // Note: Changing the trust anchors should flush the cache.
266     ASSERT_EQ(net::ERR_IO_PENDING, error);
267     EXPECT_TRUE(request);
268     error = callback.WaitForResult();
269     EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
270   }
271   // The additional trust anchors were reset, thus |cert_verifier_| should not
272   // signal it's usage anymore.
273   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
274 }
275 
TEST_P(CertVerifierWithTrustAnchorsTest,VerifyUsesAdditionalTrustAnchorsAfterConfigChange)276 TEST_P(CertVerifierWithTrustAnchorsTest,
277        VerifyUsesAdditionalTrustAnchorsAfterConfigChange) {
278   ASSERT_TRUE(SupportsAdditionalTrustAnchors());
279 
280   // |test_server_cert_| is untrusted, so Verify() fails.
281   {
282     net::CertVerifyResult verify_result;
283     net::TestCompletionCallback callback;
284     std::unique_ptr<net::CertVerifier::Request> request;
285     int error =
286         VerifyTestServerCert(callback.callback(), &verify_result, &request);
287     ASSERT_EQ(net::ERR_IO_PENDING, error);
288     EXPECT_TRUE(request);
289     error = callback.WaitForResult();
290     EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
291   }
292   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
293 
294   net::CertificateList test_ca_x509cert_list =
295       net::x509_util::CreateX509CertificateListFromCERTCertificates(
296           test_ca_cert_list_);
297   ASSERT_FALSE(test_ca_x509cert_list.empty());
298 
299   // Verify() again with the additional trust anchors.
300   cert_verifier_->SetTrustAnchors(test_ca_x509cert_list);
301   {
302     net::CertVerifyResult verify_result;
303     net::TestCompletionCallback callback;
304     std::unique_ptr<net::CertVerifier::Request> request;
305     int error =
306         VerifyTestServerCert(callback.callback(), &verify_result, &request);
307     ASSERT_EQ(net::ERR_IO_PENDING, error);
308     EXPECT_TRUE(request);
309     error = callback.WaitForResult();
310     EXPECT_EQ(net::OK, error);
311   }
312   EXPECT_TRUE(WasTrustAnchorUsedAndReset());
313 
314   // Change the configuration to enable SHA-1, which should still use the
315   // additional trust anchors.
316   net::CertVerifier::Config config;
317   config.enable_sha1_local_anchors = true;
318   cert_verifier_->SetConfig(config);
319   {
320     net::CertVerifyResult verify_result;
321     net::TestCompletionCallback callback;
322     std::unique_ptr<net::CertVerifier::Request> request;
323     int error =
324         VerifyTestServerCert(callback.callback(), &verify_result, &request);
325     ASSERT_EQ(net::ERR_IO_PENDING, error);
326     EXPECT_TRUE(request);
327     error = callback.WaitForResult();
328     EXPECT_EQ(net::OK, error);
329   }
330   EXPECT_TRUE(WasTrustAnchorUsedAndReset());
331 }
332 
333 }  // namespace network
334