// Copyright 2013 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/cert/test_root_certs.h" #include "base/files/file_path.h" #include "build/build_config.h" #include "net/base/features.h" #include "net/base/net_errors.h" #include "net/cert/cert_net_fetcher.h" #include "net/cert/cert_status_flags.h" #include "net/cert/cert_verify_proc.h" #include "net/cert/cert_verify_result.h" #include "net/cert/crl_set.h" #include "net/cert/do_nothing_ct_verifier.h" #include "net/cert/x509_certificate.h" #include "net/log/net_log_with_source.h" #include "net/net_buildflags.h" #include "net/test/cert_builder.h" #include "net/test/cert_test_util.h" #include "net/test/gtest_util.h" #include "net/test/test_data_directory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using net::test::IsOk; namespace net { namespace { // The local test root certificate. const char kRootCertificateFile[] = "root_ca_cert.pem"; // A certificate issued by the local test root for 127.0.0.1. const char kGoodCertificateFile[] = "ok_cert.pem"; } // namespace class TestRootCertsTest : public testing::TestWithParam { public: scoped_refptr CreateCertVerifyProc() { #if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL) // If CCV/CRS is optional, test with and without CCV/CRS. if (use_chrome_cert_validator()) { return CertVerifyProc::CreateBuiltinWithChromeRootStore( /*cert_net_fetcher=*/nullptr, CRLSet::BuiltinCRLSet().get(), std::make_unique(), base::MakeRefCounted(), /*root_store_data=*/nullptr, /*instance_params=*/{}); } else { return CertVerifyProc::CreateSystemVerifyProc( /*cert_net_fetcher=*/nullptr, CRLSet::BuiltinCRLSet().get()); } #elif BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) return CertVerifyProc::CreateBuiltinWithChromeRootStore( /*cert_net_fetcher=*/nullptr, CRLSet::BuiltinCRLSet().get(), std::make_unique(), base::MakeRefCounted(), /*root_store_data=*/nullptr, /*instance_params=*/{}); #elif BUILDFLAG(IS_FUCHSIA) return CertVerifyProc::CreateBuiltinVerifyProc( /*cert_net_fetcher=*/nullptr, CRLSet::BuiltinCRLSet().get(), std::make_unique(), base::MakeRefCounted(), /*instance_params=*/{}); #else return CertVerifyProc::CreateSystemVerifyProc(/*cert_net_fetcher=*/nullptr, CRLSet::BuiltinCRLSet().get()); #endif } // Whether we use Chrome Cert Validator or not. Only relevant for platforms // where CHROME_ROOT_STORE_OPTIONAL is set; on other platforms both test // params will run the same test. bool use_chrome_cert_validator() { return GetParam(); } }; // Test basic functionality when adding from an existing X509Certificate. TEST_P(TestRootCertsTest, AddFromPointer) { scoped_refptr root_cert = ImportCertFromFile(GetTestCertsDirectory(), kRootCertificateFile); ASSERT_NE(static_cast(nullptr), root_cert.get()); TestRootCerts* test_roots = TestRootCerts::GetInstance(); ASSERT_NE(static_cast(nullptr), test_roots); EXPECT_TRUE(test_roots->IsEmpty()); { ScopedTestRoot scoped_root(root_cert); EXPECT_FALSE(test_roots->IsEmpty()); } EXPECT_TRUE(test_roots->IsEmpty()); } // Test that TestRootCerts actually adds the appropriate trust status flags // when requested, and that the trusted status is cleared once the root is // removed the TestRootCerts. This test acts as a canary/sanity check for // the results of the rest of net_unittests, ensuring that the trust status // is properly being set and cleared. TEST_P(TestRootCertsTest, OverrideTrust) { TestRootCerts* test_roots = TestRootCerts::GetInstance(); ASSERT_NE(static_cast(nullptr), test_roots); EXPECT_TRUE(test_roots->IsEmpty()); scoped_refptr test_cert = ImportCertFromFile(GetTestCertsDirectory(), kGoodCertificateFile); ASSERT_NE(static_cast(nullptr), test_cert.get()); // Test that the good certificate fails verification, because the root // certificate should not yet be trusted. int flags = 0; CertVerifyResult bad_verify_result; scoped_refptr verify_proc(CreateCertVerifyProc()); int bad_status = verify_proc->Verify(test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, &bad_verify_result, NetLogWithSource()); EXPECT_NE(OK, bad_status); EXPECT_NE(0u, bad_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID); EXPECT_FALSE(bad_verify_result.is_issued_by_known_root); // Add the root certificate and mark it as trusted. scoped_refptr root_cert = ImportCertFromFile(GetTestCertsDirectory(), kRootCertificateFile); ASSERT_TRUE(root_cert); ScopedTestRoot scoped_root(root_cert); EXPECT_FALSE(test_roots->IsEmpty()); // Test that the certificate verification now succeeds, because the // TestRootCerts is successfully imbuing trust. CertVerifyResult good_verify_result; int good_status = verify_proc->Verify( test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, &good_verify_result, NetLogWithSource()); EXPECT_THAT(good_status, IsOk()); EXPECT_EQ(0u, good_verify_result.cert_status); EXPECT_FALSE(good_verify_result.is_issued_by_known_root); test_roots->Clear(); EXPECT_TRUE(test_roots->IsEmpty()); // Ensure that when the TestRootCerts is cleared, the trust settings // revert to their original state, and don't linger. If trust status // lingers, it will likely break other tests in net_unittests. CertVerifyResult restored_verify_result; int restored_status = verify_proc->Verify( test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, &restored_verify_result, NetLogWithSource()); EXPECT_NE(OK, restored_status); EXPECT_NE(0u, restored_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID); EXPECT_EQ(bad_status, restored_status); EXPECT_EQ(bad_verify_result.cert_status, restored_verify_result.cert_status); EXPECT_FALSE(restored_verify_result.is_issued_by_known_root); } TEST_P(TestRootCertsTest, OverrideKnownRoot) { TestRootCerts* test_roots = TestRootCerts::GetInstance(); ASSERT_NE(static_cast(nullptr), test_roots); EXPECT_TRUE(test_roots->IsEmpty()); // Use a runtime generated certificate chain so that the cert lifetime is not // too long, and so that it will have an allowable hostname for a publicly // trusted cert. auto [leaf, root] = net::CertBuilder::CreateSimpleChain2(); // Add the root certificate and mark it as trusted and as a known root. ScopedTestRoot scoped_root(root->GetX509Certificate()); ScopedTestKnownRoot scoped_known_root(root->GetX509Certificate().get()); EXPECT_FALSE(test_roots->IsEmpty()); // Test that the certificate verification sets the `is_issued_by_known_root` // flag. CertVerifyResult good_verify_result; scoped_refptr verify_proc(CreateCertVerifyProc()); int flags = 0; int good_status = verify_proc->Verify(leaf->GetX509Certificate().get(), "www.example.com", /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, &good_verify_result, NetLogWithSource()); EXPECT_THAT(good_status, IsOk()); EXPECT_EQ(0u, good_verify_result.cert_status); EXPECT_TRUE(good_verify_result.is_issued_by_known_root); test_roots->Clear(); EXPECT_TRUE(test_roots->IsEmpty()); // Ensure that when the TestRootCerts is cleared, the test known root status // revert to their original state, and don't linger. If known root status // lingers, it will likely break other tests in net_unittests. // Trust the root again so that the `is_issued_by_known_root` value will be // calculated, and ensure that it is false now. ScopedTestRoot scoped_root2(root->GetX509Certificate()); CertVerifyResult restored_verify_result; int restored_status = verify_proc->Verify(leaf->GetX509Certificate().get(), "www.example.com", /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, &restored_verify_result, NetLogWithSource()); EXPECT_THAT(restored_status, IsOk()); EXPECT_EQ(0u, restored_verify_result.cert_status); EXPECT_FALSE(restored_verify_result.is_issued_by_known_root); } TEST_P(TestRootCertsTest, Moveable) { TestRootCerts* test_roots = TestRootCerts::GetInstance(); ASSERT_NE(static_cast(nullptr), test_roots); EXPECT_TRUE(test_roots->IsEmpty()); scoped_refptr test_cert = ImportCertFromFile(GetTestCertsDirectory(), kGoodCertificateFile); ASSERT_NE(static_cast(nullptr), test_cert.get()); int flags = 0; CertVerifyResult bad_verify_result; int bad_status; scoped_refptr verify_proc(CreateCertVerifyProc()); { // Empty ScopedTestRoot at outer scope has no effect. ScopedTestRoot scoped_root_outer; EXPECT_TRUE(test_roots->IsEmpty()); // Test that the good certificate fails verification, because the root // certificate should not yet be trusted. bad_status = verify_proc->Verify(test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, &bad_verify_result, NetLogWithSource()); EXPECT_NE(OK, bad_status); EXPECT_NE(0u, bad_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID); { // Add the root certificate and mark it as trusted. scoped_refptr root_cert = ImportCertFromFile(GetTestCertsDirectory(), kRootCertificateFile); ASSERT_TRUE(root_cert); ScopedTestRoot scoped_root_inner(root_cert); EXPECT_FALSE(test_roots->IsEmpty()); // Test that the certificate verification now succeeds, because the // TestRootCerts is successfully imbuing trust. CertVerifyResult good_verify_result; int good_status = verify_proc->Verify( test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, &good_verify_result, NetLogWithSource()); EXPECT_THAT(good_status, IsOk()); EXPECT_EQ(0u, good_verify_result.cert_status); EXPECT_FALSE(scoped_root_inner.IsEmpty()); EXPECT_TRUE(scoped_root_outer.IsEmpty()); // Move from inner scoped root to outer scoped_root_outer = std::move(scoped_root_inner); EXPECT_FALSE(test_roots->IsEmpty()); EXPECT_FALSE(scoped_root_outer.IsEmpty()); } // After inner scoper was freed, test root is still trusted since ownership // was moved to the outer scoper. EXPECT_FALSE(test_roots->IsEmpty()); EXPECT_FALSE(scoped_root_outer.IsEmpty()); // Test that the certificate verification still succeeds, because the // TestRootCerts is successfully imbuing trust. CertVerifyResult good_verify_result; int good_status = verify_proc->Verify( test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, &good_verify_result, NetLogWithSource()); EXPECT_THAT(good_status, IsOk()); EXPECT_EQ(0u, good_verify_result.cert_status); } EXPECT_TRUE(test_roots->IsEmpty()); // Ensure that when the TestRootCerts is cleared, the trust settings // revert to their original state, and don't linger. If trust status // lingers, it will likely break other tests in net_unittests. CertVerifyResult restored_verify_result; int restored_status = verify_proc->Verify( test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, &restored_verify_result, NetLogWithSource()); EXPECT_NE(OK, restored_status); EXPECT_NE(0u, restored_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID); EXPECT_EQ(bad_status, restored_status); EXPECT_EQ(bad_verify_result.cert_status, restored_verify_result.cert_status); } INSTANTIATE_TEST_SUITE_P(All, TestRootCertsTest, ::testing::Bool()); // TODO(rsleevi): Add tests for revocation checking via CRLs, ensuring that // TestRootCerts properly injects itself into the validation process. See // http://crbug.com/63958 } // namespace net