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 "verity/hash_tree_builder.h"
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #include <algorithm>
20*288bf522SAndroid Build Coastguard Worker #include <functional>
21*288bf522SAndroid Build Coastguard Worker #include <memory>
22*288bf522SAndroid Build Coastguard Worker
23*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
24*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
25*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
26*288bf522SAndroid Build Coastguard Worker #include <android-base/strings.h>
27*288bf522SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
28*288bf522SAndroid Build Coastguard Worker #include <openssl/bn.h>
29*288bf522SAndroid Build Coastguard Worker
30*288bf522SAndroid Build Coastguard Worker #include "build_verity_tree_utils.h"
31*288bf522SAndroid Build Coastguard Worker
HashFunction(const std::string & hash_name)32*288bf522SAndroid Build Coastguard Worker const EVP_MD* HashTreeBuilder::HashFunction(const std::string& hash_name) {
33*288bf522SAndroid Build Coastguard Worker if (android::base::EqualsIgnoreCase(hash_name, "sha1")) {
34*288bf522SAndroid Build Coastguard Worker return EVP_sha1();
35*288bf522SAndroid Build Coastguard Worker }
36*288bf522SAndroid Build Coastguard Worker if (android::base::EqualsIgnoreCase(hash_name, "sha256")) {
37*288bf522SAndroid Build Coastguard Worker return EVP_sha256();
38*288bf522SAndroid Build Coastguard Worker }
39*288bf522SAndroid Build Coastguard Worker if (android::base::EqualsIgnoreCase(hash_name, "sha384")) {
40*288bf522SAndroid Build Coastguard Worker return EVP_sha384();
41*288bf522SAndroid Build Coastguard Worker }
42*288bf522SAndroid Build Coastguard Worker if (android::base::EqualsIgnoreCase(hash_name, "sha512")) {
43*288bf522SAndroid Build Coastguard Worker return EVP_sha512();
44*288bf522SAndroid Build Coastguard Worker }
45*288bf522SAndroid Build Coastguard Worker if (android::base::EqualsIgnoreCase(hash_name, "blake2b-256")) {
46*288bf522SAndroid Build Coastguard Worker return EVP_blake2b256();
47*288bf522SAndroid Build Coastguard Worker }
48*288bf522SAndroid Build Coastguard Worker
49*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Unsupported hash algorithm " << hash_name;
50*288bf522SAndroid Build Coastguard Worker return nullptr;
51*288bf522SAndroid Build Coastguard Worker }
52*288bf522SAndroid Build Coastguard Worker
HashTreeBuilder(size_t block_size,const EVP_MD * md)53*288bf522SAndroid Build Coastguard Worker HashTreeBuilder::HashTreeBuilder(size_t block_size, const EVP_MD* md)
54*288bf522SAndroid Build Coastguard Worker : block_size_(block_size), data_size_(0), md_(md) {
55*288bf522SAndroid Build Coastguard Worker CHECK(md_ != nullptr) << "Failed to initialize md";
56*288bf522SAndroid Build Coastguard Worker
57*288bf522SAndroid Build Coastguard Worker hash_size_raw_ = EVP_MD_size(md_);
58*288bf522SAndroid Build Coastguard Worker
59*288bf522SAndroid Build Coastguard Worker // Round up the hash size to the next power of 2.
60*288bf522SAndroid Build Coastguard Worker hash_size_ = 1;
61*288bf522SAndroid Build Coastguard Worker while (hash_size_ < hash_size_raw_) {
62*288bf522SAndroid Build Coastguard Worker hash_size_ = hash_size_ << 1;
63*288bf522SAndroid Build Coastguard Worker }
64*288bf522SAndroid Build Coastguard Worker CHECK_LT(hash_size_ * 2, block_size_);
65*288bf522SAndroid Build Coastguard Worker }
66*288bf522SAndroid Build Coastguard Worker
BytesArrayToString(const std::vector<unsigned char> & bytes)67*288bf522SAndroid Build Coastguard Worker std::string HashTreeBuilder::BytesArrayToString(
68*288bf522SAndroid Build Coastguard Worker const std::vector<unsigned char>& bytes) {
69*288bf522SAndroid Build Coastguard Worker std::string result;
70*288bf522SAndroid Build Coastguard Worker for (const auto& c : bytes) {
71*288bf522SAndroid Build Coastguard Worker result += android::base::StringPrintf("%02x", c);
72*288bf522SAndroid Build Coastguard Worker }
73*288bf522SAndroid Build Coastguard Worker return result;
74*288bf522SAndroid Build Coastguard Worker }
75*288bf522SAndroid Build Coastguard Worker
ParseBytesArrayFromString(const std::string & hex_string,std::vector<unsigned char> * bytes)76*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::ParseBytesArrayFromString(
77*288bf522SAndroid Build Coastguard Worker const std::string& hex_string, std::vector<unsigned char>* bytes) {
78*288bf522SAndroid Build Coastguard Worker if (hex_string.size() % 2 != 0) {
79*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Hex string size must be even number " << hex_string;
80*288bf522SAndroid Build Coastguard Worker return false;
81*288bf522SAndroid Build Coastguard Worker }
82*288bf522SAndroid Build Coastguard Worker
83*288bf522SAndroid Build Coastguard Worker BIGNUM* bn = nullptr;
84*288bf522SAndroid Build Coastguard Worker if (!BN_hex2bn(&bn, hex_string.c_str())) {
85*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse hex in " << hex_string;
86*288bf522SAndroid Build Coastguard Worker return false;
87*288bf522SAndroid Build Coastguard Worker }
88*288bf522SAndroid Build Coastguard Worker std::unique_ptr<BIGNUM, decltype(&BN_free)> guard(bn, BN_free);
89*288bf522SAndroid Build Coastguard Worker
90*288bf522SAndroid Build Coastguard Worker size_t bytes_size = BN_num_bytes(bn);
91*288bf522SAndroid Build Coastguard Worker bytes->resize(bytes_size);
92*288bf522SAndroid Build Coastguard Worker if (BN_bn2bin(bn, bytes->data()) != bytes_size) {
93*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to convert hex to bytes " << hex_string;
94*288bf522SAndroid Build Coastguard Worker return false;
95*288bf522SAndroid Build Coastguard Worker }
96*288bf522SAndroid Build Coastguard Worker return true;
97*288bf522SAndroid Build Coastguard Worker }
98*288bf522SAndroid Build Coastguard Worker
CalculateSize(uint64_t input_size,size_t block_size,size_t hash_size)99*288bf522SAndroid Build Coastguard Worker uint64_t HashTreeBuilder::CalculateSize(
100*288bf522SAndroid Build Coastguard Worker uint64_t input_size, size_t block_size, size_t hash_size) {
101*288bf522SAndroid Build Coastguard Worker uint64_t verity_blocks = 0;
102*288bf522SAndroid Build Coastguard Worker size_t level_blocks;
103*288bf522SAndroid Build Coastguard Worker size_t levels = 0;
104*288bf522SAndroid Build Coastguard Worker do {
105*288bf522SAndroid Build Coastguard Worker level_blocks =
106*288bf522SAndroid Build Coastguard Worker verity_tree_blocks(input_size, block_size, hash_size, levels);
107*288bf522SAndroid Build Coastguard Worker levels++;
108*288bf522SAndroid Build Coastguard Worker verity_blocks += level_blocks;
109*288bf522SAndroid Build Coastguard Worker } while (level_blocks > 1);
110*288bf522SAndroid Build Coastguard Worker
111*288bf522SAndroid Build Coastguard Worker return verity_blocks * block_size;
112*288bf522SAndroid Build Coastguard Worker }
113*288bf522SAndroid Build Coastguard Worker
Initialize(int64_t expected_data_size,const std::vector<unsigned char> & salt)114*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::Initialize(int64_t expected_data_size,
115*288bf522SAndroid Build Coastguard Worker const std::vector<unsigned char>& salt) {
116*288bf522SAndroid Build Coastguard Worker data_size_ = expected_data_size;
117*288bf522SAndroid Build Coastguard Worker salt_ = salt;
118*288bf522SAndroid Build Coastguard Worker
119*288bf522SAndroid Build Coastguard Worker if (data_size_ % block_size_ != 0) {
120*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "file size " << data_size_
121*288bf522SAndroid Build Coastguard Worker << " is not a multiple of block size " << block_size_;
122*288bf522SAndroid Build Coastguard Worker return false;
123*288bf522SAndroid Build Coastguard Worker }
124*288bf522SAndroid Build Coastguard Worker
125*288bf522SAndroid Build Coastguard Worker // Reserve enough space for the hash of the input data.
126*288bf522SAndroid Build Coastguard Worker size_t base_level_blocks =
127*288bf522SAndroid Build Coastguard Worker verity_tree_blocks(data_size_, block_size_, hash_size_, 0);
128*288bf522SAndroid Build Coastguard Worker std::vector<unsigned char> base_level;
129*288bf522SAndroid Build Coastguard Worker base_level.reserve(base_level_blocks * block_size_);
130*288bf522SAndroid Build Coastguard Worker verity_tree_.emplace_back(std::move(base_level));
131*288bf522SAndroid Build Coastguard Worker
132*288bf522SAndroid Build Coastguard Worker // Save the hash of the zero block to avoid future recalculation.
133*288bf522SAndroid Build Coastguard Worker std::vector<unsigned char> zero_block(block_size_, 0);
134*288bf522SAndroid Build Coastguard Worker zero_block_hash_.resize(hash_size_);
135*288bf522SAndroid Build Coastguard Worker HashBlock(zero_block.data(), zero_block_hash_.data());
136*288bf522SAndroid Build Coastguard Worker
137*288bf522SAndroid Build Coastguard Worker return true;
138*288bf522SAndroid Build Coastguard Worker }
139*288bf522SAndroid Build Coastguard Worker
HashBlock(const unsigned char * block,unsigned char * out)140*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::HashBlock(const unsigned char* block,
141*288bf522SAndroid Build Coastguard Worker unsigned char* out) {
142*288bf522SAndroid Build Coastguard Worker unsigned int s;
143*288bf522SAndroid Build Coastguard Worker int ret = 1;
144*288bf522SAndroid Build Coastguard Worker
145*288bf522SAndroid Build Coastguard Worker EVP_MD_CTX* mdctx = EVP_MD_CTX_create();
146*288bf522SAndroid Build Coastguard Worker CHECK(mdctx != nullptr);
147*288bf522SAndroid Build Coastguard Worker ret &= EVP_DigestInit_ex(mdctx, md_, nullptr);
148*288bf522SAndroid Build Coastguard Worker ret &= EVP_DigestUpdate(mdctx, salt_.data(), salt_.size());
149*288bf522SAndroid Build Coastguard Worker ret &= EVP_DigestUpdate(mdctx, block, block_size_);
150*288bf522SAndroid Build Coastguard Worker ret &= EVP_DigestFinal_ex(mdctx, out, &s);
151*288bf522SAndroid Build Coastguard Worker EVP_MD_CTX_destroy(mdctx);
152*288bf522SAndroid Build Coastguard Worker
153*288bf522SAndroid Build Coastguard Worker CHECK_EQ(1, ret);
154*288bf522SAndroid Build Coastguard Worker CHECK_EQ(hash_size_raw_, s);
155*288bf522SAndroid Build Coastguard Worker std::fill(out + s, out + hash_size_, 0);
156*288bf522SAndroid Build Coastguard Worker
157*288bf522SAndroid Build Coastguard Worker return true;
158*288bf522SAndroid Build Coastguard Worker }
159*288bf522SAndroid Build Coastguard Worker
HashBlocks(const unsigned char * data,size_t len,std::vector<unsigned char> * output_vector)160*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::HashBlocks(const unsigned char* data, size_t len,
161*288bf522SAndroid Build Coastguard Worker std::vector<unsigned char>* output_vector) {
162*288bf522SAndroid Build Coastguard Worker if (len == 0) {
163*288bf522SAndroid Build Coastguard Worker return true;
164*288bf522SAndroid Build Coastguard Worker }
165*288bf522SAndroid Build Coastguard Worker CHECK_EQ(0, len % block_size_);
166*288bf522SAndroid Build Coastguard Worker
167*288bf522SAndroid Build Coastguard Worker if (data == nullptr) {
168*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < len; i += block_size_) {
169*288bf522SAndroid Build Coastguard Worker output_vector->insert(output_vector->end(), zero_block_hash_.begin(),
170*288bf522SAndroid Build Coastguard Worker zero_block_hash_.end());
171*288bf522SAndroid Build Coastguard Worker }
172*288bf522SAndroid Build Coastguard Worker return true;
173*288bf522SAndroid Build Coastguard Worker }
174*288bf522SAndroid Build Coastguard Worker
175*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < len; i += block_size_) {
176*288bf522SAndroid Build Coastguard Worker unsigned char hash_buffer[hash_size_];
177*288bf522SAndroid Build Coastguard Worker if (!HashBlock(data + i, hash_buffer)) {
178*288bf522SAndroid Build Coastguard Worker return false;
179*288bf522SAndroid Build Coastguard Worker }
180*288bf522SAndroid Build Coastguard Worker output_vector->insert(output_vector->end(), hash_buffer,
181*288bf522SAndroid Build Coastguard Worker hash_buffer + hash_size_);
182*288bf522SAndroid Build Coastguard Worker }
183*288bf522SAndroid Build Coastguard Worker
184*288bf522SAndroid Build Coastguard Worker return true;
185*288bf522SAndroid Build Coastguard Worker }
186*288bf522SAndroid Build Coastguard Worker
Update(const unsigned char * data,size_t len)187*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::Update(const unsigned char* data, size_t len) {
188*288bf522SAndroid Build Coastguard Worker CHECK_GT(data_size_, 0);
189*288bf522SAndroid Build Coastguard Worker
190*288bf522SAndroid Build Coastguard Worker if (!leftover_.empty()) {
191*288bf522SAndroid Build Coastguard Worker CHECK_LT(leftover_.size(), block_size_);
192*288bf522SAndroid Build Coastguard Worker size_t append_len = std::min(len, block_size_ - leftover_.size());
193*288bf522SAndroid Build Coastguard Worker if (data == nullptr) {
194*288bf522SAndroid Build Coastguard Worker leftover_.insert(leftover_.end(), append_len, 0);
195*288bf522SAndroid Build Coastguard Worker } else {
196*288bf522SAndroid Build Coastguard Worker leftover_.insert(leftover_.end(), data, data + append_len);
197*288bf522SAndroid Build Coastguard Worker }
198*288bf522SAndroid Build Coastguard Worker if (leftover_.size() < block_size_) {
199*288bf522SAndroid Build Coastguard Worker return true;
200*288bf522SAndroid Build Coastguard Worker }
201*288bf522SAndroid Build Coastguard Worker if (!HashBlocks(leftover_.data(), leftover_.size(), &verity_tree_[0])) {
202*288bf522SAndroid Build Coastguard Worker return false;
203*288bf522SAndroid Build Coastguard Worker }
204*288bf522SAndroid Build Coastguard Worker leftover_.clear();
205*288bf522SAndroid Build Coastguard Worker if (data != nullptr) {
206*288bf522SAndroid Build Coastguard Worker data += append_len;
207*288bf522SAndroid Build Coastguard Worker }
208*288bf522SAndroid Build Coastguard Worker len -= append_len;
209*288bf522SAndroid Build Coastguard Worker }
210*288bf522SAndroid Build Coastguard Worker if (len % block_size_ != 0) {
211*288bf522SAndroid Build Coastguard Worker if (data == nullptr) {
212*288bf522SAndroid Build Coastguard Worker leftover_.assign(len % block_size_, 0);
213*288bf522SAndroid Build Coastguard Worker } else {
214*288bf522SAndroid Build Coastguard Worker leftover_.assign(data + len - len % block_size_, data + len);
215*288bf522SAndroid Build Coastguard Worker }
216*288bf522SAndroid Build Coastguard Worker len -= len % block_size_;
217*288bf522SAndroid Build Coastguard Worker }
218*288bf522SAndroid Build Coastguard Worker return HashBlocks(data, len, &verity_tree_[0]);
219*288bf522SAndroid Build Coastguard Worker }
220*288bf522SAndroid Build Coastguard Worker
CalculateRootDigest(const std::vector<unsigned char> & root_verity,std::vector<unsigned char> * root_digest)221*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::CalculateRootDigest(const std::vector<unsigned char>& root_verity,
222*288bf522SAndroid Build Coastguard Worker std::vector<unsigned char>* root_digest) {
223*288bf522SAndroid Build Coastguard Worker if (root_verity.size() != block_size_) {
224*288bf522SAndroid Build Coastguard Worker return false;
225*288bf522SAndroid Build Coastguard Worker }
226*288bf522SAndroid Build Coastguard Worker return HashBlocks(root_verity.data(), block_size_, root_digest);
227*288bf522SAndroid Build Coastguard Worker }
228*288bf522SAndroid Build Coastguard Worker
BuildHashTree()229*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::BuildHashTree() {
230*288bf522SAndroid Build Coastguard Worker // Expects only the base level in the verity_tree_.
231*288bf522SAndroid Build Coastguard Worker CHECK_EQ(1, verity_tree_.size());
232*288bf522SAndroid Build Coastguard Worker
233*288bf522SAndroid Build Coastguard Worker if (!leftover_.empty()) {
234*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << leftover_.size() << " bytes data left from last Update().";
235*288bf522SAndroid Build Coastguard Worker return false;
236*288bf522SAndroid Build Coastguard Worker }
237*288bf522SAndroid Build Coastguard Worker
238*288bf522SAndroid Build Coastguard Worker // Expects the base level to have the same size as the total hash size of
239*288bf522SAndroid Build Coastguard Worker // input data.
240*288bf522SAndroid Build Coastguard Worker AppendPaddings(&verity_tree_.back());
241*288bf522SAndroid Build Coastguard Worker size_t base_level_blocks =
242*288bf522SAndroid Build Coastguard Worker verity_tree_blocks(data_size_, block_size_, hash_size_, 0);
243*288bf522SAndroid Build Coastguard Worker CHECK_EQ(base_level_blocks * block_size_, verity_tree_[0].size());
244*288bf522SAndroid Build Coastguard Worker
245*288bf522SAndroid Build Coastguard Worker while (verity_tree_.back().size() > block_size_) {
246*288bf522SAndroid Build Coastguard Worker const auto& current_level = verity_tree_.back();
247*288bf522SAndroid Build Coastguard Worker // Computes the next level of the verity tree based on the hash of the
248*288bf522SAndroid Build Coastguard Worker // current level.
249*288bf522SAndroid Build Coastguard Worker size_t next_level_blocks =
250*288bf522SAndroid Build Coastguard Worker verity_tree_blocks(current_level.size(), block_size_, hash_size_, 0);
251*288bf522SAndroid Build Coastguard Worker std::vector<unsigned char> next_level;
252*288bf522SAndroid Build Coastguard Worker next_level.reserve(next_level_blocks * block_size_);
253*288bf522SAndroid Build Coastguard Worker
254*288bf522SAndroid Build Coastguard Worker HashBlocks(current_level.data(), current_level.size(), &next_level);
255*288bf522SAndroid Build Coastguard Worker AppendPaddings(&next_level);
256*288bf522SAndroid Build Coastguard Worker
257*288bf522SAndroid Build Coastguard Worker // Checks the size of the next level.
258*288bf522SAndroid Build Coastguard Worker CHECK_EQ(next_level_blocks * block_size_, next_level.size());
259*288bf522SAndroid Build Coastguard Worker verity_tree_.emplace_back(std::move(next_level));
260*288bf522SAndroid Build Coastguard Worker }
261*288bf522SAndroid Build Coastguard Worker
262*288bf522SAndroid Build Coastguard Worker CHECK_EQ(block_size_, verity_tree_.back().size());
263*288bf522SAndroid Build Coastguard Worker return CalculateRootDigest(verity_tree_.back(), &root_hash_);
264*288bf522SAndroid Build Coastguard Worker }
265*288bf522SAndroid Build Coastguard Worker
CheckHashTree(const std::vector<unsigned char> & hash_tree) const266*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::CheckHashTree(
267*288bf522SAndroid Build Coastguard Worker const std::vector<unsigned char>& hash_tree) const {
268*288bf522SAndroid Build Coastguard Worker size_t offset = 0;
269*288bf522SAndroid Build Coastguard Worker // Reads reversely to output the verity tree top-down.
270*288bf522SAndroid Build Coastguard Worker for (size_t i = verity_tree_.size(); i > 0; i--) {
271*288bf522SAndroid Build Coastguard Worker const auto& level_blocks = verity_tree_[i - 1];
272*288bf522SAndroid Build Coastguard Worker if (offset + level_blocks.size() > hash_tree.size()) {
273*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Hash tree too small: " << hash_tree.size();
274*288bf522SAndroid Build Coastguard Worker return false;
275*288bf522SAndroid Build Coastguard Worker }
276*288bf522SAndroid Build Coastguard Worker auto iter = std::mismatch(level_blocks.begin(), level_blocks.end(),
277*288bf522SAndroid Build Coastguard Worker hash_tree.begin() + offset)
278*288bf522SAndroid Build Coastguard Worker .first;
279*288bf522SAndroid Build Coastguard Worker if (iter != level_blocks.end()) {
280*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Mismatch found at the hash tree level " << i << " offset "
281*288bf522SAndroid Build Coastguard Worker << std::distance(level_blocks.begin(), iter);
282*288bf522SAndroid Build Coastguard Worker return false;
283*288bf522SAndroid Build Coastguard Worker }
284*288bf522SAndroid Build Coastguard Worker offset += level_blocks.size();
285*288bf522SAndroid Build Coastguard Worker }
286*288bf522SAndroid Build Coastguard Worker if (offset != hash_tree.size()) {
287*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Hash tree size mismatch: " << hash_tree.size()
288*288bf522SAndroid Build Coastguard Worker << " != " << offset;
289*288bf522SAndroid Build Coastguard Worker return false;
290*288bf522SAndroid Build Coastguard Worker }
291*288bf522SAndroid Build Coastguard Worker return true;
292*288bf522SAndroid Build Coastguard Worker }
293*288bf522SAndroid Build Coastguard Worker
WriteHashTreeToFile(const std::string & output) const294*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::WriteHashTreeToFile(const std::string& output) const {
295*288bf522SAndroid Build Coastguard Worker android::base::unique_fd output_fd(
296*288bf522SAndroid Build Coastguard Worker open(output.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666));
297*288bf522SAndroid Build Coastguard Worker if (output_fd == -1) {
298*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to open output file " << output;
299*288bf522SAndroid Build Coastguard Worker return false;
300*288bf522SAndroid Build Coastguard Worker }
301*288bf522SAndroid Build Coastguard Worker
302*288bf522SAndroid Build Coastguard Worker return WriteHashTreeToFd(output_fd, 0);
303*288bf522SAndroid Build Coastguard Worker }
304*288bf522SAndroid Build Coastguard Worker
WriteHashTree(std::function<bool (const void *,size_t)> callback) const305*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::WriteHashTree(
306*288bf522SAndroid Build Coastguard Worker std::function<bool(const void*, size_t)> callback) const {
307*288bf522SAndroid Build Coastguard Worker CHECK(!verity_tree_.empty());
308*288bf522SAndroid Build Coastguard Worker
309*288bf522SAndroid Build Coastguard Worker // Reads reversely to output the verity tree top-down.
310*288bf522SAndroid Build Coastguard Worker for (size_t i = verity_tree_.size(); i > 0; i--) {
311*288bf522SAndroid Build Coastguard Worker const auto& level_blocks = verity_tree_[i - 1];
312*288bf522SAndroid Build Coastguard Worker if (!callback(level_blocks.data(), level_blocks.size())) {
313*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to write the hash tree level " << i;
314*288bf522SAndroid Build Coastguard Worker return false;
315*288bf522SAndroid Build Coastguard Worker }
316*288bf522SAndroid Build Coastguard Worker }
317*288bf522SAndroid Build Coastguard Worker
318*288bf522SAndroid Build Coastguard Worker return true;
319*288bf522SAndroid Build Coastguard Worker }
320*288bf522SAndroid Build Coastguard Worker
WriteHashTreeToFd(int fd,uint64_t offset) const321*288bf522SAndroid Build Coastguard Worker bool HashTreeBuilder::WriteHashTreeToFd(int fd, uint64_t offset) const {
322*288bf522SAndroid Build Coastguard Worker CHECK(!verity_tree_.empty());
323*288bf522SAndroid Build Coastguard Worker
324*288bf522SAndroid Build Coastguard Worker if (lseek(fd, offset, SEEK_SET) != offset) {
325*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to seek the output fd, offset: " << offset;
326*288bf522SAndroid Build Coastguard Worker return false;
327*288bf522SAndroid Build Coastguard Worker }
328*288bf522SAndroid Build Coastguard Worker
329*288bf522SAndroid Build Coastguard Worker return WriteHashTree([fd](auto data, auto size) {
330*288bf522SAndroid Build Coastguard Worker return android::base::WriteFully(fd, data, size);
331*288bf522SAndroid Build Coastguard Worker });
332*288bf522SAndroid Build Coastguard Worker }
333*288bf522SAndroid Build Coastguard Worker
AppendPaddings(std::vector<unsigned char> * data)334*288bf522SAndroid Build Coastguard Worker void HashTreeBuilder::AppendPaddings(std::vector<unsigned char>* data) {
335*288bf522SAndroid Build Coastguard Worker size_t remainder = data->size() % block_size_;
336*288bf522SAndroid Build Coastguard Worker if (remainder != 0) {
337*288bf522SAndroid Build Coastguard Worker data->resize(data->size() + block_size_ - remainder, 0);
338*288bf522SAndroid Build Coastguard Worker }
339*288bf522SAndroid Build Coastguard Worker }
340