summaryrefslogtreecommitdiff
path: root/verity
diff options
context:
space:
mode:
authorNikita Ioffe <ioffe@google.com>2020-01-05 04:25:47 +0000
committerNikita Ioffe <ioffe@google.com>2020-01-05 04:25:47 +0000
commit971e4ba1c8e27dfebb52e6a83629456ba07ec1f9 (patch)
tree21f94c1cd0d9e3fcf5329f2479d4bdd355a4cf0e /verity
parent9fff8e3a7e5ddaa6ddc3551d532a548deacb032f (diff)
downloadextras-971e4ba1c8e27dfebb52e6a83629456ba07ec1f9.tar.gz
Add utility to calculate digest from the root of verity tree
This function will help verifying that external hashtree wasn't tampered. See another change in this topic for more context. Test: atest build_verity_tree_test Bug: 145670581 Change-Id: I10a8141a60eec142c77cde0048f0abf44b3406bb
Diffstat (limited to 'verity')
-rw-r--r--verity/build_verity_tree_test.cpp25
-rw-r--r--verity/hash_tree_builder.cpp12
-rw-r--r--verity/include/verity/hash_tree_builder.h4
3 files changed, 38 insertions, 3 deletions
diff --git a/verity/build_verity_tree_test.cpp b/verity/build_verity_tree_test.cpp
index 864ebdc9..8e1f114a 100644
--- a/verity/build_verity_tree_test.cpp
+++ b/verity/build_verity_tree_test.cpp
@@ -157,6 +157,31 @@ TEST_F(BuildVerityTreeTest, StreamingDataPartialBlocks) {
HashTreeBuilder::BytesArrayToString(builder->root_hash()));
}
+TEST_F(BuildVerityTreeTest, CalculateRootDigest) {
+ std::vector<unsigned char> data(256 * 4096);
+ for (size_t i = 0; i < 256; i++) {
+ std::fill_n(data.begin() + i * 4096, 4096, i);
+ }
+
+ ASSERT_TRUE(builder->Initialize(data.size(), salt_hex));
+
+ size_t offset = 0;
+ while (offset < data.size()) {
+ size_t data_length = std::min<size_t>(rand() % 40960, data.size() - offset);
+ ASSERT_TRUE(builder->Update(data.data() + offset, data_length));
+ offset += data_length;
+ }
+
+ ASSERT_TRUE(builder->BuildHashTree());
+ ASSERT_EQ(2u, verity_tree().size());
+ ASSERT_EQ(2 * 4096u, verity_tree()[0].size());
+ std::string expected_root_digest = HashTreeBuilder::BytesArrayToString(builder->root_hash());
+
+ std::vector<unsigned char> actual_root_digest;
+ ASSERT_TRUE(builder->CalculateRootDigest(verity_tree().back(), &actual_root_digest));
+ ASSERT_EQ(expected_root_digest, HashTreeBuilder::BytesArrayToString(actual_root_digest));
+}
+
TEST_F(BuildVerityTreeTest, SHA1MultipleBlocks) {
std::vector<unsigned char> data(128 * 4096, 0xff);
diff --git a/verity/hash_tree_builder.cpp b/verity/hash_tree_builder.cpp
index d061ca5c..79d30405 100644
--- a/verity/hash_tree_builder.cpp
+++ b/verity/hash_tree_builder.cpp
@@ -213,6 +213,14 @@ bool HashTreeBuilder::Update(const unsigned char* data, size_t len) {
return HashBlocks(data, len, &verity_tree_[0]);
}
+bool HashTreeBuilder::CalculateRootDigest(const std::vector<unsigned char>& root_verity,
+ std::vector<unsigned char>* root_digest) {
+ if (root_verity.size() != block_size_) {
+ return false;
+ }
+ return HashBlocks(root_verity.data(), block_size_, root_digest);
+}
+
bool HashTreeBuilder::BuildHashTree() {
// Expects only the base level in the verity_tree_.
CHECK_EQ(1, verity_tree_.size());
@@ -247,9 +255,7 @@ bool HashTreeBuilder::BuildHashTree() {
}
CHECK_EQ(block_size_, verity_tree_.back().size());
- HashBlocks(verity_tree_.back().data(), block_size_, &root_hash_);
-
- return true;
+ return CalculateRootDigest(verity_tree_.back(), &root_hash_);
}
bool HashTreeBuilder::CheckHashTree(
diff --git a/verity/include/verity/hash_tree_builder.h b/verity/include/verity/hash_tree_builder.h
index da47d0fe..7e870bf4 100644
--- a/verity/include/verity/hash_tree_builder.h
+++ b/verity/include/verity/hash_tree_builder.h
@@ -65,6 +65,10 @@ class HashTreeBuilder {
// nullptr if the algorithm is unrecongnized or not supported.
static const EVP_MD* HashFunction(const std::string& hash_name);
+ // Calculates the digest of the root of a verity tree.
+ bool CalculateRootDigest(const std::vector<unsigned char>& root_verity,
+ std::vector<unsigned char>* root_digest);
+
private:
friend class BuildVerityTreeTest;
// Calculates the hash of one single block. Write the result to |out|, a