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.
5 #include "chrome/browser/chromeos/policy/policy_cert_verifier.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/run_loop.h"
13 #include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/test/test_browser_thread_bundle.h"
16 #include "crypto/nss_util_internal.h"
17 #include "crypto/scoped_test_nss_chromeos_user.h"
18 #include "net/base/test_completion_callback.h"
19 #include "net/base/test_data_directory.h"
20 #include "net/cert/cert_trust_anchor_provider.h"
21 #include "net/cert/cert_verify_result.h"
22 #include "net/cert/nss_cert_database_chromeos.h"
23 #include "net/cert/x509_certificate.h"
24 #include "net/log/net_log.h"
25 #include "net/test/cert_test_util.h"
26 #include "testing/gtest/include/gtest/gtest.h"
30 class PolicyCertVerifierTest
: public testing::Test
{
32 PolicyCertVerifierTest()
33 : trust_anchor_used_(false), test_nss_user_("user1") {}
35 ~PolicyCertVerifierTest() override
{}
37 void SetUp() override
{
38 ASSERT_TRUE(test_nss_user_
.constructed_successfully());
39 test_nss_user_
.FinishInit();
41 test_cert_db_
.reset(new net::NSSCertDatabaseChromeOS(
42 crypto::GetPublicSlotForChromeOSUser(test_nss_user_
.username_hash()),
43 crypto::GetPrivateSlotForChromeOSUser(
44 test_nss_user_
.username_hash(),
45 base::Callback
<void(crypto::ScopedPK11Slot
)>())));
46 test_cert_db_
->SetSlowTaskRunnerForTest(base::MessageLoopProxy::current());
48 cert_verifier_
.reset(new PolicyCertVerifier(base::Bind(
49 &PolicyCertVerifierTest::OnTrustAnchorUsed
, base::Unretained(this))));
50 cert_verifier_
->InitializeOnIOThread(new chromeos::CertVerifyProcChromeOS(
51 crypto::GetPublicSlotForChromeOSUser(test_nss_user_
.username_hash())));
53 test_ca_cert_
= LoadCertificate("root_ca_cert.pem", net::CA_CERT
);
54 ASSERT_TRUE(test_ca_cert_
.get());
55 test_server_cert_
= LoadCertificate("ok_cert.pem", net::SERVER_CERT
);
56 ASSERT_TRUE(test_server_cert_
.get());
57 test_ca_cert_list_
.push_back(test_ca_cert_
);
60 void TearDown() override
{
61 // Destroy |cert_verifier_| before destroying the ThreadBundle, otherwise
62 // BrowserThread::CurrentlyOn checks fail.
63 cert_verifier_
.reset();
67 int VerifyTestServerCert(const net::TestCompletionCallback
& test_callback
,
68 net::CertVerifyResult
* verify_result
,
69 net::CertVerifier::RequestHandle
* request_handle
) {
70 return cert_verifier_
->Verify(test_server_cert_
.get(),
75 test_callback
.callback(),
80 bool SupportsAdditionalTrustAnchors() {
81 scoped_refptr
<net::CertVerifyProc
> proc
=
82 net::CertVerifyProc::CreateDefault();
83 return proc
->SupportsAdditionalTrustAnchors();
86 // Returns whether |cert_verifier| signalled usage of one of the additional
87 // trust anchors (i.e. of |test_ca_cert_|) for the first time or since the
88 // last call of this function.
89 bool WasTrustAnchorUsedAndReset() {
90 base::RunLoop().RunUntilIdle();
91 bool result
= trust_anchor_used_
;
92 trust_anchor_used_
= false;
96 // |test_ca_cert_| is the issuer of |test_server_cert_|.
97 scoped_refptr
<net::X509Certificate
> test_ca_cert_
;
98 scoped_refptr
<net::X509Certificate
> test_server_cert_
;
99 net::CertificateList test_ca_cert_list_
;
100 scoped_ptr
<net::NSSCertDatabaseChromeOS
> test_cert_db_
;
101 scoped_ptr
<PolicyCertVerifier
> cert_verifier_
;
104 void OnTrustAnchorUsed() {
105 trust_anchor_used_
= true;
108 scoped_refptr
<net::X509Certificate
> LoadCertificate(const std::string
& name
,
109 net::CertType type
) {
110 scoped_refptr
<net::X509Certificate
> cert
=
111 net::ImportCertFromFile(net::GetTestCertsDirectory(), name
);
113 // No certificate is trusted right after it's loaded.
114 net::NSSCertDatabase::TrustBits trust
=
115 test_cert_db_
->GetCertTrust(cert
.get(), type
);
116 EXPECT_EQ(net::NSSCertDatabase::TRUST_DEFAULT
, trust
);
121 bool trust_anchor_used_
;
122 crypto::ScopedTestNSSChromeOSUser test_nss_user_
;
123 content::TestBrowserThreadBundle thread_bundle_
;
126 TEST_F(PolicyCertVerifierTest
, VerifyUntrustedCert
) {
127 // |test_server_cert_| is untrusted, so Verify() fails.
129 net::CertVerifyResult verify_result
;
130 net::TestCompletionCallback callback
;
131 net::CertVerifier::RequestHandle request_handle
= NULL
;
132 int error
= VerifyTestServerCert(callback
, &verify_result
, &request_handle
);
133 ASSERT_EQ(net::ERR_IO_PENDING
, error
);
134 EXPECT_TRUE(request_handle
);
135 error
= callback
.WaitForResult();
136 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
, error
);
139 // Issuing the same request again hits the cache. This tests the synchronous
142 net::CertVerifyResult verify_result
;
143 net::TestCompletionCallback callback
;
144 net::CertVerifier::RequestHandle request_handle
= NULL
;
145 int error
= VerifyTestServerCert(callback
, &verify_result
, &request_handle
);
146 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
, error
);
149 EXPECT_FALSE(WasTrustAnchorUsedAndReset());
152 TEST_F(PolicyCertVerifierTest
, VerifyTrustedCert
) {
153 // Make the database trust |test_ca_cert_|.
154 net::NSSCertDatabase::ImportCertFailureList failure_list
;
155 ASSERT_TRUE(test_cert_db_
->ImportCACerts(
156 test_ca_cert_list_
, net::NSSCertDatabase::TRUSTED_SSL
, &failure_list
));
157 ASSERT_TRUE(failure_list
.empty());
159 // Verify that it is now trusted.
160 net::NSSCertDatabase::TrustBits trust
=
161 test_cert_db_
->GetCertTrust(test_ca_cert_
.get(), net::CA_CERT
);
162 EXPECT_EQ(net::NSSCertDatabase::TRUSTED_SSL
, trust
);
164 // Verify() successfully verifies |test_server_cert_| after it was imported.
165 net::CertVerifyResult verify_result
;
166 net::TestCompletionCallback callback
;
167 net::CertVerifier::RequestHandle request_handle
= NULL
;
168 int error
= VerifyTestServerCert(callback
, &verify_result
, &request_handle
);
169 ASSERT_EQ(net::ERR_IO_PENDING
, error
);
170 EXPECT_TRUE(request_handle
);
171 error
= callback
.WaitForResult();
172 EXPECT_EQ(net::OK
, error
);
174 // The additional trust anchors were not used, since the certificate is
175 // trusted from the database.
176 EXPECT_FALSE(WasTrustAnchorUsedAndReset());
179 TEST_F(PolicyCertVerifierTest
, VerifyUsingAdditionalTrustAnchor
) {
180 ASSERT_TRUE(SupportsAdditionalTrustAnchors());
182 // |test_server_cert_| is untrusted, so Verify() fails.
184 net::CertVerifyResult verify_result
;
185 net::TestCompletionCallback callback
;
186 net::CertVerifier::RequestHandle request_handle
= NULL
;
187 int error
= VerifyTestServerCert(callback
, &verify_result
, &request_handle
);
188 ASSERT_EQ(net::ERR_IO_PENDING
, error
);
189 EXPECT_TRUE(request_handle
);
190 error
= callback
.WaitForResult();
191 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
, error
);
193 EXPECT_FALSE(WasTrustAnchorUsedAndReset());
195 // Verify() again with the additional trust anchors.
196 cert_verifier_
->SetTrustAnchors(test_ca_cert_list_
);
198 net::CertVerifyResult verify_result
;
199 net::TestCompletionCallback callback
;
200 net::CertVerifier::RequestHandle request_handle
= NULL
;
201 int error
= VerifyTestServerCert(callback
, &verify_result
, &request_handle
);
202 ASSERT_EQ(net::ERR_IO_PENDING
, error
);
203 EXPECT_TRUE(request_handle
);
204 error
= callback
.WaitForResult();
205 EXPECT_EQ(net::OK
, error
);
207 EXPECT_TRUE(WasTrustAnchorUsedAndReset());
209 // Verify() again with the additional trust anchors will hit the cache.
210 cert_verifier_
->SetTrustAnchors(test_ca_cert_list_
);
212 net::CertVerifyResult verify_result
;
213 net::TestCompletionCallback callback
;
214 net::CertVerifier::RequestHandle request_handle
= NULL
;
215 int error
= VerifyTestServerCert(callback
, &verify_result
, &request_handle
);
216 EXPECT_EQ(net::OK
, error
);
218 EXPECT_TRUE(WasTrustAnchorUsedAndReset());
220 // Verifying after removing the trust anchors should now fail.
221 cert_verifier_
->SetTrustAnchors(net::CertificateList());
223 net::CertVerifyResult verify_result
;
224 net::TestCompletionCallback callback
;
225 net::CertVerifier::RequestHandle request_handle
= NULL
;
226 int error
= VerifyTestServerCert(callback
, &verify_result
, &request_handle
);
227 // Note: this hits the cached result from the first Verify() in this test.
228 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
, error
);
230 // The additional trust anchors were reset, thus |cert_verifier_| should not
231 // signal it's usage anymore.
232 EXPECT_FALSE(WasTrustAnchorUsedAndReset());
235 } // namespace policy