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