/* Copyright (c) 2023, Google Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include "test_helpers.h" namespace bssl { static std::unique_ptr MozillaRootStore() { std::string diagnostic; return VerifyTrustStore::FromDER( bssl::ReadTestFileToString( "testdata/verify_unittest/mozilla_roots.der"), &diagnostic); } using ::testing::UnorderedElementsAre; static std::string GetTestdata(std::string_view filename) { return bssl::ReadTestFileToString("testdata/verify_unittest/" + std::string(filename)); } TEST(VerifyTest, GoogleChain) { const std::string leaf = GetTestdata("google-leaf.der"); const std::string intermediate1 = GetTestdata("google-intermediate1.der"); const std::string intermediate2 = GetTestdata("google-intermediate2.der"); CertificateVerifyOptions opts; opts.leaf_cert = leaf; opts.intermediates = {intermediate1, intermediate2}; opts.time = 1499727444; std::unique_ptr roots = MozillaRootStore(); opts.trust_store = roots.get(); VerifyError error; ASSERT_TRUE(CertificateVerify(opts, &error)) << error.DiagnosticString(); opts.intermediates = {}; EXPECT_FALSE(CertificateVerify(opts, &error)); ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND) << error.DiagnosticString(); } TEST(VerifyTest, ExtraIntermediates) { const std::string leaf = GetTestdata("google-leaf.der"); const std::string intermediate1 = GetTestdata("google-intermediate1.der"); const std::string intermediate2 = GetTestdata("google-intermediate2.der"); CertificateVerifyOptions opts; opts.leaf_cert = leaf; std::string diagnostic; const auto cert_pool_status = CertPool::FromCerts( { intermediate1, intermediate2, }, &diagnostic); ASSERT_TRUE(cert_pool_status) << diagnostic; opts.extra_intermediates = cert_pool_status.get(); opts.time = 1499727444; std::unique_ptr roots = MozillaRootStore(); opts.trust_store = roots.get(); VerifyError error; ASSERT_TRUE(CertificateVerify(opts, &error)) << error.DiagnosticString(); } TEST(VerifyTest, AllPaths) { const std::string leaf = GetTestdata("lencr-leaf.der"); const std::string intermediate1 = GetTestdata("lencr-intermediate-r3.der"); const std::string intermediate2 = GetTestdata("lencr-root-x1-cross-signed.der"); const std::string root1 = GetTestdata("lencr-root-x1.der"); const std::string root2 = GetTestdata("lencr-root-dst-x3.der"); std::vector expected_path1 = {leaf, intermediate1, root1}; std::vector expected_path2 = {leaf, intermediate1, intermediate2, root2}; CertificateVerifyOptions opts; opts.leaf_cert = leaf; opts.intermediates = {intermediate1, intermediate2}; opts.time = 1699404611; std::unique_ptr roots = MozillaRootStore(); opts.trust_store = roots.get(); auto paths = CertificateVerifyAllPaths(opts); ASSERT_TRUE(paths); EXPECT_EQ(2U, paths.value().size()); EXPECT_THAT(paths.value(), UnorderedElementsAre(expected_path1, expected_path2)); } TEST(VerifyTest, DepthLimit) { const std::string leaf = GetTestdata("google-leaf.der"); const std::string intermediate1 = GetTestdata("google-intermediate1.der"); const std::string intermediate2 = GetTestdata("google-intermediate2.der"); CertificateVerifyOptions opts; opts.leaf_cert = leaf; opts.intermediates = {intermediate1, intermediate2}; opts.time = 1499727444; // Set the |max_path_building_depth| explicitly to test the non-default case. // Depth of 5 is enough to successfully find a path. opts.max_path_building_depth = 5; std::unique_ptr roots = MozillaRootStore(); opts.trust_store = roots.get(); VerifyError error; ASSERT_TRUE(CertificateVerify(opts, &error)) << error.DiagnosticString(); // Depth of 2 is not enough to find a path. opts.max_path_building_depth = 2; EXPECT_FALSE(CertificateVerify(opts, &error)); ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED) << error.DiagnosticString(); } } // namespace bssl