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 "native_lib_info_segment.h"
16
17 namespace OHOS {
18 namespace SignatureTools {
19
NativeLibInfoSegment()20 NativeLibInfoSegment::NativeLibInfoSegment()
21 {
22 magic = MAGIC_NUM;
23 zeroPadding = std::vector<int8_t>(0);
24 fileNameListBlockSize = 0;
25 segmentSize = 0;
26 sectionNum = 0;
27 signInfoListBlockSize = 0;
28 }
29
NativeLibInfoSegment(int32_t magic,int32_t segmentSize,int32_t sectionNum,const std::vector<SignedFilePos> & signedFilePosList,const std::vector<std::string> & fileNameList,const std::vector<SignInfo> & signInfoList,const std::vector<int8_t> & zeroPadding)30 NativeLibInfoSegment::NativeLibInfoSegment(int32_t magic,
31 int32_t segmentSize,
32 int32_t sectionNum,
33 const std::vector<SignedFilePos>& signedFilePosList,
34 const std::vector<std::string>& fileNameList,
35 const std::vector<SignInfo>& signInfoList,
36 const std::vector<int8_t>& zeroPadding)
37 {
38 this->magic = magic;
39 this->segmentSize = segmentSize;
40 this->sectionNum = sectionNum;
41 this->signedFilePosList = signedFilePosList;
42 this->fileNameList = fileNameList;
43 this->signInfoList = signInfoList;
44 this->zeroPadding = zeroPadding;
45 fileNameListBlockSize = 0;
46 signInfoListBlockSize = 0;
47 }
48
SetSoInfoList(const std::vector<std::pair<std::string,SignInfo>> & soInfoList)49 void NativeLibInfoSegment::SetSoInfoList(const std::vector<std::pair<std::string, SignInfo>> &soInfoList)
50 {
51 this->soInfoList = soInfoList;
52 // Once map is set, update length, sectionNum as well
53 sectionNum = soInfoList.size();
54 // generate file name list and sign info list
55 GenerateList();
56 }
57
GetSectionNum()58 int32_t NativeLibInfoSegment::GetSectionNum()
59 {
60 return sectionNum;
61 }
62
GetFileNameList()63 std::vector<std::string>& NativeLibInfoSegment::GetFileNameList()
64 {
65 return fileNameList;
66 }
67
GetSignInfoList()68 std::vector<OHOS::SignatureTools::SignInfo>& NativeLibInfoSegment::GetSignInfoList()
69 {
70 return signInfoList;
71 }
72
Size()73 int32_t NativeLibInfoSegment::Size()
74 {
75 int blockSize = MAGIC_LENGTH_SECNUM_BYTES;
76 blockSize += signedFilePosList.size() * SIGNED_FILE_POS_SIZE;
77 blockSize += fileNameListBlockSize + zeroPadding.size() + signInfoListBlockSize;
78 return blockSize;
79 }
80
ToByteArray(std::vector<int8_t> & ret)81 void NativeLibInfoSegment::ToByteArray(std::vector<int8_t> &ret)
82 {
83 std::unique_ptr<ByteBuffer> bf = std::make_unique<ByteBuffer>(ByteBuffer(Size()));
84 std::vector<int8_t> empt(Size());
85 bf->PutData(empt.data(), empt.size());
86 bf->Clear();
87 bf->PutInt32(magic);
88 bf->PutInt32(segmentSize);
89 bf->PutInt32(sectionNum);
90 for (SignedFilePos &offsetAndSize : signedFilePosList) {
91 bf->PutInt32(offsetAndSize.GetFileNameOffset());
92 bf->PutInt32(offsetAndSize.GetFileNameSize());
93 bf->PutInt32(offsetAndSize.GetSignInfoOffset());
94 bf->PutInt32(offsetAndSize.GetSignInfoSize());
95 }
96 for (std::string &fileName : fileNameList) {
97 bf->PutData(fileName.c_str(), fileName.size() * sizeof(char));
98 }
99 bf->PutData(zeroPadding.data(), zeroPadding.size());
100 for (SignInfo &signInfo : signInfoList) {
101 std::vector<int8_t> signInfoArr;
102 signInfo.ToByteArray(signInfoArr);
103 bf->PutData(signInfoArr.data(), signInfoArr.size());
104 }
105 ret = std::vector<int8_t>(bf->GetBufferPtr(), bf->GetBufferPtr() + bf->GetPosition());
106 return;
107 }
108
FromByteArray(std::vector<int8_t> & bytes)109 NativeLibInfoSegment NativeLibInfoSegment::FromByteArray(std::vector<int8_t> &bytes)
110 {
111 std::unique_ptr<ByteBuffer> bf = std::make_unique<ByteBuffer>(ByteBuffer(bytes.size()));
112 bf->PutData(bytes.data(), bytes.size());
113 bf->Flip();
114 int32_t inMagic = 0;
115 int32_t inSegmentSize = 0;
116 int32_t inSectionNum = 0;
117 bool checkFlag = CheckBuffer(bf.get(), inMagic, inSegmentSize, inSectionNum);
118 if (!checkFlag) {
119 return NativeLibInfoSegment();
120 }
121 std::vector<SignedFilePos> inSignedFilePosList;
122 for (int i = 0; i < inSectionNum; i++) {
123 std::vector<int8_t> entry(SIGNED_FILE_POS_SIZE, 0);
124 bf->GetByte(entry.data(), entry.size());
125 inSignedFilePosList.push_back(SignedFilePos::FromByteArray(entry));
126 }
127 // parse file name list
128 std::vector<std::string> inFileNameList;
129 int fileNameListSize = 0;
130 for (SignedFilePos &pos : inSignedFilePosList) {
131 std::vector<char> fileNameBuffer(pos.GetFileNameSize(), 0);
132 fileNameListSize += pos.GetFileNameSize();
133 bf->SetPosition(pos.GetFileNameOffset());
134 bf->GetData(fileNameBuffer.data(), fileNameBuffer.size());
135 inFileNameList.push_back(std::string(fileNameBuffer.data(), fileNameBuffer.size()));
136 }
137 // parse zeroPadding
138 std::vector<int8_t> inZeroPadding((ALIGNMENT_FOR_SIGNINFO - fileNameListSize
139 % ALIGNMENT_FOR_SIGNINFO) % ALIGNMENT_FOR_SIGNINFO);
140 bf->GetByte(inZeroPadding.data(), inZeroPadding.size());
141 // parse sign info list
142 std::vector<OHOS::SignatureTools::SignInfo> inSignInfoList;
143 for (SignedFilePos &pos : inSignedFilePosList) {
144 if (pos.GetSignInfoOffset() % ALIGNMENT_FOR_SIGNINFO != 0) {
145 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
146 "The offset of signature information must be an integer multiple of 4");
147 return NativeLibInfoSegment();
148 }
149 std::vector<int8_t> signInfoBuffer(pos.GetSignInfoSize());
150 bf->SetPosition(pos.GetSignInfoOffset());
151 bf->GetByte(signInfoBuffer.data(), signInfoBuffer.size());
152 inSignInfoList.push_back(OHOS::SignatureTools::SignInfo::FromByteArray(signInfoBuffer));
153 }
154 return NativeLibInfoSegment(inMagic, inSegmentSize, inSectionNum, inSignedFilePosList,
155 inFileNameList, inSignInfoList, inZeroPadding);
156 }
157
CheckBuffer(ByteBuffer * bf,int32_t & inMagic,int32_t & inSegmentSize,int32_t & inSectionNum)158 bool NativeLibInfoSegment::CheckBuffer(ByteBuffer* bf, int32_t& inMagic, int32_t& inSegmentSize,
159 int32_t& inSectionNum)
160 {
161 bf->GetInt32(inMagic);
162 if (inMagic != MAGIC_NUM) {
163 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
164 "The magic number of NativeLibInfoSegment is incorrect.");
165 return false;
166 }
167 bf->GetInt32(inSegmentSize);
168 if (inSegmentSize < 0) {
169 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
170 "The segment size of NativeLibInfoSegment is incorrect.");
171 return false;
172 }
173 bf->GetInt32(inSectionNum);
174 if (inSectionNum < 0) {
175 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
176 "The section number of NativeLibInfoSegment is incorrect.");
177 return false;
178 }
179 return true;
180 }
181
GenerateList()182 void NativeLibInfoSegment::GenerateList()
183 {
184 // empty all before generate list
185 fileNameList.clear();
186 signInfoList.clear();
187 signedFilePosList.clear();
188 int fileNameOffset = 0;
189 int signInfoOffset = 0;
190 for (std::pair<std::string, SignInfo> &soInfo :soInfoList) {
191 std::string fileName = soInfo.first;
192 SignInfo& signInfo = soInfo.second;
193 int fileNameSizeInBytes = fileName.size() * sizeof(char);
194 int signInfoSizeInBytes = signInfo.GetSize() * sizeof(char);
195 fileNameList.push_back(fileName);
196 signInfoList.push_back(signInfo);
197 std::unique_ptr<SignedFilePos> posPtr = std::make_unique<SignedFilePos>(fileNameOffset,
198 fileNameSizeInBytes, signInfoOffset, signInfoSizeInBytes);
199 signedFilePosList.push_back(*posPtr.get());
200 // increase fileNameOffset and signInfoOffset
201 fileNameOffset += fileNameSizeInBytes;
202 signInfoOffset += signInfoSizeInBytes;
203 }
204 fileNameListBlockSize = fileNameOffset;
205 signInfoListBlockSize = signInfoOffset;
206 // alignment for signInfo
207 zeroPadding = std::vector<int8_t>((ALIGNMENT_FOR_SIGNINFO - fileNameListBlockSize
208 % ALIGNMENT_FOR_SIGNINFO) % ALIGNMENT_FOR_SIGNINFO);
209 // after fileNameList and signInfoList is generated, update segment size
210 segmentSize = Size();
211 // adjust file name and sign info offset base on segment start
212 int fileNameOffsetBase = MAGIC_LENGTH_SECNUM_BYTES + signedFilePosList.size() * SIGNED_FILE_POS_SIZE;
213 int signInfoOffsetBase = fileNameOffsetBase + fileNameListBlockSize;
214 for (SignedFilePos &pos : signedFilePosList) {
215 pos.IncreaseFileNameOffset(fileNameOffsetBase);
216 pos.IncreaseSignInfoOffset(signInfoOffsetBase + zeroPadding.size());
217 }
218 }
219
220 }
221 }
222