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