1 /*
2  * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "fs_verity_generator.h"
16 
17 namespace OHOS {
18 namespace SignatureTools {
19 const FsVerityHashAlgorithm FS_SHA256(1, "SHA-256", 256 / 8);
20 const FsVerityHashAlgorithm FS_SHA512(2, "SHA-512", 512 / 8);
21 const int8_t FsVerityGenerator::LOG_2_OF_FSVERITY_HASH_PAGE_SIZE = 12;
22 const FsVerityHashAlgorithm FsVerityGenerator::FS_VERITY_HASH_ALGORITHM = FS_SHA256;
23 
GenerateMerkleTree(std::istream& inputStream, long size, const FsVerityHashAlgorithm& fsVerityHashAlgorithm)24 MerkleTree* FsVerityGenerator::GenerateMerkleTree(std::istream& inputStream, long size,
25     const FsVerityHashAlgorithm& fsVerityHashAlgorithm)
26 {
27     std::unique_ptr<MerkleTreeBuilder>builder = std::make_unique<MerkleTreeBuilder>(MerkleTreeBuilder());
28     return builder->GenerateMerkleTree(inputStream, size, fsVerityHashAlgorithm);
29 }
30 
GenerateFsVerityDigest(std::istream& inputStream, long size, long fsvTreeOffset)31 bool FsVerityGenerator::GenerateFsVerityDigest(std::istream& inputStream, long size, long fsvTreeOffset)
32 {
33     std::vector<int8_t> emptyVector;
34     MerkleTree* merkleTree = nullptr;
35     if (size == 0) {
36         merkleTree = new MerkleTree(emptyVector, emptyVector, FS_SHA256);
37     } else {
38         merkleTree = GenerateMerkleTree(inputStream, size, FS_SHA256);
39     }
40     if (merkleTree == nullptr) {
41         return false;
42     }
43     int flags = fsvTreeOffset == 0 ? 0 : FsVerityDescriptor::FLAG_STORE_MERKLE_TREE_OFFSET;
44     std::shared_ptr<MerkleTree> merkleTree_ptr(merkleTree);
45     // sign size is 0, cs version is 0
46     std::unique_ptr<FsVerityDescriptor::Builder> builder = std::make_unique<FsVerityDescriptor::Builder>();
47     builder->SetFileSize(size)
48         .SetHashAlgorithm(FS_SHA256.GetId())
49         .SetLog2BlockSize(LOG_2_OF_FSVERITY_HASH_PAGE_SIZE)
50         .SetSaltSize((uint8_t)GetSaltSize())
51         .SetSalt(salt)
52         .SetRawRootHash(merkleTree_ptr->rootHash)
53         .SetFlags(flags)
54         .SetMerkleTreeOffset(fsvTreeOffset);
55     std::vector<int8_t> fsVerityDescriptor;
56     builder->Build().GetByteForGenerateDigest(fsVerityDescriptor);
57     std::vector<int8_t> digest;
58     DigestUtils digestUtils(HASH_SHA256);
59     std::stringstream ss;
60     for (const auto& elem : fsVerityDescriptor) {
61         ss << elem;
62     }
63     digestUtils.AddData(ss.str());
64     std::string result = digestUtils.Result(DigestUtils::Type::BINARY);
65     for (int i = 0; i < result.size(); i++) {
66         digest.push_back(result[i]);
67     }
68     FsVerityDigest::GetFsVerityDigest(FS_SHA256.GetId(), digest, fsVerityDigest);
69     treeBytes = merkleTree_ptr->tree;
70     rootHash = merkleTree_ptr->rootHash;
71     return true;
72 }
73 } // namespace SignatureTools
74 } // namespace OHOS