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 "code_sign_block.h"
16 #include "merkle_tree_extension.h"
17
18 namespace OHOS {
19 namespace SignatureTools {
20
CodeSignBlock()21 CodeSignBlock::CodeSignBlock()
22 {
23 }
24
~CodeSignBlock()25 CodeSignBlock::~CodeSignBlock()
26 {
27 }
28
AddOneMerkleTree(const std::string & key,const std::vector<int8_t> & merkleTree)29 void CodeSignBlock::AddOneMerkleTree(const std::string& key, const std::vector<int8_t>& merkleTree)
30 {
31 if (key.empty()) {
32 return;
33 }
34 if (merkleTreeMap.find(key) == merkleTreeMap.end()) {
35 if (merkleTree.empty()) {
36 merkleTreeMap.insert(std::make_pair(key, std::vector<int8_t>(0)));
37 } else {
38 merkleTreeMap.insert(std::make_pair(key, merkleTree));
39 }
40 }
41 }
42
GetOneMerkleTreeByFileName(const std::string & key)43 std::vector<int8_t> CodeSignBlock::GetOneMerkleTreeByFileName(const std::string& key)
44 {
45 if (key.empty()) {
46 return std::vector<int8_t>();
47 }
48 return merkleTreeMap[key];
49 }
50
SetCodeSignBlockFlag()51 void CodeSignBlock::SetCodeSignBlockFlag()
52 {
53 int flags = CodeSignBlockHeader::FLAG_MERKLE_TREE_INLINED;
54 if (nativeLibInfoSegment.GetSectionNum() != 0) {
55 flags |= CodeSignBlockHeader::FLAG_NATIVE_LIB_INCLUDED;
56 }
57 codeSignBlockHeader.SetFlags(flags);
58 }
59
SetSegmentNum()60 void CodeSignBlock::SetSegmentNum()
61 {
62 codeSignBlockHeader.SetSegmentNum(static_cast<int>(segmentHeaderList.size()));
63 }
64
AddToSegmentList(const SegmentHeader & sh)65 void CodeSignBlock::AddToSegmentList(const SegmentHeader& sh)
66 {
67 segmentHeaderList.push_back(sh);
68 }
69
GetSegmentHeaderList()70 std::vector<SegmentHeader>& CodeSignBlock::GetSegmentHeaderList()
71 {
72 return segmentHeaderList;
73 }
74
SetSegmentHeaders()75 void CodeSignBlock::SetSegmentHeaders()
76 {
77 // fs-verity info segment
78 SegmentHeader tempVar(SegmentHeader::CSB_FSVERITY_INFO_SEG, FsVerityInfoSegment::FS_VERITY_INFO_SEGMENT_SIZE);
79 segmentHeaderList.push_back(tempVar);
80 // hap info segment
81 SegmentHeader tempVar2(SegmentHeader::CSB_HAP_META_SEG, hapInfoSegment.GetSize());
82 segmentHeaderList.push_back(tempVar2);
83 // native lib info segment
84 SegmentHeader tempVar3(SegmentHeader::CSB_NATIVE_LIB_INFO_SEG, nativeLibInfoSegment.Size());
85 segmentHeaderList.push_back(tempVar3);
86 }
87
GetCodeSignBlockHeader()88 CodeSignBlockHeader& CodeSignBlock::GetCodeSignBlockHeader()
89 {
90 return codeSignBlockHeader;
91 }
92
SetCodeSignBlockHeader(const CodeSignBlockHeader & csbHeader)93 void CodeSignBlock::SetCodeSignBlockHeader(const CodeSignBlockHeader& csbHeader)
94 {
95 codeSignBlockHeader = csbHeader;
96 }
97
SetFsVerityInfoSegment(const FsVerityInfoSegment & fsVeritySeg)98 void CodeSignBlock::SetFsVerityInfoSegment(const FsVerityInfoSegment& fsVeritySeg)
99 {
100 fsVerityInfoSegment = fsVeritySeg;
101 }
102
GetHapInfoSegment()103 HapInfoSegment& CodeSignBlock::GetHapInfoSegment()
104 {
105 return hapInfoSegment;
106 }
107
SetHapInfoSegment(const HapInfoSegment & hapSeg)108 void CodeSignBlock::SetHapInfoSegment(const HapInfoSegment& hapSeg)
109 {
110 hapInfoSegment = hapSeg;
111 }
112
GetSoInfoSegment()113 NativeLibInfoSegment& CodeSignBlock::GetSoInfoSegment()
114 {
115 return nativeLibInfoSegment;
116 }
117
SetSoInfoSegment(const NativeLibInfoSegment & soSeg)118 void CodeSignBlock::SetSoInfoSegment(const NativeLibInfoSegment& soSeg)
119 {
120 nativeLibInfoSegment = soSeg;
121 }
122
ToByteArray(std::vector<int8_t> & ret)123 void CodeSignBlock::ToByteArray(std::vector<int8_t>& ret)
124 {
125 std::unique_ptr<ByteBuffer> bf = std::make_unique<ByteBuffer>
126 (ByteBuffer(codeSignBlockHeader.GetBlockSize()));
127 std::vector<int8_t> codeSignBlockHeaderVec;
128 codeSignBlockHeader.ToByteArray(codeSignBlockHeaderVec);
129 bf->PutData(codeSignBlockHeaderVec.data(), codeSignBlockHeaderVec.size());
130 for (auto &sh : segmentHeaderList) {
131 std::vector<int8_t> shVec;
132 sh.ToByteArray(shVec);
133 bf->PutData(shVec.data(), shVec.size());
134 }
135 bf->PutData(zeroPadding.data(), zeroPadding.size());
136 // Hap merkle tree
137 bf->PutData(merkleTreeMap["Hap"].data(), merkleTreeMap["Hap"].size());
138 std::vector<int8_t> fsVerityInfoSegmentVec;
139 fsVerityInfoSegment.ToByteArray(fsVerityInfoSegmentVec);
140 bf->PutData(fsVerityInfoSegmentVec.data(), fsVerityInfoSegmentVec.size());
141 std::vector<int8_t> hapInfoSegmentVec;
142 hapInfoSegment.ToByteArray(hapInfoSegmentVec);
143 bf->PutData(hapInfoSegmentVec.data(), hapInfoSegmentVec.size());
144 std::vector<int8_t> nativeLibInfoSegmentVec;
145 nativeLibInfoSegment.ToByteArray(nativeLibInfoSegmentVec);
146 bf->PutData(nativeLibInfoSegmentVec.data(), nativeLibInfoSegmentVec.size());
147
148 ret = std::vector<int8_t>(bf->GetBufferPtr(), bf->GetBufferPtr() + bf->GetPosition());
149 }
150
ComputeSegmentOffset()151 void CodeSignBlock::ComputeSegmentOffset()
152 {
153 // 1) the first segment is placed after merkle tree
154 int segmentOffset = CodeSignBlockHeader::Size()
155 + segmentHeaderList.size() * SegmentHeader::SEGMENT_HEADER_LENGTH
156 + zeroPadding.size() + GetOneMerkleTreeByFileName("Hap").size();
157 for (std::vector<SegmentHeader>::size_type i = 0; i < segmentHeaderList.size(); i++) {
158 segmentHeaderList[i].SetSegmentOffset(static_cast<int32_t>(segmentOffset));
159 segmentOffset += segmentHeaderList[i].GetSegmentSize();
160 }
161 }
162
ComputeMerkleTreeOffset(int64_t codeSignBlockOffset)163 int64_t CodeSignBlock::ComputeMerkleTreeOffset(int64_t codeSignBlockOffset)
164 {
165 int64_t sizeWithoutMerkleTree = CodeSignBlockHeader::Size()
166 + SEGMENT_HEADER_COUNT * SegmentHeader::SEGMENT_HEADER_LENGTH;
167 // add code sign block offset while computing align position for merkle tree
168 int64_t residual = (codeSignBlockOffset + sizeWithoutMerkleTree) % PAGE_SIZE_4K;
169 if (residual == 0) {
170 zeroPadding = std::vector<int8_t>(0);
171 } else {
172 zeroPadding = std::vector<int8_t>(static_cast<int>(PAGE_SIZE_4K - residual));
173 }
174 return codeSignBlockOffset + sizeWithoutMerkleTree + zeroPadding.size();
175 }
176
GenerateCodeSignBlockByte(int64_t fsvTreeOffset,std::vector<int8_t> & ret)177 void CodeSignBlock::GenerateCodeSignBlockByte(int64_t fsvTreeOffset, std::vector<int8_t>& ret)
178 {
179 // 1) compute overall block size without merkle tree
180 int64_t csbSize = CodeSignBlockHeader::Size()
181 + static_cast<int64_t>(segmentHeaderList.size()) * SegmentHeader::SEGMENT_HEADER_LENGTH
182 + zeroPadding.size()
183 + GetOneMerkleTreeByFileName("Hap").size()
184 + fsVerityInfoSegment.Size()
185 + hapInfoSegment.GetSize()
186 + nativeLibInfoSegment.Size();
187 Extension* ext = hapInfoSegment.GetSignInfo().GetExtensionByType(MerkleTreeExtension::MERKLE_TREE_INLINED);
188 if (ext != nullptr) {
189 MerkleTreeExtension* merkleTreeExtension = static_cast<MerkleTreeExtension*>(ext);
190 merkleTreeExtension->SetMerkleTreeOffset(fsvTreeOffset);
191 }
192 codeSignBlockHeader.SetBlockSize(csbSize);
193 // 2) generate byte array of complete code sign block
194 ToByteArray(ret);
195 }
196
197 }
198 }