xref: /aosp_15_r20/system/extras/verity/build_verity_tree_test.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker #include <algorithm>
20*288bf522SAndroid Build Coastguard Worker #include <memory>
21*288bf522SAndroid Build Coastguard Worker #include <string>
22*288bf522SAndroid Build Coastguard Worker #include <vector>
23*288bf522SAndroid Build Coastguard Worker 
24*288bf522SAndroid Build Coastguard Worker #include <gtest/gtest.h>
25*288bf522SAndroid Build Coastguard Worker #include <openssl/evp.h>
26*288bf522SAndroid Build Coastguard Worker 
27*288bf522SAndroid Build Coastguard Worker #include "build_verity_tree_utils.h"
28*288bf522SAndroid Build Coastguard Worker #include "verity/hash_tree_builder.h"
29*288bf522SAndroid Build Coastguard Worker 
30*288bf522SAndroid Build Coastguard Worker // The hex string we are using in build_image.py
31*288bf522SAndroid Build Coastguard Worker // aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7
32*288bf522SAndroid Build Coastguard Worker constexpr unsigned char kSaltHex[] = {
33*288bf522SAndroid Build Coastguard Worker     0xae, 0xe0, 0x87, 0xa5, 0xbe, 0x3b, 0x98, 0x29, 0x78, 0xc9, 0x23,
34*288bf522SAndroid Build Coastguard Worker     0xf5, 0x66, 0xa9, 0x46, 0x13, 0x49, 0x6b, 0x41, 0x7f, 0x2a, 0xf5,
35*288bf522SAndroid Build Coastguard Worker     0x92, 0x63, 0x9b, 0xc8, 0x0d, 0x14, 0x1e, 0x34, 0xdf, 0xe7};
36*288bf522SAndroid Build Coastguard Worker 
37*288bf522SAndroid Build Coastguard Worker class BuildVerityTreeTest : public ::testing::Test {
38*288bf522SAndroid Build Coastguard Worker  protected:
SetUp()39*288bf522SAndroid Build Coastguard Worker   void SetUp() override {
40*288bf522SAndroid Build Coastguard Worker     salt_hex =
41*288bf522SAndroid Build Coastguard Worker         std::vector<unsigned char>(kSaltHex, kSaltHex + sizeof(kSaltHex));
42*288bf522SAndroid Build Coastguard Worker     builder.reset(new HashTreeBuilder(4096, EVP_sha256()));
43*288bf522SAndroid Build Coastguard Worker   }
44*288bf522SAndroid Build Coastguard Worker 
zero_block_hash() const45*288bf522SAndroid Build Coastguard Worker   const std::vector<unsigned char>& zero_block_hash() const {
46*288bf522SAndroid Build Coastguard Worker     return builder->zero_block_hash_;
47*288bf522SAndroid Build Coastguard Worker   }
verity_tree() const48*288bf522SAndroid Build Coastguard Worker   const std::vector<std::vector<unsigned char>>& verity_tree() const {
49*288bf522SAndroid Build Coastguard Worker     return builder->verity_tree_;
50*288bf522SAndroid Build Coastguard Worker   }
51*288bf522SAndroid Build Coastguard Worker 
GenerateHashTree(const std::vector<unsigned char> & data,const std::vector<unsigned char> & salt)52*288bf522SAndroid Build Coastguard Worker   void GenerateHashTree(const std::vector<unsigned char>& data,
53*288bf522SAndroid Build Coastguard Worker                         const std::vector<unsigned char>& salt) {
54*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(builder->Initialize(data.size(), salt));
55*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(builder->Update(data.data(), data.size()));
56*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(builder->BuildHashTree());
57*288bf522SAndroid Build Coastguard Worker   }
58*288bf522SAndroid Build Coastguard Worker 
59*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> salt_hex;
60*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<HashTreeBuilder> builder;
61*288bf522SAndroid Build Coastguard Worker };
62*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,CalculateSize)63*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, CalculateSize) {
64*288bf522SAndroid Build Coastguard Worker   // The hash of source data will occupy at least one block
65*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(4096u, builder->CalculateSize(1));
66*288bf522SAndroid Build Coastguard Worker   // Sha256 hash of 128 blocks fits into one block.
67*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(4096u, builder->CalculateSize(128 * 4096));
68*288bf522SAndroid Build Coastguard Worker   // Requires 3 blocks to hold more data.
69*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(12288u, builder->CalculateSize(128 * 4096 + 1));
70*288bf522SAndroid Build Coastguard Worker 
71*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(20811776u, builder->CalculateSize(2641915904));
72*288bf522SAndroid Build Coastguard Worker }
73*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,InitializeBuilder)74*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, InitializeBuilder) {
75*288bf522SAndroid Build Coastguard Worker   // data_size should be divisible by 4096
76*288bf522SAndroid Build Coastguard Worker   ASSERT_FALSE(builder->Initialize(4095, salt_hex));
77*288bf522SAndroid Build Coastguard Worker 
78*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(builder->Initialize(4096, salt_hex));
79*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(1u, verity_tree().size());
80*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ("6eb8c4e1bce842d137f18b27beb857d3b43899d178090537ad7a0fbe3bf4126a",
81*288bf522SAndroid Build Coastguard Worker             HashTreeBuilder::BytesArrayToString(zero_block_hash()));
82*288bf522SAndroid Build Coastguard Worker }
83*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,HashSingleBlock)84*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, HashSingleBlock) {
85*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> data(4096, 1);
86*288bf522SAndroid Build Coastguard Worker 
87*288bf522SAndroid Build Coastguard Worker   GenerateHashTree(data, salt_hex);
88*288bf522SAndroid Build Coastguard Worker 
89*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(1u, verity_tree().size());
90*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ("e69eb527b16f933483768e92de9bca45f6cc09208525d408436bb362eb865d32",
91*288bf522SAndroid Build Coastguard Worker             HashTreeBuilder::BytesArrayToString(builder->root_hash()));
92*288bf522SAndroid Build Coastguard Worker }
93*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,HashSingleLevel)94*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, HashSingleLevel) {
95*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> data(128 * 4096, 0);
96*288bf522SAndroid Build Coastguard Worker 
97*288bf522SAndroid Build Coastguard Worker   GenerateHashTree(data, salt_hex);
98*288bf522SAndroid Build Coastguard Worker 
99*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(1u, verity_tree().size());
100*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ("62a4fbe8c9036168ba77fe3e3fd78dd6ed963aeb8aaaa36e84f5c7f9107c6b78",
101*288bf522SAndroid Build Coastguard Worker             HashTreeBuilder::BytesArrayToString(builder->root_hash()));
102*288bf522SAndroid Build Coastguard Worker }
103*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,HashSingleLevel_blake2b256)104*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, HashSingleLevel_blake2b256) {
105*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> data(128 * 4096, 0x0);
106*288bf522SAndroid Build Coastguard Worker 
107*288bf522SAndroid Build Coastguard Worker   builder.reset(
108*288bf522SAndroid Build Coastguard Worker       new HashTreeBuilder(4096, HashTreeBuilder::HashFunction("blake2b-256")));
109*288bf522SAndroid Build Coastguard Worker 
110*288bf522SAndroid Build Coastguard Worker   GenerateHashTree(data, salt_hex);
111*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(1u, verity_tree().size());
112*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ("6d5b006af5308523f7db6956c60b2650ff3e7edab1e2194cc8ee19b1a1398c03",
113*288bf522SAndroid Build Coastguard Worker             HashTreeBuilder::BytesArrayToString(builder->root_hash()));
114*288bf522SAndroid Build Coastguard Worker }
115*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,HashMultipleLevels)116*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, HashMultipleLevels) {
117*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> data(129 * 4096, 0xff);
118*288bf522SAndroid Build Coastguard Worker 
119*288bf522SAndroid Build Coastguard Worker   GenerateHashTree(data, salt_hex);
120*288bf522SAndroid Build Coastguard Worker 
121*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(2u, verity_tree().size());
122*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(2 * 4096u, verity_tree()[0].size());
123*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ("9e74f2d47a990c276093760f01de5e9039883e808286ee9492c9cafe9e4ff825",
124*288bf522SAndroid Build Coastguard Worker             HashTreeBuilder::BytesArrayToString(builder->root_hash()));
125*288bf522SAndroid Build Coastguard Worker }
126*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,StreamingDataMultipleBlocks)127*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, StreamingDataMultipleBlocks) {
128*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> data(256 * 4096);
129*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < 256; i++) {
130*288bf522SAndroid Build Coastguard Worker     std::fill_n(data.begin() + i * 4096, 4096, i);
131*288bf522SAndroid Build Coastguard Worker   }
132*288bf522SAndroid Build Coastguard Worker 
133*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(builder->Initialize(data.size(), salt_hex));
134*288bf522SAndroid Build Coastguard Worker 
135*288bf522SAndroid Build Coastguard Worker   size_t offset = 0;
136*288bf522SAndroid Build Coastguard Worker   while (offset < data.size()) {
137*288bf522SAndroid Build Coastguard Worker     size_t data_length =
138*288bf522SAndroid Build Coastguard Worker         std::min<size_t>(rand() % 10 * 4096, data.size() - offset);
139*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(builder->Update(data.data() + offset, data_length));
140*288bf522SAndroid Build Coastguard Worker     offset += data_length;
141*288bf522SAndroid Build Coastguard Worker   }
142*288bf522SAndroid Build Coastguard Worker 
143*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(builder->BuildHashTree());
144*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(2u, verity_tree().size());
145*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(2 * 4096u, verity_tree()[0].size());
146*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ("6e73d59b0b6baf026e921814979a7db02244c95a46b869a17aa1310dad066deb",
147*288bf522SAndroid Build Coastguard Worker             HashTreeBuilder::BytesArrayToString(builder->root_hash()));
148*288bf522SAndroid Build Coastguard Worker }
149*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,StreamingDataPartialBlocks)150*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, StreamingDataPartialBlocks) {
151*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> data(256 * 4096);
152*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < 256; i++) {
153*288bf522SAndroid Build Coastguard Worker     std::fill_n(data.begin() + i * 4096, 4096, i);
154*288bf522SAndroid Build Coastguard Worker   }
155*288bf522SAndroid Build Coastguard Worker 
156*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(builder->Initialize(data.size(), salt_hex));
157*288bf522SAndroid Build Coastguard Worker 
158*288bf522SAndroid Build Coastguard Worker   size_t offset = 0;
159*288bf522SAndroid Build Coastguard Worker   while (offset < data.size()) {
160*288bf522SAndroid Build Coastguard Worker     size_t data_length = std::min<size_t>(rand() % 40960, data.size() - offset);
161*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(builder->Update(data.data() + offset, data_length));
162*288bf522SAndroid Build Coastguard Worker     offset += data_length;
163*288bf522SAndroid Build Coastguard Worker   }
164*288bf522SAndroid Build Coastguard Worker 
165*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(builder->BuildHashTree());
166*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(2u, verity_tree().size());
167*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(2 * 4096u, verity_tree()[0].size());
168*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ("6e73d59b0b6baf026e921814979a7db02244c95a46b869a17aa1310dad066deb",
169*288bf522SAndroid Build Coastguard Worker             HashTreeBuilder::BytesArrayToString(builder->root_hash()));
170*288bf522SAndroid Build Coastguard Worker }
171*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,CalculateRootDigest)172*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, CalculateRootDigest) {
173*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> data(256 * 4096);
174*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < 256; i++) {
175*288bf522SAndroid Build Coastguard Worker     std::fill_n(data.begin() + i * 4096, 4096, i);
176*288bf522SAndroid Build Coastguard Worker   }
177*288bf522SAndroid Build Coastguard Worker 
178*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(builder->Initialize(data.size(), salt_hex));
179*288bf522SAndroid Build Coastguard Worker 
180*288bf522SAndroid Build Coastguard Worker   size_t offset = 0;
181*288bf522SAndroid Build Coastguard Worker   while (offset < data.size()) {
182*288bf522SAndroid Build Coastguard Worker     size_t data_length = std::min<size_t>(rand() % 40960, data.size() - offset);
183*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(builder->Update(data.data() + offset, data_length));
184*288bf522SAndroid Build Coastguard Worker     offset += data_length;
185*288bf522SAndroid Build Coastguard Worker   }
186*288bf522SAndroid Build Coastguard Worker 
187*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(builder->BuildHashTree());
188*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(2u, verity_tree().size());
189*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(2 * 4096u, verity_tree()[0].size());
190*288bf522SAndroid Build Coastguard Worker   std::string expected_root_digest =  HashTreeBuilder::BytesArrayToString(builder->root_hash());
191*288bf522SAndroid Build Coastguard Worker 
192*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> actual_root_digest;
193*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(builder->CalculateRootDigest(verity_tree().back(), &actual_root_digest));
194*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(expected_root_digest, HashTreeBuilder::BytesArrayToString(actual_root_digest));
195*288bf522SAndroid Build Coastguard Worker }
196*288bf522SAndroid Build Coastguard Worker 
TEST_F(BuildVerityTreeTest,SHA1MultipleBlocks)197*288bf522SAndroid Build Coastguard Worker TEST_F(BuildVerityTreeTest, SHA1MultipleBlocks) {
198*288bf522SAndroid Build Coastguard Worker   std::vector<unsigned char> data(128 * 4096, 0xff);
199*288bf522SAndroid Build Coastguard Worker 
200*288bf522SAndroid Build Coastguard Worker   builder.reset(
201*288bf522SAndroid Build Coastguard Worker       new HashTreeBuilder(4096, HashTreeBuilder::HashFunction("SHA1")));
202*288bf522SAndroid Build Coastguard Worker 
203*288bf522SAndroid Build Coastguard Worker   GenerateHashTree(data, salt_hex);
204*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(1u, verity_tree().size());
205*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ("7ea287e6167929988810077abaafbc313b2b8593000000000000000000000000",
206*288bf522SAndroid Build Coastguard Worker             HashTreeBuilder::BytesArrayToString(builder->root_hash()));
207*288bf522SAndroid Build Coastguard Worker }
208