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