cert_verify_proc_chromeos_unittest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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_internal.h"
8#include "crypto/scoped_test_nss_chromeos_user.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
17namespace chromeos {
18
19class 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(db_1_->GetPublicSlot());
45    verify_proc_2_ = new CertVerifyProcChromeOS(db_2_->GetPublicSlot());
46
47    // Load test cert chains from disk.
48    certs_1_ =
49        net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
50                                           "multi-root-chain1.pem",
51                                           net::X509Certificate::FORMAT_AUTO);
52    ASSERT_EQ(4U, certs_1_.size());
53
54    certs_2_ =
55        net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
56                                           "multi-root-chain2.pem",
57                                           net::X509Certificate::FORMAT_AUTO);
58    ASSERT_EQ(4U, certs_2_.size());
59
60    // The chains:
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);
68
69    root_1_.push_back(certs_1_.back());
70    root_2_.push_back(certs_2_.back());
71
72    ASSERT_EQ("D Root CA", root_1_[0]->subject().common_name);
73    ASSERT_EQ("E Root CA", root_2_[0]->subject().common_name);
74  }
75
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) {
81    int flags = 0;
82    net::CertVerifyResult verify_result;
83    int error = verify_proc->Verify(cert,
84                                    "127.0.0.1",
85                                    flags,
86                                    NULL,
87                                    additional_trust_anchors,
88                                    &verify_result);
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);
94    } else {
95      root_subject_name->clear();
96    }
97    return error;
98  }
99
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);
106  }
107
108 protected:
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_;
120};
121
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.
125TEST_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 that roots specified through additional_trust_anchors are trusted for
193// that verification, and that there is not any caching that affects later
194// verifications.
195TEST_F(CertVerifyProcChromeOSTest, TestAdditionalTrustAnchors) {
196  EXPECT_TRUE(verify_proc_default_->SupportsAdditionalTrustAnchors());
197  EXPECT_TRUE(verify_proc_1_->SupportsAdditionalTrustAnchors());
198
199  scoped_refptr<net::X509Certificate> server = certs_1_[0];
200  std::string verify_root;
201  net::CertificateList additional_trust_anchors;
202
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,
208                                             server.get(),
209                                             &verify_root));
210  EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
211            VerifyWithAdditionalTrustAnchors(verify_proc_1_.get(),
212                                             additional_trust_anchors,
213                                             server.get(),
214                                             &verify_root));
215
216  // Use D Root CA as additional trust anchor. Verifications should succeed now.
217  additional_trust_anchors.push_back(root_1_[0]);
218  EXPECT_EQ(net::OK,
219            VerifyWithAdditionalTrustAnchors(verify_proc_default_.get(),
220                                             additional_trust_anchors,
221                                             server.get(),
222                                             &verify_root));
223  EXPECT_EQ("CN=D Root CA", verify_root);
224  EXPECT_EQ(net::OK,
225            VerifyWithAdditionalTrustAnchors(verify_proc_1_.get(),
226                                             additional_trust_anchors,
227                                             server.get(),
228                                             &verify_root));
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(),
234                                             server.get(),
235                                             &verify_root));
236
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,
242                                             server.get(),
243                                             &verify_root));
244  EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
245            VerifyWithAdditionalTrustAnchors(verify_proc_1_.get(),
246                                             additional_trust_anchors,
247                                             server.get(),
248                                             &verify_root));
249
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;
254  EXPECT_TRUE(
255      db_2_->ImportCACerts(roots, net::NSSCertDatabase::TRUSTED_SSL, &failed));
256  EXPECT_EQ(0U, failed.size());
257
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]);
261  EXPECT_EQ(net::OK,
262            VerifyWithAdditionalTrustAnchors(verify_proc_default_.get(),
263                                             additional_trust_anchors,
264                                             server.get(),
265                                             &verify_root));
266  EXPECT_EQ("CN=D Root CA", verify_root);
267  EXPECT_EQ(net::OK,
268            VerifyWithAdditionalTrustAnchors(verify_proc_1_.get(),
269                                             additional_trust_anchors,
270                                             server.get(),
271                                             &verify_root));
272  EXPECT_EQ("CN=D Root CA", verify_root);
273  EXPECT_EQ(net::OK,
274            VerifyWithAdditionalTrustAnchors(verify_proc_2_.get(),
275                                             additional_trust_anchors,
276                                             server.get(),
277                                             &verify_root));
278  EXPECT_EQ("CN=D Root CA", verify_root);
279}
280
281class CertVerifyProcChromeOSOrderingTest
282    : public CertVerifyProcChromeOSTest,
283      public ::testing::WithParamInterface<
284          std::tr1::tuple<bool, int, std::string> > {};
285
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// http://crbug.com/396501
290TEST_P(CertVerifyProcChromeOSOrderingTest, DISABLED_TrustThenVerify) {
291  const ParamType& param = GetParam();
292  const bool verify_first = std::tr1::get<0>(param);
293  const int trust_bitmask = std::tr1::get<1>(param);
294  const std::string test_order = std::tr1::get<2>(param);
295  DVLOG(1) << "verify_first: " << verify_first
296           << " trust_bitmask: " << trust_bitmask
297           << " test_order: " << test_order;
298
299  scoped_refptr<net::X509Certificate> server = certs_1_[0];
300  std::string verify_root;
301
302  if (verify_first) {
303    // Before either of the root certs have been trusted, all verifications
304    // should fail with CERT_AUTHORITY_INVALID.
305    EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
306              Verify(verify_proc_default_.get(), server.get(), &verify_root));
307    EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
308              Verify(verify_proc_1_.get(), server.get(), &verify_root));
309    EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
310              Verify(verify_proc_2_.get(), server.get(), &verify_root));
311  }
312
313  int expected_user1_result = net::ERR_CERT_AUTHORITY_INVALID;
314  int expected_user2_result = net::ERR_CERT_AUTHORITY_INVALID;
315
316  if (trust_bitmask & 1) {
317    expected_user1_result = net::OK;
318    // Import and trust the D root for user 1.
319    net::NSSCertDatabase::ImportCertFailureList failed;
320    EXPECT_TRUE(db_1_->ImportCACerts(
321        root_1_, net::NSSCertDatabase::TRUSTED_SSL, &failed));
322    EXPECT_EQ(0U, failed.size());
323    for (size_t i = 0; i < failed.size(); ++i) {
324      LOG(ERROR) << "import fail " << failed[i].net_error << " for "
325                 << failed[i].certificate->subject().GetDisplayName();
326    }
327  }
328
329  if (trust_bitmask & 2) {
330    expected_user2_result = net::OK;
331    // Import and trust the E root for user 2.
332    net::NSSCertDatabase::ImportCertFailureList failed;
333    EXPECT_TRUE(db_2_->ImportCACerts(
334        root_2_, net::NSSCertDatabase::TRUSTED_SSL, &failed));
335    EXPECT_EQ(0U, failed.size());
336    for (size_t i = 0; i < failed.size(); ++i) {
337      LOG(ERROR) << "import fail " << failed[i].net_error << " for "
338                 << failed[i].certificate->subject().GetDisplayName();
339    }
340  }
341
342  // Repeat the tests twice, they should return the same each time.
343  for (int i = 0; i < 2; ++i) {
344    SCOPED_TRACE(i);
345    for (std::string::const_iterator j = test_order.begin();
346         j != test_order.end();
347         ++j) {
348      switch (*j) {
349        case 'd':
350          // Default verifier should always fail.
351          EXPECT_EQ(
352              net::ERR_CERT_AUTHORITY_INVALID,
353              Verify(verify_proc_default_.get(), server.get(), &verify_root));
354          break;
355        case '1':
356          EXPECT_EQ(expected_user1_result,
357                    Verify(verify_proc_1_.get(), server.get(), &verify_root));
358          if (expected_user1_result == net::OK)
359            EXPECT_EQ("CN=D Root CA", verify_root);
360          break;
361        case '2':
362          EXPECT_EQ(expected_user2_result,
363                    Verify(verify_proc_2_.get(), server.get(), &verify_root));
364          if (expected_user2_result == net::OK)
365            EXPECT_EQ("CN=E Root CA", verify_root);
366          break;
367        default:
368          FAIL();
369      }
370    }
371  }
372}
373
374INSTANTIATE_TEST_CASE_P(
375    Variations,
376    CertVerifyProcChromeOSOrderingTest,
377    ::testing::Combine(
378        ::testing::Bool(),
379        ::testing::Range(0, 1 << 2),
380        ::testing::Values("d12", "d21", "1d2", "12d", "2d1", "21d")));
381
382}  // namespace chromeos
383