• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }