Home | History | Annotate | Download | only in net
      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(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.
    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 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.
    195 TEST_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 
    281 class 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 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;
    297 
    298   scoped_refptr<net::X509Certificate> server = certs_1_[0];
    299   std::string verify_root;
    300 
    301   if (verify_first) {
    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));
    310   }
    311 
    312   int expected_user1_result = net::ERR_CERT_AUTHORITY_INVALID;
    313   int expected_user2_result = net::ERR_CERT_AUTHORITY_INVALID;
    314 
    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();
    325     }
    326   }
    327 
    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();
    338     }
    339   }
    340 
    341   // Repeat the tests twice, they should return the same each time.
    342   for (int i = 0; i < 2; ++i) {
    343     SCOPED_TRACE(i);
    344     for (std::string::const_iterator j = test_order.begin();
    345          j != test_order.end();
    346          ++j) {
    347       switch (*j) {
    348         case 'd':
    349           // Default verifier should always fail.
    350           EXPECT_EQ(
    351               net::ERR_CERT_AUTHORITY_INVALID,
    352               Verify(verify_proc_default_.get(), server.get(), &verify_root));
    353           break;
    354         case '1':
    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);
    359           break;
    360         case '2':
    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);
    365           break;
    366         default:
    367           FAIL();
    368       }
    369     }
    370   }
    371 }
    372 
    373 INSTANTIATE_TEST_CASE_P(
    374     Variations,
    375     CertVerifyProcChromeOSOrderingTest,
    376     ::testing::Combine(
    377         ::testing::Bool(),
    378         ::testing::Range(0, 1 << 2),
    379         ::testing::Values("d12", "d21", "1d2", "12d", "2d1", "21d")));
    380 
    381 }  // namespace chromeos
    382