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
16#include "elf_sign_block.h"
17
18namespace OHOS {
19namespace SignatureTools {
20
21ElfSignBlock::ElfSignBlock()
22{
23    type = MERKLE_TREE_INLINED;
24}
25
26ElfSignBlock::ElfSignBlock(int32_t paddingSize, const std::vector<int8_t> &merkleTreeData,
27                           const FsVerityDescriptorWithSign &descriptorWithSign)
28{
29    std::vector<int8_t> inMerkleTreeData;
30    if (!merkleTreeData.empty()) {
31        inMerkleTreeData = merkleTreeData;
32    }
33    treeLength = paddingSize + inMerkleTreeData.size();
34    merkleTreeWithPadding.resize(treeLength);
35    std::copy(inMerkleTreeData.begin(), inMerkleTreeData.end(), merkleTreeWithPadding.begin() + paddingSize);
36    this->descriptorWithSign = descriptorWithSign;
37}
38
39int32_t ElfSignBlock::Size()
40{
41    int tmpVariable = 2;
42    return FsVerityDescriptorWithSign::INTEGER_BYTES * tmpVariable
43        + merkleTreeWithPadding.size() + descriptorWithSign.Size();
44}
45
46std::vector<int8_t>& ElfSignBlock::GetMerkleTreeWithPadding()
47{
48    return merkleTreeWithPadding;
49}
50
51int64_t ElfSignBlock::GetDataSize()
52{
53    return descriptorWithSign.GetFsVerityDescriptor().GetFileSize();
54}
55
56int64_t ElfSignBlock::GetTreeOffset()
57{
58    return descriptorWithSign.GetFsVerityDescriptor().GetMerkleTreeOffset();
59}
60
61std::vector<int8_t>& ElfSignBlock::GetSignature()
62{
63    return descriptorWithSign.GetSignature();
64}
65
66void ElfSignBlock::ToByteArray(std::vector<int8_t>& ret)
67{
68    std::unique_ptr<ByteBuffer> bf = std::make_unique<ByteBuffer>(Size());
69    bf->PutInt32(type);
70    bf->PutInt32(merkleTreeWithPadding.size());
71    bf->PutData(merkleTreeWithPadding.data(), merkleTreeWithPadding.size());
72    std::vector<int8_t> descriptorWithSignArr;
73    descriptorWithSign.ToByteArray(descriptorWithSignArr);
74    bf->PutData(descriptorWithSignArr.data(), descriptorWithSignArr.size());
75    ret = std::vector<int8_t>(bf->GetBufferPtr(), bf->GetBufferPtr() + bf->GetLimit());
76}
77
78bool ElfSignBlock::FromByteArray(std::vector<int8_t>& bytes, ElfSignBlock& elfSignBlock)
79{
80    std::unique_ptr<ByteBuffer> bf = std::make_unique<ByteBuffer>(bytes.size());
81    bf->PutData(bytes.data(), bytes.size());
82    bf->Flip();
83    int32_t inTreeType = 0;
84    bf->GetInt32(inTreeType);
85    if (MERKLE_TREE_INLINED != inTreeType) {
86        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
87                            "The merkle tree type of elf signature block is incorrect");
88        return false;
89    }
90    int32_t inTreeLength = 0;
91    bf->GetInt32(inTreeLength);
92    std::vector<int8_t> treeWithPadding(inTreeLength);
93    bf->GetByte(treeWithPadding.data(), treeWithPadding.size());
94    int32_t inFsdType = 0;
95    bf->GetInt32(inFsdType);
96    if (FsVerityDescriptor::FS_VERITY_DESCRIPTOR_TYPE != inFsdType) {
97        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
98                            "The FS descriptor type of elf signature block is incorrect");
99        return false;
100    }
101    int32_t inFsdLength = 0;
102    int tmpVariable = 2;
103    bf->GetInt32(inFsdLength);
104    if (bytes.size() != FsVerityDescriptorWithSign::INTEGER_BYTES * tmpVariable + inTreeLength +
105        FsVerityDescriptorWithSign::INTEGER_BYTES * tmpVariable + inFsdLength) {
106        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
107                            "The signature length of the elf signature block is incorrect");
108        return false;
109    }
110    std::vector<int8_t> fsdArray(FsVerityDescriptor::DESCRIPTOR_SIZE);
111    bf->GetByte(fsdArray.data(), fsdArray.size());
112    FsVerityDescriptor fsd = FsVerityDescriptor::FromByteArray(fsdArray);
113    if (inFsdLength != fsd.GetSignSize() + FsVerityDescriptor::DESCRIPTOR_SIZE) {
114        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
115                            "The signed size of the elf signature block is incorrect");
116        return false;
117    }
118    std::vector<int8_t> inSignature(inFsdLength - FsVerityDescriptor::DESCRIPTOR_SIZE);
119    bf->GetByte(inSignature.data(), inSignature.size());
120    FsVerityDescriptorWithSign fsVerityDescriptorWithSign(inFsdType, inFsdLength, fsd, inSignature);
121    elfSignBlock.type = inTreeType;
122    elfSignBlock.treeLength = inTreeLength;
123    elfSignBlock.merkleTreeWithPadding = treeWithPadding;
124    elfSignBlock.descriptorWithSign = fsVerityDescriptorWithSign;
125    return true;
126}
127
128int32_t ElfSignBlock::ComputeMerkleTreePaddingLength(int64_t signBlockOffset)
129{
130    int tmpVariable = 2;
131    return (int32_t)(PAGE_SIZE_4K - (signBlockOffset + FsVerityDescriptorWithSign::INTEGER_BYTES * tmpVariable)
132                     % PAGE_SIZE_4K) % PAGE_SIZE_4K;
133}
134
135}
136}