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/net/cert_verify_proc_chromeos.h"
7 #include "crypto/nss_util.h"
8 #include "crypto/nss_util_internal.h"
9 #include "net/base/net_errors.h"
10 #include "net/base/test_data_directory.h"
11 #include "net/cert/cert_verify_proc.h"
12 #include "net/cert/cert_verify_result.h"
13 #include "net/cert/nss_cert_database_chromeos.h"
14 #include "net/test/cert_test_util.h"
15 #include "testing/gtest/include/gtest/gtest.h"
19 class CertVerifyProcChromeOSTest
: public testing::Test
{
21 CertVerifyProcChromeOSTest() : user_1_("user1"), user_2_("user2") {}
23 virtual void SetUp() OVERRIDE
{
24 // Initialize nss_util slots.
25 ASSERT_TRUE(user_1_
.constructed_successfully());
26 ASSERT_TRUE(user_2_
.constructed_successfully());
30 // Create NSSCertDatabaseChromeOS for each user.
31 db_1_
.reset(new net::NSSCertDatabaseChromeOS(
32 crypto::GetPublicSlotForChromeOSUser(user_1_
.username_hash()),
33 crypto::GetPrivateSlotForChromeOSUser(
34 user_1_
.username_hash(),
35 base::Callback
<void(crypto::ScopedPK11Slot
)>())));
36 db_2_
.reset(new net::NSSCertDatabaseChromeOS(
37 crypto::GetPublicSlotForChromeOSUser(user_2_
.username_hash()),
38 crypto::GetPrivateSlotForChromeOSUser(
39 user_2_
.username_hash(),
40 base::Callback
<void(crypto::ScopedPK11Slot
)>())));
42 // Create default verifier and for each user.
43 verify_proc_default_
= new CertVerifyProcChromeOS();
44 verify_proc_1_
= new CertVerifyProcChromeOS(db_1_
->GetPublicSlot());
45 verify_proc_2_
= new CertVerifyProcChromeOS(db_2_
->GetPublicSlot());
47 // Load test cert chains from disk.
49 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
50 "multi-root-chain1.pem",
51 net::X509Certificate::FORMAT_AUTO
);
52 ASSERT_EQ(4U, certs_1_
.size());
55 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
56 "multi-root-chain2.pem",
57 net::X509Certificate::FORMAT_AUTO
);
58 ASSERT_EQ(4U, certs_2_
.size());
61 // 1. A (end-entity) -> B -> C -> D (self-signed root)
62 // 2. A (end-entity) -> B -> C2 -> E (self-signed root)
63 ASSERT_TRUE(certs_1_
[0]->Equals(certs_2_
[0]));
64 ASSERT_TRUE(certs_1_
[1]->Equals(certs_2_
[1]));
65 ASSERT_FALSE(certs_1_
[2]->Equals(certs_2_
[2]));
66 ASSERT_EQ("C CA", certs_1_
[2]->subject().common_name
);
67 ASSERT_EQ("C CA", certs_2_
[2]->subject().common_name
);
69 root_1_
.push_back(certs_1_
.back());
70 root_2_
.push_back(certs_2_
.back());
72 ASSERT_EQ("D Root CA", root_1_
[0]->subject().common_name
);
73 ASSERT_EQ("E Root CA", root_2_
[0]->subject().common_name
);
76 int VerifyWithAdditionalTrustAnchors(
77 net::CertVerifyProc
* verify_proc
,
78 const net::CertificateList
& additional_trust_anchors
,
79 net::X509Certificate
* cert
,
80 std::string
* root_subject_name
) {
82 net::CertVerifyResult verify_result
;
83 int error
= verify_proc
->Verify(cert
,
87 additional_trust_anchors
,
89 if (verify_result
.verified_cert
.get() &&
90 !verify_result
.verified_cert
->GetIntermediateCertificates().empty()) {
91 net::X509Certificate::OSCertHandle root
=
92 verify_result
.verified_cert
->GetIntermediateCertificates().back();
93 root_subject_name
->assign(root
->subjectName
);
95 root_subject_name
->clear();
100 int Verify(net::CertVerifyProc
* verify_proc
,
101 net::X509Certificate
* cert
,
102 std::string
* root_subject_name
) {
103 net::CertificateList additional_trust_anchors
;
104 return VerifyWithAdditionalTrustAnchors(
105 verify_proc
, additional_trust_anchors
, cert
, root_subject_name
);
109 crypto::ScopedTestNSSChromeOSUser user_1_
;
110 crypto::ScopedTestNSSChromeOSUser user_2_
;
111 scoped_ptr
<net::NSSCertDatabaseChromeOS
> db_1_
;
112 scoped_ptr
<net::NSSCertDatabaseChromeOS
> db_2_
;
113 scoped_refptr
<net::CertVerifyProc
> verify_proc_default_
;
114 scoped_refptr
<net::CertVerifyProc
> verify_proc_1_
;
115 scoped_refptr
<net::CertVerifyProc
> verify_proc_2_
;
116 net::CertificateList certs_1_
;
117 net::CertificateList certs_2_
;
118 net::CertificateList root_1_
;
119 net::CertificateList root_2_
;
122 // Test that the CertVerifyProcChromeOS doesn't trusts roots that are in other
123 // user's slots or that have been deleted, and that verifying done by one user
124 // doesn't affect verifications done by others.
125 TEST_F(CertVerifyProcChromeOSTest
, TestChainVerify
) {
126 scoped_refptr
<net::X509Certificate
> server
= certs_1_
[0];
127 std::string verify_root
;
128 // Before either of the root certs have been trusted, all verifications should
129 // fail with CERT_AUTHORITY_INVALID.
130 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
131 Verify(verify_proc_default_
.get(), server
.get(), &verify_root
));
132 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
133 Verify(verify_proc_1_
.get(), server
.get(), &verify_root
));
134 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
135 Verify(verify_proc_2_
.get(), server
.get(), &verify_root
));
137 // Import and trust the D root for user 1.
138 net::NSSCertDatabase::ImportCertFailureList failed
;
139 EXPECT_TRUE(db_1_
->ImportCACerts(
140 root_1_
, net::NSSCertDatabase::TRUSTED_SSL
, &failed
));
141 EXPECT_EQ(0U, failed
.size());
143 // Imported CA certs are not trusted by default verifier.
144 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
145 Verify(verify_proc_default_
.get(), server
.get(), &verify_root
));
146 // User 1 should now verify successfully through the D root.
147 EXPECT_EQ(net::OK
, Verify(verify_proc_1_
.get(), server
.get(), &verify_root
));
148 EXPECT_EQ("CN=D Root CA", verify_root
);
149 // User 2 should still fail.
150 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
151 Verify(verify_proc_2_
.get(), server
.get(), &verify_root
));
153 // Import and trust the E root for user 2.
155 EXPECT_TRUE(db_2_
->ImportCACerts(
156 root_2_
, net::NSSCertDatabase::TRUSTED_SSL
, &failed
));
157 EXPECT_EQ(0U, failed
.size());
159 // Imported CA certs are not trusted by default verifier.
160 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
161 Verify(verify_proc_default_
.get(), server
.get(), &verify_root
));
162 // User 1 should still verify successfully through the D root.
163 EXPECT_EQ(net::OK
, Verify(verify_proc_1_
.get(), server
.get(), &verify_root
));
164 EXPECT_EQ("CN=D Root CA", verify_root
);
165 // User 2 should now verify successfully through the E root.
166 EXPECT_EQ(net::OK
, Verify(verify_proc_2_
.get(), server
.get(), &verify_root
));
167 EXPECT_EQ("CN=E Root CA", verify_root
);
170 EXPECT_TRUE(db_1_
->DeleteCertAndKey(root_1_
[0]));
171 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
172 Verify(verify_proc_default_
.get(), server
.get(), &verify_root
));
173 // User 1 should now fail to verify.
174 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
175 Verify(verify_proc_1_
.get(), server
.get(), &verify_root
));
176 // User 2 should still verify successfully through the E root.
177 EXPECT_EQ(net::OK
, Verify(verify_proc_2_
.get(), server
.get(), &verify_root
));
178 EXPECT_EQ("CN=E Root CA", verify_root
);
181 EXPECT_TRUE(db_2_
->DeleteCertAndKey(root_2_
[0]));
182 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
183 Verify(verify_proc_default_
.get(), server
.get(), &verify_root
));
184 // User 1 should still fail to verify.
185 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
186 Verify(verify_proc_1_
.get(), server
.get(), &verify_root
));
187 // User 2 should now fail to verify.
188 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
189 Verify(verify_proc_2_
.get(), server
.get(), &verify_root
));
192 // Test that roots specified through additional_trust_anchors are trusted for
193 // that verification, and that there is not any caching that affects later
195 TEST_F(CertVerifyProcChromeOSTest
, TestAdditionalTrustAnchors
) {
196 EXPECT_TRUE(verify_proc_default_
->SupportsAdditionalTrustAnchors());
197 EXPECT_TRUE(verify_proc_1_
->SupportsAdditionalTrustAnchors());
199 scoped_refptr
<net::X509Certificate
> server
= certs_1_
[0];
200 std::string verify_root
;
201 net::CertificateList additional_trust_anchors
;
203 // Before either of the root certs have been trusted, all verifications should
204 // fail with CERT_AUTHORITY_INVALID.
205 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
206 VerifyWithAdditionalTrustAnchors(verify_proc_default_
.get(),
207 additional_trust_anchors
,
210 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
211 VerifyWithAdditionalTrustAnchors(verify_proc_1_
.get(),
212 additional_trust_anchors
,
216 // Use D Root CA as additional trust anchor. Verifications should succeed now.
217 additional_trust_anchors
.push_back(root_1_
[0]);
219 VerifyWithAdditionalTrustAnchors(verify_proc_default_
.get(),
220 additional_trust_anchors
,
223 EXPECT_EQ("CN=D Root CA", verify_root
);
225 VerifyWithAdditionalTrustAnchors(verify_proc_1_
.get(),
226 additional_trust_anchors
,
229 EXPECT_EQ("CN=D Root CA", verify_root
);
230 // User 2 should still fail.
231 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
232 VerifyWithAdditionalTrustAnchors(verify_proc_2_
.get(),
233 net::CertificateList(),
237 // Without additional trust anchors, verification should fail again.
238 additional_trust_anchors
.clear();
239 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
240 VerifyWithAdditionalTrustAnchors(verify_proc_default_
.get(),
241 additional_trust_anchors
,
244 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
245 VerifyWithAdditionalTrustAnchors(verify_proc_1_
.get(),
246 additional_trust_anchors
,
250 // Import and trust the D Root CA for user 2.
251 net::CertificateList roots
;
252 roots
.push_back(root_1_
[0]);
253 net::NSSCertDatabase::ImportCertFailureList failed
;
255 db_2_
->ImportCACerts(roots
, net::NSSCertDatabase::TRUSTED_SSL
, &failed
));
256 EXPECT_EQ(0U, failed
.size());
258 // Use D Root CA as additional trust anchor. Verifications should still
259 // succeed even if the cert is trusted by a different profile.
260 additional_trust_anchors
.push_back(root_1_
[0]);
262 VerifyWithAdditionalTrustAnchors(verify_proc_default_
.get(),
263 additional_trust_anchors
,
266 EXPECT_EQ("CN=D Root CA", verify_root
);
268 VerifyWithAdditionalTrustAnchors(verify_proc_1_
.get(),
269 additional_trust_anchors
,
272 EXPECT_EQ("CN=D Root CA", verify_root
);
274 VerifyWithAdditionalTrustAnchors(verify_proc_2_
.get(),
275 additional_trust_anchors
,
278 EXPECT_EQ("CN=D Root CA", verify_root
);
281 class CertVerifyProcChromeOSOrderingTest
282 : public CertVerifyProcChromeOSTest
,
283 public ::testing::WithParamInterface
<
284 std::tr1::tuple
<bool, int, std::string
> > {};
286 // Test a variety of different combinations of (maybe) verifying / (maybe)
287 // importing / verifying again, to try to find any cases where caching might
288 // affect the results.
289 TEST_P(CertVerifyProcChromeOSOrderingTest
, TrustThenVerify
) {
290 const ParamType
& param
= GetParam();
291 const bool verify_first
= std::tr1::get
<0>(param
);
292 const int trust_bitmask
= std::tr1::get
<1>(param
);
293 const std::string test_order
= std::tr1::get
<2>(param
);
294 DVLOG(1) << "verify_first: " << verify_first
295 << " trust_bitmask: " << trust_bitmask
296 << " test_order: " << test_order
;
298 scoped_refptr
<net::X509Certificate
> server
= certs_1_
[0];
299 std::string verify_root
;
302 // Before either of the root certs have been trusted, all verifications
303 // should fail with CERT_AUTHORITY_INVALID.
304 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
305 Verify(verify_proc_default_
.get(), server
.get(), &verify_root
));
306 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
307 Verify(verify_proc_1_
.get(), server
.get(), &verify_root
));
308 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID
,
309 Verify(verify_proc_2_
.get(), server
.get(), &verify_root
));
312 int expected_user1_result
= net::ERR_CERT_AUTHORITY_INVALID
;
313 int expected_user2_result
= net::ERR_CERT_AUTHORITY_INVALID
;
315 if (trust_bitmask
& 1) {
316 expected_user1_result
= net::OK
;
317 // Import and trust the D root for user 1.
318 net::NSSCertDatabase::ImportCertFailureList failed
;
319 EXPECT_TRUE(db_1_
->ImportCACerts(
320 root_1_
, net::NSSCertDatabase::TRUSTED_SSL
, &failed
));
321 EXPECT_EQ(0U, failed
.size());
322 for (size_t i
= 0; i
< failed
.size(); ++i
) {
323 LOG(ERROR
) << "import fail " << failed
[i
].net_error
<< " for "
324 << failed
[i
].certificate
->subject().GetDisplayName();
328 if (trust_bitmask
& 2) {
329 expected_user2_result
= net::OK
;
330 // Import and trust the E root for user 2.
331 net::NSSCertDatabase::ImportCertFailureList failed
;
332 EXPECT_TRUE(db_2_
->ImportCACerts(
333 root_2_
, net::NSSCertDatabase::TRUSTED_SSL
, &failed
));
334 EXPECT_EQ(0U, failed
.size());
335 for (size_t i
= 0; i
< failed
.size(); ++i
) {
336 LOG(ERROR
) << "import fail " << failed
[i
].net_error
<< " for "
337 << failed
[i
].certificate
->subject().GetDisplayName();
341 // Repeat the tests twice, they should return the same each time.
342 for (int i
= 0; i
< 2; ++i
) {
344 for (std::string::const_iterator j
= test_order
.begin();
345 j
!= test_order
.end();
349 // Default verifier should always fail.
351 net::ERR_CERT_AUTHORITY_INVALID
,
352 Verify(verify_proc_default_
.get(), server
.get(), &verify_root
));
355 EXPECT_EQ(expected_user1_result
,
356 Verify(verify_proc_1_
.get(), server
.get(), &verify_root
));
357 if (expected_user1_result
== net::OK
)
358 EXPECT_EQ("CN=D Root CA", verify_root
);
361 EXPECT_EQ(expected_user2_result
,
362 Verify(verify_proc_2_
.get(), server
.get(), &verify_root
));
363 if (expected_user2_result
== net::OK
)
364 EXPECT_EQ("CN=E Root CA", verify_root
);
373 INSTANTIATE_TEST_CASE_P(
375 CertVerifyProcChromeOSOrderingTest
,
378 ::testing::Range(0, 1 << 2),
379 ::testing::Values("d12", "d21", "1d2", "12d", "2d1", "21d")));
381 } // namespace chromeos