OLD | NEW |
---|---|
(Empty) | |
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 "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h" | |
6 | |
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" | |
16 | |
17 namespace chromeos { | |
18 | |
19 class CertVerifyProcChromeOSTest : public testing::Test { | |
20 public: | |
21 CertVerifyProcChromeOSTest() : user_1_("user1"), user_2_("user2") {} | |
22 | |
23 virtual void SetUp() OVERRIDE { | |
24 // Initialize nss_util slots. | |
25 ASSERT_TRUE(user_1_.constructed_successfully()); | |
26 ASSERT_TRUE(user_2_.constructed_successfully()); | |
27 user_1_.FinishInit(); | |
28 user_2_.FinishInit(); | |
29 | |
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)>()))); | |
41 | |
42 // Create default verifier and for each user. | |
43 verify_proc_default_ = new CertVerifyProcChromeOS(); | |
44 verify_proc_1_ = new CertVerifyProcChromeOS( | |
45 crypto::GetPublicSlotForChromeOSUser(user_1_.username_hash())); | |
46 verify_proc_2_ = new CertVerifyProcChromeOS( | |
47 crypto::GetPublicSlotForChromeOSUser(user_2_.username_hash())); | |
Ryan Sleevi
2014/01/30 05:27:40
cache public slots as part of init? (Note lines 37
mattm
2014/02/04 05:31:21
That ended up being messier looking, but there is
| |
48 | |
49 // Load test cert chains from disk. | |
50 certs_1_ = | |
51 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(), | |
52 "foo-chain1.pem", | |
53 net::X509Certificate::FORMAT_AUTO); | |
54 ASSERT_EQ(4U, certs_1_.size()); | |
55 | |
56 certs_2_ = | |
57 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(), | |
58 "foo-chain2.pem", | |
59 net::X509Certificate::FORMAT_AUTO); | |
60 ASSERT_EQ(4U, certs_2_.size()); | |
61 | |
62 // The chains: | |
63 // 1. A (end-entity) -> B -> C -> D (self-signed root) | |
64 // 2. A (end-entity) -> B -> C2 -> E (self-signed root) | |
65 ASSERT_TRUE(certs_1_[0]->Equals(certs_2_[0])); | |
66 ASSERT_TRUE(certs_1_[1]->Equals(certs_2_[1])); | |
67 ASSERT_FALSE(certs_1_[2]->Equals(certs_2_[2])); | |
68 ASSERT_EQ("C CA", certs_1_[2]->subject().common_name); | |
69 ASSERT_EQ("C CA", certs_2_[2]->subject().common_name); | |
70 | |
71 root_1_.push_back(certs_1_.back()); | |
72 root_2_.push_back(certs_2_.back()); | |
73 | |
74 ASSERT_EQ("D Root CA", root_1_[0]->subject().common_name); | |
75 ASSERT_EQ("E Root CA", root_2_[0]->subject().common_name); | |
76 } | |
77 | |
78 int VerifyWithAdditionalTrustAnchors( | |
79 net::CertVerifyProc* verify_proc, | |
80 const net::CertificateList& additional_trust_anchors, | |
81 net::X509Certificate* cert, | |
82 std::string* root_subject_name) { | |
83 int flags = 0; | |
84 net::CertVerifyResult verify_result; | |
85 int error = verify_proc->Verify(cert, | |
86 "127.0.0.1", | |
87 flags, | |
88 NULL, | |
89 additional_trust_anchors, | |
90 &verify_result); | |
91 if (verify_result.verified_cert.get() && | |
92 !verify_result.verified_cert->GetIntermediateCertificates().empty()) { | |
93 net::X509Certificate::OSCertHandle root = | |
94 verify_result.verified_cert->GetIntermediateCertificates().back(); | |
95 *root_subject_name = root->subjectName; | |
Ryan Sleevi
2014/01/30 05:27:40
root_subject_name->assign() ?
mattm
2014/02/04 05:31:21
Done.
| |
96 } else { | |
97 *root_subject_name = ""; | |
Ryan Sleevi
2014/01/30 05:27:40
root_subject_name->clear()
mattm
2014/02/04 05:31:21
Done.
| |
98 } | |
99 return error; | |
100 } | |
101 | |
102 int Verify(net::CertVerifyProc* verify_proc, | |
103 net::X509Certificate* cert, | |
104 std::string* root_subject_name) { | |
105 net::CertificateList additional_trust_anchors; | |
106 return VerifyWithAdditionalTrustAnchors( | |
107 verify_proc, additional_trust_anchors, cert, root_subject_name); | |
108 } | |
109 | |
110 protected: | |
111 crypto::ScopedTestNSSChromeOSUser user_1_; | |
112 crypto::ScopedTestNSSChromeOSUser user_2_; | |
113 scoped_ptr<net::NSSCertDatabaseChromeOS> db_1_; | |
114 scoped_ptr<net::NSSCertDatabaseChromeOS> db_2_; | |
115 scoped_refptr<net::CertVerifyProc> verify_proc_default_; | |
116 scoped_refptr<net::CertVerifyProc> verify_proc_1_; | |
117 scoped_refptr<net::CertVerifyProc> verify_proc_2_; | |
118 net::CertificateList certs_1_; | |
119 net::CertificateList certs_2_; | |
120 net::CertificateList root_1_; | |
121 net::CertificateList root_2_; | |
122 }; | |
123 | |
124 // XXX | |
Ryan Sleevi
2014/01/30 05:27:40
XXX - Document :)
mattm
2014/02/04 05:31:21
Done.
| |
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)); | |
136 | |
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()); | |
142 | |
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)); | |
152 | |
153 // Import and trust the E root for user 2. | |
154 failed.clear(); | |
155 EXPECT_TRUE(db_2_->ImportCACerts( | |
156 root_2_, net::NSSCertDatabase::TRUSTED_SSL, &failed)); | |
157 EXPECT_EQ(0U, failed.size()); | |
158 | |
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); | |
168 | |
169 // Delete D 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); | |
179 | |
180 // Delete E 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)); | |
190 } | |
191 | |
192 TEST_F(CertVerifyProcChromeOSTest, TestAdditionalTrustAnchors) { | |
Ryan Sleevi
2014/01/30 05:27:40
Document?
mattm
2014/02/04 05:31:21
Done.
| |
193 EXPECT_TRUE(verify_proc_default_->SupportsAdditionalTrustAnchors()); | |
194 EXPECT_TRUE(verify_proc_1_->SupportsAdditionalTrustAnchors()); | |
195 | |
196 scoped_refptr<net::X509Certificate> server = certs_1_[0]; | |
197 std::string verify_root; | |
198 net::CertificateList additional_trust_anchors; | |
199 // Before either of the root certs have been trusted, all verifications should | |
200 // fail with CERT_AUTHORITY_INVALID. | |
201 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, | |
202 VerifyWithAdditionalTrustAnchors(verify_proc_default_.get(), | |
203 additional_trust_anchors, | |
204 server.get(), | |
205 &verify_root)); | |
206 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, | |
207 VerifyWithAdditionalTrustAnchors(verify_proc_1_.get(), | |
208 additional_trust_anchors, | |
209 server.get(), | |
210 &verify_root)); | |
211 | |
212 // Use B CA as additional trust anchor. Verifications should succeed now. | |
213 // XXX why doesn't this work with D Root CA? | |
Ryan Sleevi
2014/01/30 05:27:40
Yes. Why doesn't it? :)
mattm
2014/02/04 05:31:21
Done.
| |
214 additional_trust_anchors.push_back(certs_1_[1]); | |
215 EXPECT_EQ(net::OK, | |
216 VerifyWithAdditionalTrustAnchors(verify_proc_default_.get(), | |
217 additional_trust_anchors, | |
218 server.get(), | |
219 &verify_root)); | |
220 EXPECT_EQ("CN=B CA", verify_root); | |
221 EXPECT_EQ(net::OK, | |
222 VerifyWithAdditionalTrustAnchors(verify_proc_1_.get(), | |
223 additional_trust_anchors, | |
224 server.get(), | |
225 &verify_root)); | |
226 EXPECT_EQ("CN=B CA", verify_root); | |
Ryan Sleevi
2014/01/30 05:27:40
Test that User 2 is *not* succeeding (when an empt
mattm
2014/02/04 05:31:21
Done.
| |
227 | |
228 // Without additional trust anchors, verification should fail again. | |
229 additional_trust_anchors.clear(); | |
230 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, | |
231 VerifyWithAdditionalTrustAnchors(verify_proc_default_.get(), | |
232 additional_trust_anchors, | |
233 server.get(), | |
234 &verify_root)); | |
235 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, | |
236 VerifyWithAdditionalTrustAnchors(verify_proc_1_.get(), | |
237 additional_trust_anchors, | |
238 server.get(), | |
239 &verify_root)); | |
240 | |
241 // Import and trust the B CA for user 2. | |
242 net::CertificateList roots; | |
243 roots.push_back(certs_1_[1]); | |
244 net::NSSCertDatabase::ImportCertFailureList failed; | |
245 EXPECT_TRUE( | |
246 db_2_->ImportCACerts(roots, net::NSSCertDatabase::TRUSTED_SSL, &failed)); | |
247 EXPECT_EQ(0U, failed.size()); | |
248 | |
249 // Use B CA as additional trust anchor. Verifications should still | |
250 // succeed even if the cert is trusted by a different profile. | |
251 additional_trust_anchors.push_back(certs_1_[1]); | |
252 EXPECT_EQ(net::OK, | |
253 VerifyWithAdditionalTrustAnchors(verify_proc_default_.get(), | |
254 additional_trust_anchors, | |
255 server.get(), | |
256 &verify_root)); | |
257 EXPECT_EQ("CN=B CA", verify_root); | |
258 EXPECT_EQ(net::OK, | |
259 VerifyWithAdditionalTrustAnchors(verify_proc_1_.get(), | |
260 additional_trust_anchors, | |
261 server.get(), | |
262 &verify_root)); | |
263 EXPECT_EQ("CN=B CA", verify_root); | |
264 EXPECT_EQ(net::OK, | |
265 VerifyWithAdditionalTrustAnchors(verify_proc_2_.get(), | |
266 additional_trust_anchors, | |
267 server.get(), | |
268 &verify_root)); | |
269 EXPECT_EQ("CN=B CA", verify_root); | |
270 } | |
271 | |
272 class CertVerifyProcChromeOSOrderingTest | |
273 : public CertVerifyProcChromeOSTest, | |
274 public ::testing::WithParamInterface< | |
275 std::tr1::tuple<bool, int, std::string> > {}; | |
276 | |
277 TEST_P(CertVerifyProcChromeOSOrderingTest, TrustThenVerify) { | |
278 const ParamType& param = GetParam(); | |
279 const bool verify_first = std::tr1::get<0>(param); | |
280 const int trust_bitmask = std::tr1::get<1>(param); | |
281 const std::string test_order = std::tr1::get<2>(param); | |
282 DVLOG(1) << "verify_first: " << verify_first | |
283 << " trust_bitmask: " << trust_bitmask | |
284 << " test_order: " << test_order; | |
285 | |
286 scoped_refptr<net::X509Certificate> server = certs_1_[0]; | |
287 std::string verify_root; | |
288 | |
289 if (verify_first) { | |
290 // Before either of the root certs have been trusted, all verifications | |
291 // should fail with CERT_AUTHORITY_INVALID. | |
292 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, | |
293 Verify(verify_proc_default_.get(), server.get(), &verify_root)); | |
294 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, | |
295 Verify(verify_proc_1_.get(), server.get(), &verify_root)); | |
296 EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, | |
297 Verify(verify_proc_2_.get(), server.get(), &verify_root)); | |
298 } | |
299 | |
300 int expected_user1_result = net::ERR_CERT_AUTHORITY_INVALID; | |
301 int expected_user2_result = net::ERR_CERT_AUTHORITY_INVALID; | |
302 | |
303 if (trust_bitmask & 1) { | |
304 expected_user1_result = net::OK; | |
305 // Import and trust the D root for user 1. | |
306 net::NSSCertDatabase::ImportCertFailureList failed; | |
307 EXPECT_TRUE(db_1_->ImportCACerts( | |
308 root_1_, net::NSSCertDatabase::TRUSTED_SSL, &failed)); | |
309 EXPECT_EQ(0U, failed.size()); | |
310 } | |
311 | |
312 if (trust_bitmask & 2) { | |
313 expected_user2_result = net::OK; | |
314 // Import and trust the E root for user 2. | |
315 net::NSSCertDatabase::ImportCertFailureList failed; | |
316 EXPECT_TRUE(db_2_->ImportCACerts( | |
317 root_2_, net::NSSCertDatabase::TRUSTED_SSL, &failed)); | |
318 EXPECT_EQ(0U, failed.size()); | |
319 } | |
320 | |
321 // Repeat the tests twice, they should return the same each time. | |
322 for (int i = 0; i < 2; ++i) { | |
323 SCOPED_TRACE(i); | |
324 for (std::string::const_iterator j = test_order.begin(); | |
325 j != test_order.end(); | |
326 ++j) { | |
327 switch (*j) { | |
328 case 'd': | |
329 // Default verifier should always fail. | |
330 EXPECT_EQ( | |
331 net::ERR_CERT_AUTHORITY_INVALID, | |
332 Verify(verify_proc_default_.get(), server.get(), &verify_root)); | |
333 break; | |
334 case '1': | |
335 EXPECT_EQ(expected_user1_result, | |
336 Verify(verify_proc_1_.get(), server.get(), &verify_root)); | |
337 if (expected_user1_result == net::OK) | |
338 EXPECT_EQ("CN=D Root CA", verify_root); | |
339 break; | |
340 case '2': | |
341 EXPECT_EQ(expected_user2_result, | |
342 Verify(verify_proc_2_.get(), server.get(), &verify_root)); | |
343 if (expected_user2_result == net::OK) | |
344 EXPECT_EQ("CN=E Root CA", verify_root); | |
345 break; | |
346 default: | |
347 ASSERT_TRUE(false); | |
Ryan Sleevi
2014/01/30 05:27:40
s/ASSERT_TRUE(false)/FAIL()/ (or GTEST_FAIL if nee
mattm
2014/02/04 05:31:21
Done.
| |
348 } | |
349 } | |
350 } | |
351 } | |
352 | |
353 INSTANTIATE_TEST_CASE_P( | |
354 Variations, | |
355 CertVerifyProcChromeOSOrderingTest, | |
356 ::testing::Combine( | |
357 ::testing::Bool(), | |
358 ::testing::Range(0, 1 << 2), | |
359 ::testing::Values("d12", "d21", "1d2", "12d", "2d1", "21d"))); | |
360 | |
361 } // namespace chromeos | |
OLD | NEW |