|  | // Copyright 2016 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/merkle_tree_leaf.h" | 
|  |  | 
|  | #include <string.h> | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include "base/strings/string_number_conversions.h" | 
|  | #include "net/cert/x509_certificate.h" | 
|  | #include "net/test/cert_test_util.h" | 
|  | #include "net/test/ct_test_util.h" | 
|  | #include "net/test/test_data_directory.h" | 
|  | #include "starboard/memory.h" | 
|  | #include "starboard/types.h" | 
|  | #include "testing/gmock/include/gmock/gmock.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | namespace ct { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | MATCHER_P(HexEq, hexStr, "") { | 
|  | std::vector<uint8_t> bytes; | 
|  |  | 
|  | if (!base::HexStringToBytes(hexStr, &bytes)) { | 
|  | *result_listener << "expected value was not a valid hex string"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (bytes.size() != arg.size()) { | 
|  | *result_listener << "expected and actual are different lengths"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Make sure we don't pass nullptrs to memcmp | 
|  | if (arg.empty()) | 
|  | return true; | 
|  |  | 
|  | // Print hex string (easier to read than default GTest representation) | 
|  | *result_listener << "a.k.a. 0x" << base::HexEncode(arg.data(), arg.size()); | 
|  | return SbMemoryCompare(arg.data(), bytes.data(), bytes.size()) == 0; | 
|  | } | 
|  |  | 
|  | class MerkleTreeLeafTest : public ::testing::Test { | 
|  | public: | 
|  | void SetUp() override { | 
|  | std::string der_test_cert(ct::GetDerEncodedX509Cert()); | 
|  | test_cert_ = X509Certificate::CreateFromBytes(der_test_cert.data(), | 
|  | der_test_cert.length()); | 
|  | ASSERT_TRUE(test_cert_); | 
|  |  | 
|  | GetX509CertSCT(&x509_sct_); | 
|  | x509_sct_->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE; | 
|  |  | 
|  | test_precert_ = CreateCertificateChainFromFile( | 
|  | GetTestCertsDirectory(), "ct-test-embedded-cert.pem", | 
|  | X509Certificate::FORMAT_AUTO); | 
|  | ASSERT_TRUE(test_precert_); | 
|  | ASSERT_EQ(1u, test_precert_->intermediate_buffers().size()); | 
|  | GetPrecertSCT(&precert_sct_); | 
|  | precert_sct_->origin = SignedCertificateTimestamp::SCT_EMBEDDED; | 
|  | } | 
|  |  | 
|  | protected: | 
|  | scoped_refptr<SignedCertificateTimestamp> x509_sct_; | 
|  | scoped_refptr<SignedCertificateTimestamp> precert_sct_; | 
|  | scoped_refptr<X509Certificate> test_cert_; | 
|  | scoped_refptr<X509Certificate> test_precert_; | 
|  | }; | 
|  |  | 
|  | TEST_F(MerkleTreeLeafTest, CreatesForX509Cert) { | 
|  | MerkleTreeLeaf leaf; | 
|  | ASSERT_TRUE(GetMerkleTreeLeaf(test_cert_.get(), x509_sct_.get(), &leaf)); | 
|  |  | 
|  | EXPECT_EQ(SignedEntryData::LOG_ENTRY_TYPE_X509, leaf.signed_entry.type); | 
|  | EXPECT_FALSE(leaf.signed_entry.leaf_certificate.empty()); | 
|  | EXPECT_TRUE(leaf.signed_entry.tbs_certificate.empty()); | 
|  |  | 
|  | EXPECT_EQ(x509_sct_->timestamp, leaf.timestamp); | 
|  | EXPECT_EQ(x509_sct_->extensions, leaf.extensions); | 
|  | } | 
|  |  | 
|  | TEST_F(MerkleTreeLeafTest, CreatesForPrecert) { | 
|  | MerkleTreeLeaf leaf; | 
|  | ASSERT_TRUE( | 
|  | GetMerkleTreeLeaf(test_precert_.get(), precert_sct_.get(), &leaf)); | 
|  |  | 
|  | EXPECT_EQ(SignedEntryData::LOG_ENTRY_TYPE_PRECERT, leaf.signed_entry.type); | 
|  | EXPECT_FALSE(leaf.signed_entry.tbs_certificate.empty()); | 
|  | EXPECT_TRUE(leaf.signed_entry.leaf_certificate.empty()); | 
|  |  | 
|  | EXPECT_EQ(precert_sct_->timestamp, leaf.timestamp); | 
|  | EXPECT_EQ(precert_sct_->extensions, leaf.extensions); | 
|  | } | 
|  |  | 
|  | TEST_F(MerkleTreeLeafTest, DoesNotCreateForEmbeddedSCTButNotPrecert) { | 
|  | MerkleTreeLeaf leaf; | 
|  | ASSERT_FALSE(GetMerkleTreeLeaf(test_cert_.get(), precert_sct_.get(), &leaf)); | 
|  | } | 
|  |  | 
|  | // Expected hashes calculated by: | 
|  | // 1. Writing the serialized tree leaves from | 
|  | //    CtSerialization::EncodesLogEntryFor{X509Cert,Precert} to files. | 
|  | // 2. Prepending a zero byte to both files. | 
|  | // 3. Passing each file through the sha256sum tool. | 
|  |  | 
|  | TEST_F(MerkleTreeLeafTest, HashForX509Cert) { | 
|  | MerkleTreeLeaf leaf; | 
|  | ct::GetX509CertTreeLeaf(&leaf); | 
|  |  | 
|  | std::string hash; | 
|  | ASSERT_TRUE(HashMerkleTreeLeaf(leaf, &hash)); | 
|  | EXPECT_THAT(hash, HexEq("452da788b3b8d15872ff0bb0777354b2a7f1c1887b5633201e76" | 
|  | "2ba5a4b143fc")); | 
|  | } | 
|  |  | 
|  | TEST_F(MerkleTreeLeafTest, HashForPrecert) { | 
|  | MerkleTreeLeaf leaf; | 
|  | ct::GetPrecertTreeLeaf(&leaf); | 
|  |  | 
|  | std::string hash; | 
|  | ASSERT_TRUE(HashMerkleTreeLeaf(leaf, &hash)); | 
|  | EXPECT_THAT(hash, HexEq("257ae85f08810445511e35e33f7aee99ee19407971e35e95822b" | 
|  | "bf42a74be223")); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | }  // namespace ct | 
|  |  | 
|  | }  // namespace net |