Chromium Code Reviews| Index: net/cert/cert_verify_proc_chromeos_unittest.cc |
| diff --git a/net/cert/cert_verify_proc_chromeos_unittest.cc b/net/cert/cert_verify_proc_chromeos_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c34c738e96428383efafb842a680da5f5a172eb4 |
| --- /dev/null |
| +++ b/net/cert/cert_verify_proc_chromeos_unittest.cc |
| @@ -0,0 +1,279 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "net/cert/cert_verify_proc_chromeos.h" |
| + |
| +#include "crypto/nss_util.h" |
| +#include "crypto/nss_util_internal.h" |
| +#include "net/base/net_errors.h" |
| +#include "net/base/test_data_directory.h" |
| +#include "net/cert/cert_verify_proc.h" |
| +#include "net/cert/cert_verify_proc_chromeos.h" |
| +#include "net/cert/cert_verify_result.h" |
| +#include "net/cert/nss_cert_database_chromeos.h" |
| +#include "net/test/cert_test_util.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace net { |
| + |
| +class CertVerifyProcChromeOSTest : public testing::Test { |
| + public: |
| + CertVerifyProcChromeOSTest() : user_1_("user1"), user_2_("user2") {} |
| + |
| + virtual void SetUp() OVERRIDE { |
| + // Initialize nss_util slots. |
| + ASSERT_TRUE(user_1_.constructed_successfully()); |
| + ASSERT_TRUE(user_2_.constructed_successfully()); |
| + user_1_.FinishInit(); |
| + user_2_.FinishInit(); |
| + |
| + // Create NSSCertDatabaseChromeOS for each user. |
| + db_1_.reset(new NSSCertDatabaseChromeOS( |
| + crypto::GetPublicSlotForChromeOSUser(user_1_.username_hash()), |
| + crypto::GetPrivateSlotForChromeOSUser( |
| + user_1_.username_hash(), |
| + base::Callback<void(crypto::ScopedPK11Slot)>()))); |
| + db_2_.reset(new NSSCertDatabaseChromeOS( |
| + crypto::GetPublicSlotForChromeOSUser(user_2_.username_hash()), |
| + crypto::GetPrivateSlotForChromeOSUser( |
| + user_2_.username_hash(), |
| + base::Callback<void(crypto::ScopedPK11Slot)>()))); |
| + |
| + // Create default verifier and for each user. |
| + verify_proc_default_ = CertVerifyProc::CreateDefault(); |
| + verify_proc_1_ = new CertVerifyProcChromeOS( |
| + crypto::GetPublicSlotForChromeOSUser(user_1_.username_hash()), |
| + crypto::GetPrivateSlotForChromeOSUser( |
| + user_1_.username_hash(), |
| + base::Callback<void(crypto::ScopedPK11Slot)>())); |
| + verify_proc_2_ = new CertVerifyProcChromeOS( |
| + crypto::GetPublicSlotForChromeOSUser(user_2_.username_hash()), |
| + crypto::GetPrivateSlotForChromeOSUser( |
| + user_2_.username_hash(), |
| + base::Callback<void(crypto::ScopedPK11Slot)>())); |
| + |
| + // Load test cert chains from disk. |
| + certs_1_ = CreateCertificateListFromFile(GetTestCertsDirectory(), |
| + "foo-chain1.pem", |
| + X509Certificate::FORMAT_AUTO); |
| + ASSERT_EQ(4U, certs_1_.size()); |
| + |
| + certs_2_ = CreateCertificateListFromFile(GetTestCertsDirectory(), |
| + "foo-chain2.pem", |
| + X509Certificate::FORMAT_AUTO); |
| + ASSERT_EQ(4U, certs_2_.size()); |
| + |
| + // The chains: |
| + // 1. A (end-entity) -> B -> C -> D (self-signed root) |
| + // 2. A (end-entity) -> B -> C2 -> E (self-signed root) |
| + ASSERT_TRUE(certs_1_[0]->Equals(certs_2_[0])); |
| + ASSERT_TRUE(certs_1_[1]->Equals(certs_2_[1])); |
| + ASSERT_FALSE(certs_1_[2]->Equals(certs_2_[2])); |
| + ASSERT_EQ("C CA", certs_1_[2]->subject().common_name); |
| + ASSERT_EQ("C CA", certs_2_[2]->subject().common_name); |
| + |
| + root_1_.push_back(certs_1_.back()); |
| + root_2_.push_back(certs_2_.back()); |
| + |
| + ASSERT_EQ("D Root CA", root_1_[0]->subject().common_name); |
| + ASSERT_EQ("E Root CA", root_2_[0]->subject().common_name); |
| + } |
| + |
| + int Verify(CertVerifyProc* verify_proc, |
| + X509Certificate* cert, |
| + std::string* root_subject_name) { |
| + int flags = 0; |
| + CertVerifyResult verify_result; |
| + CertificateList additional_trust_anchors; |
| + int error = verify_proc->Verify(cert, |
| + "127.0.0.1", |
| + flags, |
| + NULL, |
| + additional_trust_anchors, |
| + &verify_result); |
| + if (verify_result.verified_cert.get() && |
| + !verify_result.verified_cert->GetIntermediateCertificates().empty()) { |
| + X509Certificate::OSCertHandle root = |
| + verify_result.verified_cert->GetIntermediateCertificates().back(); |
| + *root_subject_name = root->subjectName; |
| + } else { |
| + *root_subject_name = ""; |
| + } |
| + return error; |
| + } |
| + |
| + protected: |
| + crypto::ScopedTestNSSChromeOSUser user_1_; |
| + crypto::ScopedTestNSSChromeOSUser user_2_; |
| + scoped_ptr<NSSCertDatabaseChromeOS> db_1_; |
| + scoped_ptr<NSSCertDatabaseChromeOS> db_2_; |
| + scoped_refptr<CertVerifyProc> verify_proc_default_; |
| + scoped_refptr<CertVerifyProc> verify_proc_1_; |
| + scoped_refptr<CertVerifyProc> verify_proc_2_; |
| + CertificateList certs_1_; |
| + CertificateList certs_2_; |
| + CertificateList root_1_; |
| + CertificateList root_2_; |
| +}; |
| + |
| +// XXX |
| +TEST_F(CertVerifyProcChromeOSTest, TestChainVerify) { |
| + scoped_refptr<X509Certificate> server = certs_1_[0]; |
| + std::string verify_root; |
| + // Before either of the root certs have been trusted, all verifications should |
| + // fail with CERT_AUTHORITY_INVALID. |
| + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, |
| + Verify(verify_proc_default_.get(), server.get(), &verify_root)); |
| + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, |
| + Verify(verify_proc_1_.get(), server.get(), &verify_root)); |
| + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, |
| + Verify(verify_proc_2_.get(), server.get(), &verify_root)); |
| + |
| + // Import and trust the D root for user 1. |
| + NSSCertDatabase::ImportCertFailureList failed; |
| + EXPECT_TRUE( |
| + db_1_->ImportCACerts(root_1_, NSSCertDatabase::TRUSTED_SSL, &failed)); |
| + EXPECT_EQ(0U, failed.size()); |
| + |
| + // Imported CA certs are not trusted by default verifier. |
| + EXPECT_EQ(ERR_CERT_REVOKED, |
| + Verify(verify_proc_default_.get(), server.get(), &verify_root)); |
| + // User 1 should now verify successfully through the D root. |
| + EXPECT_EQ(OK, Verify(verify_proc_1_.get(), server.get(), &verify_root)); |
| + EXPECT_EQ("CN=D Root CA", verify_root); |
| + // User 2 should still fail. |
| + EXPECT_EQ(ERR_CERT_REVOKED, |
| + Verify(verify_proc_2_.get(), server.get(), &verify_root)); |
| + |
| + // Import and trust the E root for user 2. |
| + failed.clear(); |
| + EXPECT_TRUE( |
| + db_2_->ImportCACerts(root_2_, NSSCertDatabase::TRUSTED_SSL, &failed)); |
| + EXPECT_EQ(0U, failed.size()); |
| + |
| + // Imported CA certs are not trusted by default verifier. |
| + EXPECT_EQ(ERR_CERT_REVOKED, |
|
Ryan Sleevi
2014/01/25 01:50:17
wrong error code?? revoked isnt right, should be u
mattm
2014/01/28 04:36:44
Done.
|
| + Verify(verify_proc_default_.get(), server.get(), &verify_root)); |
| + // User 1 should still verify successfully through the D root. |
| + EXPECT_EQ(OK, Verify(verify_proc_1_.get(), server.get(), &verify_root)); |
| + EXPECT_EQ("CN=D Root CA", verify_root); |
| + // User 2 should now verify successfully through the E root. |
| + EXPECT_EQ(OK, Verify(verify_proc_2_.get(), server.get(), &verify_root)); |
| + EXPECT_EQ("CN=E Root CA", verify_root); |
| + |
| + // Delete D root. |
| + EXPECT_TRUE(db_1_->DeleteCertAndKey(root_1_[0])); |
| + EXPECT_EQ(ERR_CERT_REVOKED, |
| + Verify(verify_proc_default_.get(), server.get(), &verify_root)); |
| + // User 1 should now fail to verify. |
| + EXPECT_EQ(ERR_CERT_REVOKED, |
| + Verify(verify_proc_1_.get(), server.get(), &verify_root)); |
| + // User 2 should still verify successfully through the E root. |
| + EXPECT_EQ(OK, Verify(verify_proc_2_.get(), server.get(), &verify_root)); |
| + EXPECT_EQ("CN=E Root CA", verify_root); |
| + |
| + // Delete E root. |
| + EXPECT_TRUE(db_2_->DeleteCertAndKey(root_2_[0])); |
| + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, |
| + Verify(verify_proc_default_.get(), server.get(), &verify_root)); |
| + // User 1 should still fail to verify. |
| + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, |
| + Verify(verify_proc_1_.get(), server.get(), &verify_root)); |
| + // User 2 should now fail to verify. |
| + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, |
| + Verify(verify_proc_2_.get(), server.get(), &verify_root)); |
| +} |
| + |
| +class CertVerifyProcChromeOSOrderingTest |
| + : public CertVerifyProcChromeOSTest, |
| + public ::testing::WithParamInterface< |
| + std::tr1::tuple<bool, int, std::string> > {}; |
| + |
| +TEST_P(CertVerifyProcChromeOSOrderingTest, TrustThenVerify) { |
| + const ParamType& param = GetParam(); |
| + const bool verify_first = std::tr1::get<0>(param); |
| + const int trust_bitmask = std::tr1::get<1>(param); |
| + const std::string test_order = std::tr1::get<2>(param); |
| + DVLOG(1) << "verify_first: " << verify_first |
| + << " trust_bitmask: " << trust_bitmask |
| + << " test_order: " << test_order; |
| + |
| + scoped_refptr<X509Certificate> server = certs_1_[0]; |
| + std::string verify_root; |
| + |
| + if (verify_first) { |
| + // Before either of the root certs have been trusted, all verifications |
| + // should fail with CERT_AUTHORITY_INVALID. |
| + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, |
| + Verify(verify_proc_default_.get(), server.get(), &verify_root)); |
| + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, |
| + Verify(verify_proc_1_.get(), server.get(), &verify_root)); |
| + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, |
| + Verify(verify_proc_2_.get(), server.get(), &verify_root)); |
| + } |
| + |
| + int expected_fail_value = |
| + trust_bitmask ? ERR_CERT_REVOKED : ERR_CERT_AUTHORITY_INVALID; |
| + int expected_user1_result = expected_fail_value; |
| + int expected_user2_result = expected_fail_value; |
| + |
| + if (trust_bitmask & 1) { |
| + expected_user1_result = OK; |
| + // Import and trust the D root for user 1. |
| + NSSCertDatabase::ImportCertFailureList failed; |
| + EXPECT_TRUE( |
| + db_1_->ImportCACerts(root_1_, NSSCertDatabase::TRUSTED_SSL, &failed)); |
| + EXPECT_EQ(0U, failed.size()); |
| + } |
| + |
| + if (trust_bitmask & 2) { |
| + expected_user2_result = OK; |
| + // Import and trust the E root for user 2. |
| + NSSCertDatabase::ImportCertFailureList failed; |
| + EXPECT_TRUE( |
| + db_2_->ImportCACerts(root_2_, NSSCertDatabase::TRUSTED_SSL, &failed)); |
| + EXPECT_EQ(0U, failed.size()); |
| + } |
| + |
| + // Repeat the tests twice, they should return the same each time. |
| + for (int i = 0; i < 2; ++i) { |
| + SCOPED_TRACE(i); |
| + for (std::string::const_iterator j = test_order.begin(); |
| + j != test_order.end(); |
| + ++j) { |
| + switch (*j) { |
| + case 'd': |
| + // Default verifier should always fail. |
| + EXPECT_EQ( |
| + expected_fail_value, |
| + Verify(verify_proc_default_.get(), server.get(), &verify_root)); |
| + break; |
| + case '1': |
| + EXPECT_EQ(expected_user1_result, |
| + Verify(verify_proc_1_.get(), server.get(), &verify_root)); |
| + if (expected_user1_result == OK) |
| + EXPECT_EQ("CN=D Root CA", verify_root); |
| + break; |
| + case '2': |
| + EXPECT_EQ(expected_user2_result, |
| + Verify(verify_proc_2_.get(), server.get(), &verify_root)); |
| + if (expected_user2_result == OK) |
| + EXPECT_EQ("CN=E Root CA", verify_root); |
| + break; |
| + default: |
| + ASSERT_TRUE(false); |
| + } |
| + } |
| + } |
| +} |
| + |
| +INSTANTIATE_TEST_CASE_P( |
| + Variations, |
| + CertVerifyProcChromeOSOrderingTest, |
| + ::testing::Combine( |
| + ::testing::Bool(), |
| + ::testing::Range(0, 1 << 2), |
| + ::testing::Values("d12", "d21", "1d2", "12d", "2d1", "21d"))); |
| + |
| +} // namespace net |