1 /*
2 * Copyright (c) 2021 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 "pkg_upgradefile.h"
16 #include <cerrno>
17 #include <cstdio>
18 #include <cstring>
19 #include <ctime>
20 #include <limits>
21 #include <memory>
22 #include "pkg_lz4file.h"
23 #include "pkg_manager.h"
24 #include "pkg_pkgfile.h"
25 #include "pkg_stream.h"
26 #include "pkg_utils.h"
27 #include "pkg_zipfile.h"
28 #include "securec.h"
29
30 #define CHECK_TLV(tlv, tlvType, len, fileLen) \
31 do { \
32 if (!((tlv)->length < (fileLen) && (tlv)->length >= (len) && (tlv)->type == (tlvType) && \
33 ((tlv)->length + sizeof(PkgTlv)) < (fileLen))) { \
34 PKG_LOGE("Invalid tlv type: %d length %u ", tlvType, ((tlv)->length)); \
35 return PKG_INVALID_FILE; \
36 } \
37 } while (0)
38
39 using namespace std;
40
41 namespace hpackage {
42 constexpr int32_t UPGRADE_FILE_HEADER_LEN = 3 * sizeof(PkgTlv) + sizeof(UpgradePkgHeader) + sizeof(UpgradePkgTime);
43 constexpr int32_t UPGRADE_RESERVE_LEN = 16;
44 constexpr int16_t TLV_TYPE_FOR_SHA256 = 0x0001;
45 constexpr int16_t TLV_TYPE_FOR_SHA384 = 0x0011;
46 constexpr size_t BUFFER_SIZE = 4 * 1024 * 1024;
47
Init(const PkgManager::FileInfoPtr fileInfo,PkgStreamPtr inStream)48 int32_t UpgradeFileEntry::Init(const PkgManager::FileInfoPtr fileInfo, PkgStreamPtr inStream)
49 {
50 int32_t ret = PkgEntry::Init(&fileInfo_.fileInfo, fileInfo, inStream);
51 PKG_CHECK(ret == PKG_SUCCESS, return PKG_INVALID_PARAM, "Fail to check input param");
52 ComponentInfo *info = (ComponentInfo *)fileInfo;
53 if (info != nullptr) {
54 fileInfo_.version = info->version;
55 fileInfo_.id = info->id;
56 fileInfo_.resType = info->resType;
57 fileInfo_.type = info->type;
58 fileInfo_.compFlags = info->compFlags;
59 fileInfo_.originalSize = info->originalSize;
60 PKG_CHECK(!memcpy_s(fileInfo_.digest, sizeof(fileInfo_.digest), info->digest, sizeof(info->digest)),
61 return PKG_NONE_MEMORY, "UpgradeFileEntry memcpy failed");
62 }
63 return PKG_SUCCESS;
64 }
65
GetUpgradeSignatureLen() const66 size_t UpgradePkgFile::GetUpgradeSignatureLen() const
67 {
68 return SIGN_SHA256_LEN + SIGN_SHA384_LEN;
69 }
70
GetDigestLen() const71 size_t UpgradePkgFile::GetDigestLen() const
72 {
73 return DigestAlgorithm::GetDigestLen(pkgInfo_.pkgInfo.digestMethod);
74 }
75
AddEntry(const PkgManager::FileInfoPtr file,const PkgStreamPtr inStream)76 int32_t UpgradePkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStreamPtr inStream)
77 {
78 PKG_CHECK(file != nullptr && inStream != nullptr, return PKG_INVALID_PARAM, "Fail to check input param");
79 PKG_CHECK(CheckState({PKG_FILE_STATE_IDLE, PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_WORKING),
80 return PKG_INVALID_STATE, "error state curr %d ", state_);
81 PKG_CHECK(pkgEntryMapId_.size() < pkgInfo_.pkgInfo.entryCount, return PKG_INVALID_PARAM,
82 "More entry for and for %s %zu", file->identity.c_str(), pkgEntryMapId_.size());
83 PKG_LOGI("Add file %s to package", file->identity.c_str());
84
85 size_t compDataLen = 0;
86 for (auto &it : pkgEntryMapId_) {
87 compDataLen += (*it.second).GetFileInfo()->packedSize;
88 }
89
90 UpgradeFileEntry *entry = static_cast<UpgradeFileEntry *>(AddPkgEntry(file->identity));
91 PKG_CHECK(entry != nullptr, return PKG_NONE_MEMORY, "Fail create pkg node for %s", file->identity.c_str());
92 int32_t ret = entry->Init(file, inStream);
93 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail init entry for %s", file->identity.c_str());
94
95 size_t dataOffset = UPGRADE_FILE_HEADER_LEN + pkgInfo_.pkgInfo.entryCount * sizeof(UpgradeCompInfo);
96 dataOffset += UPGRADE_RESERVE_LEN + GetUpgradeSignatureLen();
97 dataOffset += compDataLen;
98 size_t encodeLen = 0;
99 ret = entry->Pack(inStream, dataOffset, encodeLen);
100 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail Pack for %s", file->identity.c_str());
101 packedFileSize_ += encodeLen;
102
103 size_t offset = UPGRADE_FILE_HEADER_LEN + (pkgEntryMapId_.size() - 1) * sizeof(UpgradeCompInfo);
104 ret = entry->EncodeHeader(inStream, offset, encodeLen);
105 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail encode header for %s", file->identity.c_str());
106
107 PKG_LOGI("Header offset:%zu data offset:%zu packedFileSize: %zu", offset, dataOffset, packedFileSize_);
108 return PKG_SUCCESS;
109 }
110
SavePackage(size_t & signOffset)111 int32_t UpgradePkgFile::SavePackage(size_t &signOffset)
112 {
113 PKG_LOGI("SavePackage %s", pkgStream_->GetFileName().c_str());
114 PKG_CHECK(CheckState({PKG_FILE_STATE_WORKING}, PKG_FILE_STATE_CLOSE),
115 return PKG_INVALID_STATE, "error state curr %d ", state_);
116 // Allocate buffer size with max possible size
117 size_t buffSize = GetUpgradeSignatureLen() + UPGRADE_RESERVE_LEN;
118 buffSize = ((UPGRADE_FILE_HEADER_LEN > buffSize) ? UPGRADE_FILE_HEADER_LEN : buffSize);
119 std::vector<uint8_t> buffer(buffSize);
120
121 size_t offset = 0;
122 // Package header information
123 WriteLE16(buffer.data(), GetPackageTlvType()); // Type is 1 for package header in TLV format
124 WriteLE16(buffer.data() + sizeof(uint16_t), sizeof(UpgradePkgHeader));
125 offset += sizeof(PkgTlv);
126 UpgradePkgHeader *header = reinterpret_cast<UpgradePkgHeader *>(buffer.data() + offset);
127 header->pkgInfoLength = sizeof(PkgTlv) + sizeof(PkgTlv) + sizeof(PkgTlv) + sizeof(UpgradePkgHeader) +
128 sizeof(UpgradePkgTime) + pkgInfo_.pkgInfo.entryCount * sizeof(UpgradeCompInfo) + UPGRADE_RESERVE_LEN;
129 WriteLE32(reinterpret_cast<uint8_t *>(&header->updateFileVersion), pkgInfo_.updateFileVersion);
130 int32_t ret = memcpy_s(header->softwareVersion, sizeof(header->softwareVersion), pkgInfo_.softwareVersion.data(),
131 pkgInfo_.softwareVersion.size());
132 PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret:%d", pkgStream_->GetFileName().c_str(), ret);
133 ret = memcpy_s(header->productUpdateId, sizeof(header->productUpdateId), pkgInfo_.productUpdateId.data(),
134 pkgInfo_.productUpdateId.size());
135 PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret:%d", pkgStream_->GetFileName().c_str(), ret);
136 offset += sizeof(UpgradePkgHeader);
137 // 时间tlv
138 WriteLE16(buffer.data() + offset, 0x02); // Type is 2 for time in TLV format
139 WriteLE16(buffer.data() + offset + sizeof(uint16_t), sizeof(UpgradePkgTime));
140 offset += sizeof(PkgTlv);
141 UpgradePkgTime *time = reinterpret_cast<UpgradePkgTime *>(buffer.data() + offset);
142 ret = memcpy_s(time->date, sizeof(time->date), pkgInfo_.date.data(), pkgInfo_.date.size());
143 PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret:%d", pkgStream_->GetFileName().c_str(), ret);
144 ret = memcpy_s(time->time, sizeof(time->time), pkgInfo_.time.data(), pkgInfo_.time.size());
145 PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret:%d", pkgStream_->GetFileName().c_str(), ret);
146 offset += sizeof(UpgradePkgTime);
147 // 组件的tlv
148 WriteLE16(buffer.data() + offset, 0x05); // Type is 5 for component in TLV format
149 WriteLE16(buffer.data() + offset + sizeof(uint16_t), pkgInfo_.pkgInfo.entryCount * sizeof(UpgradeCompInfo));
150 offset += sizeof(PkgTlv);
151 ret = pkgStream_->Write(buffer, UPGRADE_FILE_HEADER_LEN, 0);
152 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail write upgrade file header for %s ret:%d",
153 pkgStream_->GetFileName().c_str(), ret);
154
155 // Clear buffer and save signature information
156 offset += pkgInfo_.pkgInfo.entryCount * sizeof(UpgradeCompInfo);
157 signOffset = offset + UPGRADE_RESERVE_LEN;
158
159 buffer.assign(buffer.capacity(), 0);
160 size_t nameLen = 0;
161 ret = PkgFile::ConvertStringToBuffer(pkgInfo_.descriptPackageId, {buffer.data(), UPGRADE_RESERVE_LEN}, nameLen);
162 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail write descriptPackageId");
163 ret = pkgStream_->Write(buffer, GetUpgradeSignatureLen() + UPGRADE_RESERVE_LEN, offset);
164 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail write sign for %s", pkgStream_->GetFileName().c_str());
165 PKG_LOGI("SavePackage success file length: %zu signOffset %zu", pkgStream_->GetFileLength(), signOffset);
166 pkgStream_->Flush(offset);
167 return PKG_SUCCESS;
168 }
169
LoadPackage(std::vector<std::string> & fileNames,VerifyFunction verifier)170 int32_t UpgradePkgFile::LoadPackage(std::vector<std::string> &fileNames, VerifyFunction verifier)
171 {
172 PKG_CHECK(verifier != nullptr, return PKG_INVALID_SIGNATURE, "Check verifier nullptr");
173 PKG_CHECK(CheckState({PKG_FILE_STATE_IDLE}, PKG_FILE_STATE_WORKING),
174 return PKG_INVALID_STATE, "error state curr %d ", state_);
175 PKG_LOGI("LoadPackage %s ", pkgStream_->GetFileName().c_str());
176 size_t fileLen = pkgStream_->GetFileLength();
177 // Allocate buffer with smallest package size
178 size_t buffSize = UPGRADE_FILE_HEADER_LEN + sizeof(UpgradeCompInfo) +
179 GetUpgradeSignatureLen() + UPGRADE_RESERVE_LEN;
180 PKG_CHECK(fileLen > 0 && fileLen <= static_cast<size_t>(0xffffffff) && fileLen >= buffSize,
181 return PKG_INVALID_FILE, "Invalid file %s fileLen:%zu ", pkgStream_->GetFileName().c_str(), fileLen);
182
183 DigestAlgorithm::DigestAlgorithmPtr algorithm = nullptr;
184 // Parse header
185 PkgBuffer buffer(buffSize);
186 size_t parsedLen = 0;
187 int32_t ret = ReadUpgradePkgHeader(buffer, parsedLen, algorithm);
188 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Decode header fail %d", ret);
189
190 ret = ReadComponents(buffer, parsedLen, algorithm, fileNames);
191 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Decode components fail %d", ret);
192 PKG_CHECK(parsedLen + UPGRADE_RESERVE_LEN + GetUpgradeSignatureLen() < fileLen,
193 return ret, "Decode components fail %d", ret);
194
195 // Read signature information
196 size_t readBytes = 0;
197 ret = pkgStream_->Read(buffer, parsedLen, GetUpgradeSignatureLen() + UPGRADE_RESERVE_LEN, readBytes);
198 PKG_CHECK(ret == PKG_SUCCESS, return ret, "read sign data fail");
199 PkgFile::ConvertBufferToString(pkgInfo_.descriptPackageId, {buffer.buffer, UPGRADE_RESERVE_LEN});
200 std::vector<uint8_t> signData;
201 if (pkgInfo_.pkgInfo.digestMethod == PKG_DIGEST_TYPE_SHA384) {
202 signData.resize(SIGN_SHA384_LEN);
203 ret = memcpy_s(signData.data(), signData.size(),
204 buffer.buffer + UPGRADE_RESERVE_LEN + SIGN_SHA256_LEN, SIGN_SHA384_LEN);
205 } else {
206 signData.resize(SIGN_SHA256_LEN);
207 ret = memcpy_s(signData.data(), signData.size(), buffer.buffer + UPGRADE_RESERVE_LEN, SIGN_SHA256_LEN);
208 }
209 PKG_CHECK(ret == PKG_SUCCESS, return ret, "memcpy sign data fail");
210 ret = memset_s(buffer.buffer + UPGRADE_RESERVE_LEN, buffer.length, 0, GetUpgradeSignatureLen());
211 PKG_CHECK(ret == 0, return ret, "memset buff fail");
212 algorithm->Update(buffer, UPGRADE_RESERVE_LEN + GetUpgradeSignatureLen());
213 parsedLen += UPGRADE_RESERVE_LEN + GetUpgradeSignatureLen();
214
215 // Calculate digest and verify
216 return Verify(parsedLen, algorithm, verifier, signData);
217 }
218
Verify(size_t start,DigestAlgorithm::DigestAlgorithmPtr algorithm,VerifyFunction verifier,const std::vector<uint8_t> & signData)219 int32_t UpgradePkgFile::Verify(size_t start, DigestAlgorithm::DigestAlgorithmPtr algorithm,
220 VerifyFunction verifier, const std::vector<uint8_t> &signData)
221 {
222 int ret = 0;
223 size_t buffSize = BUFFER_SIZE;
224 size_t offset = start;
225 size_t readBytes = 0;
226 PkgBuffer buffer(buffSize);
227
228 while (offset + readBytes < pkgStream_->GetFileLength()) {
229 offset += readBytes;
230 readBytes = 0;
231 size_t remainBytes = pkgStream_->GetFileLength() - offset;
232 remainBytes = ((remainBytes > buffSize) ? buffSize : remainBytes);
233 ret = pkgStream_->Read(buffer, offset, remainBytes, readBytes);
234 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to read data ");
235 algorithm->Update(buffer, readBytes);
236 pkgManager_->PostDecodeProgress(POST_TYPE_VERIFY_PKG, remainBytes, nullptr);
237 }
238
239 PkgBuffer digest(GetDigestLen());
240 algorithm->Final(digest);
241 ret = verifier(&pkgInfo_.pkgInfo, digest.data, signData);
242 PKG_CHECK(ret == 0, return PKG_INVALID_SIGNATURE, "Fail to verifier signature");
243 return 0;
244 }
245
ReadComponents(const PkgBuffer & buffer,size_t & parsedLen,DigestAlgorithm::DigestAlgorithmPtr algorithm,std::vector<std::string> & fileNames)246 int32_t UpgradePkgFile::ReadComponents(const PkgBuffer &buffer, size_t &parsedLen,
247 DigestAlgorithm::DigestAlgorithmPtr algorithm, std::vector<std::string> &fileNames)
248 {
249 size_t fileLen = pkgStream_->GetFileLength();
250 size_t readLen = 0;
251 int32_t ret = pkgStream_->Read(buffer, parsedLen, buffer.length, readLen);
252 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Read component fail");
253 PkgTlv tlv;
254 tlv.type = ReadLE16(buffer.buffer);
255 tlv.length = ReadLE16(buffer.buffer + sizeof(uint16_t));
256 CHECK_TLV(&tlv, 5, sizeof(UpgradeCompInfo), fileLen); // component type is 5
257 algorithm->Update(buffer, sizeof(PkgTlv)); // tlv generate digest
258
259 parsedLen += sizeof(PkgTlv);
260 size_t dataOffset = parsedLen + tlv.length + GetUpgradeSignatureLen() + UPGRADE_RESERVE_LEN;
261 size_t srcOffset = 0;
262 size_t currLen = sizeof(PkgTlv);
263 while (srcOffset < tlv.length) {
264 if (currLen + sizeof(UpgradeCompInfo) > readLen) {
265 readLen = 0;
266 ret = pkgStream_->Read(buffer, parsedLen + srcOffset, buffer.length, readLen);
267 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to read data");
268 currLen = 0;
269 }
270
271 UpgradeFileEntry *entry = new UpgradeFileEntry(this, nodeId_++);
272 PKG_CHECK(entry != nullptr, return PKG_NONE_MEMORY, "Fail create upgrade node for %s",
273 pkgStream_->GetFileName().c_str());
274
275 // Extract header information from file
276 size_t decodeLen = 0;
277 PkgBuffer headerBuff(buffer.buffer + currLen, readLen - currLen);
278 ret = entry->DecodeHeader(headerBuff, parsedLen + srcOffset, dataOffset, decodeLen);
279 PKG_CHECK(ret == PKG_SUCCESS, delete entry; return ret, "Fail to decode header");
280
281 // Save entry
282 pkgEntryMapId_.insert(pair<uint32_t, PkgEntryPtr>(entry->GetNodeId(), entry));
283 pkgEntryMapFileName_.insert(std::pair<std::string, PkgEntryPtr>(entry->GetFileName(), entry));
284 fileNames.push_back(entry->GetFileName());
285
286 PkgBuffer signBuffer(buffer.buffer + currLen, decodeLen);
287 algorithm->Update(signBuffer, decodeLen); // Generate digest for components
288
289 currLen += decodeLen;
290 srcOffset += decodeLen;
291 PKG_CHECK(entry->GetFileInfo() != nullptr, delete entry; return PKG_INVALID_FILE, "Failed to get file info");
292 dataOffset += entry->GetFileInfo()->packedSize;
293 pkgInfo_.pkgInfo.entryCount++;
294 PKG_LOGI("Component packedSize %zu unpackedSize %zu %s", entry->GetFileInfo()->packedSize,
295 entry->GetFileInfo()->unpackedSize, entry->GetFileInfo()->identity.c_str());
296 }
297 parsedLen += srcOffset;
298 return PKG_SUCCESS;
299 }
300
ReadUpgradePkgHeader(const PkgBuffer & buffer,size_t & realLen,DigestAlgorithm::DigestAlgorithmPtr & algorithm)301 int32_t UpgradePkgFile::ReadUpgradePkgHeader(const PkgBuffer &buffer, size_t &realLen,
302 DigestAlgorithm::DigestAlgorithmPtr &algorithm)
303 {
304 size_t fileLen = pkgStream_->GetFileLength();
305 size_t readLen = 0;
306 size_t currLen = 0;
307 int32_t ret = pkgStream_->Read(buffer, 0, buffer.length, readLen);
308 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to read header");
309 pkgInfo_.pkgInfo.pkgType = PkgFile::PKG_TYPE_UPGRADE;
310 pkgInfo_.pkgInfo.signMethod = PKG_SIGN_METHOD_RSA;
311 pkgInfo_.pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256;
312
313 PkgTlv tlv;
314 tlv.type = ReadLE16(buffer.buffer);
315 tlv.length = ReadLE16(buffer.buffer + sizeof(uint16_t));
316 if (tlv.type == TLV_TYPE_FOR_SHA384) {
317 pkgInfo_.pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA384;
318 }
319
320 // Header information
321 currLen = sizeof(PkgTlv);
322 UpgradePkgHeader *header = reinterpret_cast<UpgradePkgHeader *>(buffer.buffer + currLen);
323 pkgInfo_.updateFileVersion = ReadLE32(buffer.buffer + currLen + offsetof(UpgradePkgHeader, updateFileVersion));
324 PkgFile::ConvertBufferToString(pkgInfo_.softwareVersion, {header->softwareVersion,
325 sizeof(header->softwareVersion)});
326 PkgFile::ConvertBufferToString(pkgInfo_.productUpdateId, {header->productUpdateId,
327 sizeof(header->productUpdateId)});
328
329 algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(pkgInfo_.pkgInfo.digestMethod);
330 PKG_CHECK(algorithm != nullptr, return PKG_NOT_EXIST_ALGORITHM,
331 "Invalid file %s", pkgStream_->GetFileName().c_str());
332 algorithm->Init();
333
334 if (currLen + tlv.length >= readLen) { // Extra TLV information, read it.
335 realLen = currLen + tlv.length;
336 algorithm->Update(buffer, realLen);
337 ret = pkgStream_->Read(buffer, realLen, buffer.length, readLen);
338 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to read header");
339 currLen = 0;
340 } else {
341 currLen += tlv.length;
342 }
343
344 // Time information
345 tlv.type = ReadLE16(buffer.buffer + currLen);
346 tlv.length = ReadLE16(buffer.buffer + currLen + sizeof(uint16_t));
347 CHECK_TLV(&tlv, sizeof(uint16_t), sizeof(UpgradePkgTime), fileLen);
348 currLen += sizeof(PkgTlv);
349 UpgradePkgTime *time = reinterpret_cast<UpgradePkgTime *>(buffer.buffer + currLen);
350 PkgFile::ConvertBufferToString(pkgInfo_.date, {time->date, sizeof(time->date)});
351 PkgFile::ConvertBufferToString(pkgInfo_.time, {time->time, sizeof(time->time)});
352 currLen += tlv.length;
353 realLen += currLen;
354
355 // Parser header to get compressional algorithm
356 algorithm->Update(buffer, currLen); // Generate digest
357 return PKG_SUCCESS;
358 }
359
EncodeHeader(PkgStreamPtr inStream,size_t startOffset,size_t & encodeLen)360 int32_t UpgradeFileEntry::EncodeHeader(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen)
361 {
362 PkgStreamPtr outStream = pkgFile_->GetPkgStream();
363 PKG_CHECK(outStream != nullptr && inStream != nullptr, return PKG_INVALID_PARAM,
364 "outStream or inStream null for %s", fileName_.c_str());
365
366 UpgradeCompInfo comp;
367 PKG_CHECK(!memset_s(&comp, sizeof(comp), 0, sizeof(comp)),
368 return PKG_NONE_MEMORY, "UpgradeFileEntry memset_s failed");
369
370 size_t len = 0;
371 int32_t ret = PkgFile::ConvertStringToBuffer(
372 fileInfo_.fileInfo.identity, {comp.address, sizeof(comp.address)}, len);
373 ret |= PkgFile::ConvertStringToBuffer(fileInfo_.version, {comp.version, sizeof(comp.version)}, len);
374 PKG_CHECK(ret == PKG_SUCCESS, return PKG_INVALID_PARAM, "outStream or inStream null for %s", fileName_.c_str());
375
376 ret = memcpy_s(comp.digest, sizeof(comp.digest), fileInfo_.digest, sizeof(fileInfo_.digest));
377 PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s ret:%d", ret);
378 WriteLE32(reinterpret_cast<uint8_t *>(&comp.size), fileInfo_.fileInfo.unpackedSize);
379 WriteLE16(reinterpret_cast<uint8_t *>(&comp.id), fileInfo_.id);
380 WriteLE32(reinterpret_cast<uint8_t *>(&comp.originalSize), fileInfo_.originalSize);
381 comp.resType = fileInfo_.resType;
382 comp.flags = fileInfo_.compFlags;
383 comp.type = fileInfo_.type;
384
385 headerOffset_ = startOffset;
386 PkgBuffer buffer(reinterpret_cast<uint8_t *>(&comp), sizeof(comp));
387 ret = outStream->Write(buffer, sizeof(comp), startOffset);
388 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail write header for %s", fileName_.c_str());
389 encodeLen = sizeof(UpgradeCompInfo);
390
391 PKG_LOGI("EncodeHeader startOffset: %zu %zu packedSize:%zu %zu ", headerOffset_, dataOffset_,
392 fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize);
393 return PKG_SUCCESS;
394 }
395
Pack(PkgStreamPtr inStream,size_t startOffset,size_t & encodeLen)396 int32_t UpgradeFileEntry::Pack(PkgStreamPtr inStream, size_t startOffset, size_t &encodeLen)
397 {
398 PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo);
399 PkgStreamPtr outStream = pkgFile_->GetPkgStream();
400 PKG_CHECK(algorithm != nullptr && outStream != nullptr && inStream != nullptr, return PKG_INVALID_PARAM,
401 "outStream or inStream null for %s", fileName_.c_str());
402
403 PkgAlgorithmContext context = {
404 {0, startOffset},
405 {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize},
406 0, fileInfo_.fileInfo.digestMethod
407 };
408 PKG_CHECK(!memcpy_s(context.digest, sizeof(context.digest), fileInfo_.digest, sizeof(fileInfo_.digest)),
409 return PKG_NONE_MEMORY, "UpgradeFileEntry pack memcpy failed");
410 int32_t ret = algorithm->Pack(inStream, outStream, context);
411 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail Compress for %s", fileName_.c_str());
412
413 // Fill digest and compressed size of file
414 PKG_CHECK(!memcpy_s(fileInfo_.digest, sizeof(fileInfo_.digest), context.digest, sizeof(context.digest)),
415 return PKG_NONE_MEMORY, "UpgradeFileEntry pack memcpy failed");
416 fileInfo_.fileInfo.packedSize = context.packedSize;
417 dataOffset_ = startOffset;
418 encodeLen = fileInfo_.fileInfo.packedSize;
419 PKG_LOGI("Pack start:%zu unpackSize:%zu packSize:%zu", startOffset, fileInfo_.fileInfo.unpackedSize,
420 fileInfo_.fileInfo.packedSize);
421 return PKG_SUCCESS;
422 }
423
DecodeHeader(const PkgBuffer & buffer,size_t headerOffset,size_t dataOffset,size_t & decodeLen)424 int32_t UpgradeFileEntry::DecodeHeader(const PkgBuffer &buffer, size_t headerOffset, size_t dataOffset,
425 size_t &decodeLen)
426 {
427 PkgStreamPtr inStream = pkgFile_->GetPkgStream();
428 PKG_CHECK(inStream != nullptr, return PKG_INVALID_PARAM, "outStream or inStream null for %s", fileName_.c_str());
429 PKG_CHECK(buffer.length >= sizeof(UpgradeCompInfo),
430 return PKG_INVALID_PKG_FORMAT, "Fail to check buffer %zu", buffer.length);
431
432 UpgradeCompInfo *info = reinterpret_cast<UpgradeCompInfo *>(buffer.buffer);
433 fileInfo_.fileInfo.packedSize = ReadLE32(buffer.buffer + offsetof(UpgradeCompInfo, size));
434 fileInfo_.fileInfo.unpackedSize = fileInfo_.fileInfo.packedSize;
435 fileInfo_.originalSize = ReadLE32(buffer.buffer + offsetof(UpgradeCompInfo, originalSize));
436 fileInfo_.fileInfo.packMethod = PKG_COMPRESS_METHOD_NONE;
437 fileInfo_.fileInfo.digestMethod = PKG_DIGEST_TYPE_NONE;
438 int32_t ret = memcpy_s(fileInfo_.digest, sizeof(fileInfo_.digest), info->digest, sizeof(info->digest));
439 PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s ret:%d", ret);
440 PkgFile::ConvertBufferToString(fileInfo_.fileInfo.identity, {info->address, sizeof(info->address)});
441 PkgFile::ConvertBufferToString(fileInfo_.version, {info->version, sizeof(info->version)});
442 fileName_ = fileInfo_.fileInfo.identity;
443 fileInfo_.id = ReadLE16(buffer.buffer + offsetof(UpgradeCompInfo, id));
444 fileInfo_.resType = info->resType;
445 fileInfo_.compFlags = info->flags;
446 fileInfo_.type = info->type;
447
448 headerOffset_ = headerOffset;
449 dataOffset_ = dataOffset;
450 decodeLen = sizeof(UpgradeCompInfo);
451
452 PKG_LOGI("Component offset: %zu %zu packedSize:%zu %zu %s", headerOffset, dataOffset,
453 fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize, fileName_.c_str());
454 return PKG_SUCCESS;
455 }
456
Unpack(PkgStreamPtr outStream)457 int32_t UpgradeFileEntry::Unpack(PkgStreamPtr outStream)
458 {
459 PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(&fileInfo_.fileInfo);
460 PKG_CHECK(algorithm != nullptr, return PKG_INVALID_PARAM, "can not algorithm for %s", fileName_.c_str());
461
462 PkgStreamPtr inStream = pkgFile_->GetPkgStream();
463 PKG_CHECK(outStream != nullptr && inStream != nullptr, return PKG_INVALID_PARAM,
464 "outStream or inStream null for %s", fileName_.c_str());
465 PkgAlgorithmContext context = {
466 {this->dataOffset_, 0},
467 {fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize},
468 0, fileInfo_.fileInfo.digestMethod
469 };
470 int32_t ret = memcpy_s(context.digest, sizeof(context.digest), fileInfo_.digest, sizeof(fileInfo_.digest));
471 PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s ret:%d", ret);
472 ret = algorithm->Unpack(inStream, outStream, context);
473 PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail Decompress for %s", fileName_.c_str());
474 PKG_LOGI("Unpack %s data offset:%zu packedSize:%zu unpackedSize:%zu", fileName_.c_str(), dataOffset_,
475 fileInfo_.fileInfo.packedSize, fileInfo_.fileInfo.unpackedSize);
476 outStream->Flush(fileInfo_.fileInfo.unpackedSize);
477 return PKG_SUCCESS;
478 }
479
GetPackageTlvType()480 int16_t UpgradePkgFile::GetPackageTlvType()
481 {
482 static int16_t packageTlvType[PKG_DIGEST_TYPE_MAX] = {
483 TLV_TYPE_FOR_SHA256, TLV_TYPE_FOR_SHA256, TLV_TYPE_FOR_SHA256, TLV_TYPE_FOR_SHA384
484 };
485 if (pkgInfo_.pkgInfo.digestMethod < PKG_DIGEST_TYPE_MAX) {
486 return packageTlvType[pkgInfo_.pkgInfo.digestMethod];
487 }
488 return TLV_TYPE_FOR_SHA256;
489 }
490 } // namespace hpackage
491