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