• 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_manager_impl.h"
16 #include <algorithm>
17 #include <cctype>
18 #include <cstdio>
19 #include <cstring>
20 #include <functional>
21 #include <iterator>
22 #include <unistd.h>
23 #include <vector>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include "dump.h"
27 #include "pkg_gzipfile.h"
28 #include "pkg_lz4file.h"
29 #include "pkg_manager.h"
30 #include "pkg_upgradefile.h"
31 #include "pkg_verify_util.h"
32 #include "pkg_zipfile.h"
33 #include "securec.h"
34 #include "updater/updater_const.h"
35 #include "utils.h"
36 #include "zip_pkg_parse.h"
37 
38 using namespace std;
39 
40 namespace Hpackage {
41 constexpr int32_t BUFFER_SIZE = 4096;
42 constexpr int32_t DIGEST_INFO_NO_SIGN = 0;
43 constexpr int32_t DIGEST_INFO_HAS_SIGN = 1;
44 constexpr int32_t DIGEST_INFO_SIGNATURE = 2;
45 constexpr int32_t DIGEST_FLAGS_NO_SIGN = 1;
46 constexpr int32_t DIGEST_FLAGS_HAS_SIGN = 2;
47 constexpr int32_t DIGEST_FLAGS_SIGNATURE = 4;
48 constexpr uint32_t VERIFY_FINSH_PERCENT = 100;
49 
50 static thread_local PkgManagerImpl *g_pkgManagerInstance = nullptr;
GetPackageInstance()51 PkgManager::PkgManagerPtr PkgManager::GetPackageInstance()
52 {
53     if (g_pkgManagerInstance == nullptr) {
54         g_pkgManagerInstance = new PkgManagerImpl();
55     }
56     return g_pkgManagerInstance;
57 }
58 
CreatePackageInstance()59 PkgManager::PkgManagerPtr PkgManager::CreatePackageInstance()
60 {
61     return new PkgManagerImpl();
62 }
63 
ReleasePackageInstance(PkgManager::PkgManagerPtr manager)64 void PkgManager::ReleasePackageInstance(PkgManager::PkgManagerPtr manager)
65 {
66     if (manager == nullptr) {
67         return;
68     }
69     if (g_pkgManagerInstance == manager) {
70         delete g_pkgManagerInstance;
71         g_pkgManagerInstance = nullptr;
72     } else {
73         delete manager;
74     }
75     manager = nullptr;
76 }
77 
~PkgManagerImpl()78 PkgManagerImpl::~PkgManagerImpl()
79 {
80     ClearPkgFile();
81 }
82 
ClearPkgFile()83 void PkgManagerImpl::ClearPkgFile()
84 {
85     auto iter = pkgFiles_.begin();
86     while (iter != pkgFiles_.end()) {
87         PkgFilePtr file = (*iter);
88         delete file;
89         file = nullptr;
90         iter = pkgFiles_.erase(iter);
91     }
92     std::lock_guard<std::mutex> lock(mapLock_);
93     auto iter1 = pkgStreams_.begin();
94     while (iter1 != pkgStreams_.end()) {
95         PkgStreamPtr stream = (*iter1).second;
96         delete stream;
97         stream = nullptr;
98         iter1 = pkgStreams_.erase(iter1);
99     }
100 }
101 
CreatePackage(const std::string & path,const std::string & keyName,PkgInfoPtr header,std::vector<std::pair<std::string,ZipFileInfo>> & files)102 int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
103     std::vector<std::pair<std::string, ZipFileInfo>> &files)
104 {
105     int32_t ret = SetSignVerifyKeyName(keyName);
106     if (ret != PKG_SUCCESS) {
107         PKG_LOGE("ZipFileInfo Invalid keyname");
108         return ret;
109     }
110     if (files.size() <= 0 || header == nullptr) {
111         PKG_LOGE("ZipFileInfo Invalid param");
112         return PKG_INVALID_PARAM;
113     }
114     size_t offset = 0;
115     PkgFilePtr pkgFile = CreatePackage<ZipFileInfo>(path, header, files, offset);
116     if (pkgFile == nullptr) {
117         return PKG_INVALID_FILE;
118     }
119     delete pkgFile;
120     pkgFile = nullptr;
121     return ret;
122 }
123 
CreatePackage(const std::string & path,const std::string & keyName,PkgInfoPtr header,std::vector<std::pair<std::string,ComponentInfo>> & files)124 int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
125     std::vector<std::pair<std::string, ComponentInfo>> &files)
126 {
127     int32_t ret = SetSignVerifyKeyName(keyName);
128     if (ret != PKG_SUCCESS) {
129         PKG_LOGE("ComponentInfo Invalid keyname");
130         return ret;
131     }
132     if (files.size() <= 0 || header == nullptr) {
133         PKG_LOGE("ComponentInfo sssInvalid param");
134         return PKG_INVALID_PARAM;
135     }
136     size_t offset = 0;
137     PkgFilePtr pkgFile = CreatePackage<ComponentInfo>(path, header, files, offset);
138     if (pkgFile == nullptr) {
139         return PKG_INVALID_FILE;
140     }
141     ret = Sign(pkgFile->GetPkgStream(), offset, header);
142     delete pkgFile;
143     pkgFile = nullptr;
144     return ret;
145 }
146 
CreatePackage(const std::string & path,const std::string & keyName,PkgInfoPtr header,std::vector<std::pair<std::string,Lz4FileInfo>> & files)147 int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
148     std::vector<std::pair<std::string, Lz4FileInfo>> &files)
149 {
150     int32_t ret = SetSignVerifyKeyName(keyName);
151     if (ret != PKG_SUCCESS) {
152         PKG_LOGE("Invalid keyname");
153         return ret;
154     }
155     if (files.size() != 1 || header == nullptr) {
156         PKG_LOGE("Invalid param");
157         return PKG_INVALID_PARAM;
158     }
159     size_t offset = 0;
160     PkgFilePtr pkgFile = CreatePackage<Lz4FileInfo>(path, header, files, offset);
161     if (pkgFile == nullptr) {
162         return PKG_INVALID_FILE;
163     }
164     ret = Sign(pkgFile->GetPkgStream(), offset, header);
165     delete pkgFile;
166     pkgFile = nullptr;
167     return ret;
168 }
169 
170 template<class T>
CreatePackage(const std::string & path,PkgInfoPtr header,std::vector<std::pair<std::string,T>> & files,size_t & offset)171 PkgFilePtr PkgManagerImpl::CreatePackage(const std::string &path, PkgInfoPtr header,
172     std::vector<std::pair<std::string, T>> &files, size_t &offset)
173 {
174     PkgStreamPtr stream = nullptr;
175     int32_t ret = CreatePkgStream(stream, path, 0, PkgStream::PkgStreamType_Write);
176     if (ret != PKG_SUCCESS) {
177         PKG_LOGE("CreatePackage fail %s", path.c_str());
178         return nullptr;
179     }
180 
181     PkgFilePtr pkgFile = CreatePackage(PkgStreamImpl::ConvertPkgStream(stream),
182         static_cast<PkgFile::PkgType>(header->pkgType), header);
183     if (pkgFile == nullptr) {
184         PKG_LOGE("CreatePackage fail %s", path.c_str());
185         ClosePkgStream(stream);
186         return nullptr;
187     }
188 
189     PkgStreamPtr inputStream = nullptr;
190     for (size_t i = 0; i < files.size(); i++) {
191         ret = CreatePkgStream(inputStream, files[i].first, 0, PkgStream::PkgStreamType_Read);
192         if (ret != PKG_SUCCESS) {
193             PKG_LOGE("Create stream fail %s", files[i].first.c_str());
194             break;
195         }
196         ret = pkgFile->AddEntry(reinterpret_cast<const FileInfoPtr>(&(files[i].second)), inputStream);
197         if (ret != PKG_SUCCESS) {
198             PKG_LOGE("Add entry fail %s", files[i].first.c_str());
199             break;
200         }
201         ClosePkgStream(inputStream);
202         inputStream = nullptr;
203     }
204     if (ret != PKG_SUCCESS) {
205         ClosePkgStream(inputStream);
206         delete pkgFile;
207         pkgFile = nullptr;
208         return nullptr;
209     }
210     ret = pkgFile->SavePackage(offset);
211     if (ret != PKG_SUCCESS) {
212         delete pkgFile;
213         pkgFile = nullptr;
214         return nullptr;
215     }
216     return pkgFile;
217 }
218 
CreatePackage(PkgStreamPtr stream,PkgFile::PkgType type,PkgInfoPtr header)219 PkgFilePtr PkgManagerImpl::CreatePackage(PkgStreamPtr stream, PkgFile::PkgType type, PkgInfoPtr header)
220 {
221     PkgFilePtr pkgFile = nullptr;
222     switch (type) {
223         case PkgFile::PKG_TYPE_UPGRADE:
224             pkgFile = new UpgradePkgFile(this, stream, header);
225             break;
226         case PkgFile::PKG_TYPE_ZIP:
227             pkgFile = new ZipPkgFile(this, stream);
228             break;
229         case PkgFile::PKG_TYPE_LZ4:
230             pkgFile = new Lz4PkgFile(this, stream);
231             break;
232         case PkgFile::PKG_TYPE_GZIP:
233             pkgFile = new GZipPkgFile(this, stream);
234             break;
235         default:
236             return nullptr;
237     }
238     return pkgFile;
239 }
240 
LoadPackageWithoutUnPack(const std::string & packagePath,std::vector<std::string> & fileIds)241 int32_t PkgManagerImpl::LoadPackageWithoutUnPack(const std::string &packagePath,
242     std::vector<std::string> &fileIds)
243 {
244     PkgFile::PkgType pkgType = GetPkgTypeByName(packagePath);
245     int32_t ret = LoadPackage(packagePath, fileIds, pkgType);
246     if (ret != PKG_SUCCESS) {
247         PKG_LOGE("Parse %s fail ", packagePath.c_str());
248         ClearPkgFile();
249         return ret;
250     }
251     return PKG_SUCCESS;
252 }
253 
ParsePackage(StreamPtr stream,std::vector<std::string> & fileIds,int32_t type)254 int32_t PkgManagerImpl::ParsePackage(StreamPtr stream, std::vector<std::string> &fileIds, int32_t type)
255 {
256     if (stream == nullptr) {
257         PKG_LOGE("Invalid stream");
258         return PKG_INVALID_PARAM;
259     }
260     PkgFilePtr pkgFile = CreatePackage(static_cast<PkgStreamPtr>(stream), static_cast<PkgFile::PkgType>(type), nullptr);
261     if (pkgFile == nullptr) {
262         PKG_LOGE("Create package fail %s", stream->GetFileName().c_str());
263         return PKG_INVALID_PARAM;
264     }
265 
266     int32_t ret = pkgFile->LoadPackage(fileIds,
267         [](const PkgInfoPtr info, const std::vector<uint8_t> &digest, const std::vector<uint8_t> &signature)->int {
268             return PKG_SUCCESS;
269         });
270     if (ret != PKG_SUCCESS) {
271         PKG_LOGE("Load package fail %s", stream->GetFileName().c_str());
272         pkgFile->SetPkgStream();
273         delete pkgFile;
274         return ret;
275     }
276     pkgFiles_.push_back(pkgFile);
277     return PKG_SUCCESS;
278 }
279 
LoadPackage(const std::string & packagePath,const std::string & keyPath,std::vector<std::string> & fileIds)280 int32_t PkgManagerImpl::LoadPackage(const std::string &packagePath, const std::string &keyPath,
281     std::vector<std::string> &fileIds)
282 {
283     if (access(packagePath.c_str(), 0) != 0) {
284         UPDATER_LAST_WORD(PKG_INVALID_FILE);
285         return PKG_INVALID_FILE;
286     }
287     int32_t ret = SetSignVerifyKeyName(keyPath);
288     if (ret != PKG_SUCCESS) {
289         UPDATER_LAST_WORD(ret);
290         PKG_LOGE("Invalid keyname");
291         return ret;
292     }
293     // Check if package already loaded
294     for (auto iter : pkgFiles_) {
295         PkgFilePtr pkgFile = iter;
296         if (pkgFile != nullptr && pkgFile->GetPkgStream()->GetFileName().compare(packagePath) == 0) {
297             return PKG_SUCCESS;
298         }
299     }
300     PkgFile::PkgType pkgType = GetPkgTypeByName(packagePath);
301     ret = PKG_INVALID_FILE;
302     unzipToFile_ = ((pkgType == PkgFile::PKG_TYPE_GZIP) ? true : unzipToFile_);
303     if (pkgType == PkgFile::PKG_TYPE_UPGRADE) {
304         ret = LoadPackage(packagePath, fileIds, pkgType);
305         if (ret != PKG_SUCCESS) {
306             ClearPkgFile();
307             UPDATER_LAST_WORD(ret);
308             PKG_LOGE("Parse %s fail ", packagePath.c_str());
309             return ret;
310         }
311     } else if (pkgType != PkgFile::PKG_TYPE_NONE) {
312         std::vector<std::string> innerFileNames;
313         ret = LoadPackage(packagePath, innerFileNames, pkgType);
314         if (ret != PKG_SUCCESS) {
315             ClearPkgFile();
316             PKG_LOGE("Unzip %s fail ", packagePath.c_str());
317             return ret;
318         }
319         std::string path = GetFilePath(packagePath);
320         for (auto name : innerFileNames) {
321             pkgType = GetPkgTypeByName(name);
322             if (pkgType == PkgFile::PKG_TYPE_NONE) {
323                 fileIds.push_back(name);
324                 continue;
325             }
326             ret = ExtraAndLoadPackage(path, name, pkgType, fileIds);
327             PKG_CHECK(ret == PKG_SUCCESS, ClearPkgFile(); UPDATER_LAST_WORD(ret);
328                 return ret, "unpack %s fail in package %s ", name.c_str(), packagePath.c_str());
329         }
330     }
331     return PKG_SUCCESS;
332 }
333 
ExtraAndLoadPackage(const std::string & path,const std::string & name,PkgFile::PkgType type,std::vector<std::string> & fileIds)334 int32_t PkgManagerImpl::ExtraAndLoadPackage(const std::string &path, const std::string &name,
335     PkgFile::PkgType type, std::vector<std::string> &fileIds)
336 {
337     int32_t ret = PKG_SUCCESS;
338     const FileInfo *info = GetFileInfo(name);
339     if (info == nullptr) {
340         PKG_LOGE("Create middle stream fail %s", name.c_str());
341         return PKG_INVALID_FILE;
342     }
343 
344     PkgStreamPtr stream = nullptr;
345     struct stat st {};
346     const std::string tempPath = path.find(Updater::SDCARD_CARD_PATH) != string::npos ?
347         path : (string(Updater::UPDATER_PATH) + "/");
348     if (stat(tempPath.c_str(), &st) != 0) {
349 #ifndef __WIN32
350         (void)mkdir(tempPath.c_str(), 0775); // 0775 : rwxrwxr-x
351         (void)chown(tempPath.c_str(), Updater::Utils::USER_UPDATE_AUTHORITY, Updater::Utils::GROUP_UPDATE_AUTHORITY);
352 #endif
353     }
354 
355     // Extract package to file or memory
356     if (unzipToFile_) {
357         ret = CreatePkgStream(stream, tempPath + name + ".tmp", info->unpackedSize, PkgStream::PkgStreamType_Write);
358     } else {
359         ret = CreatePkgStream(stream, tempPath + name + ".tmp", info->unpackedSize, PkgStream::PkgStreamType_MemoryMap);
360     }
361     if (ret != PKG_SUCCESS) {
362         PKG_LOGE("Create middle stream fail %s", name.c_str());
363         return ret;
364     }
365 
366     ret = ExtractFile(name, stream);
367     if (ret != PKG_SUCCESS) {
368         PKG_LOGE("Extract file fail %s", name.c_str());
369         ClosePkgStream(stream);
370         return ret;
371     }
372     return LoadPackageWithStream(path, fileIds, type, stream);
373 }
374 
LoadPackage(const std::string & packagePath,std::vector<std::string> & fileIds,PkgFile::PkgType type)375 int32_t PkgManagerImpl::LoadPackage(const std::string &packagePath, std::vector<std::string> &fileIds,
376     PkgFile::PkgType type)
377 {
378     PkgStreamPtr stream = nullptr;
379     int32_t ret = CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read);
380     if (ret != PKG_SUCCESS) {
381         PKG_LOGE("Create input stream fail %s", packagePath.c_str());
382         UPDATER_LAST_WORD(ret);
383         return ret;
384     }
385     return LoadPackageWithStream(packagePath, fileIds, type, stream);
386 }
387 
LoadPackageWithStream(const std::string & packagePath,std::vector<std::string> & fileIds,PkgFile::PkgType type,PkgStreamPtr stream)388 int32_t PkgManagerImpl::LoadPackageWithStream(const std::string &packagePath,
389     std::vector<std::string> &fileIds, PkgFile::PkgType type, PkgStreamPtr stream)
390 {
391     int32_t ret = PKG_SUCCESS;
392     PkgFilePtr pkgFile = CreatePackage(stream, type, nullptr);
393     if (pkgFile == nullptr) {
394         PKG_LOGE("Create package fail %s", packagePath.c_str());
395         ClosePkgStream(stream);
396         UPDATER_LAST_WORD(ret);
397         return PKG_INVALID_PARAM;
398     }
399 
400     ret = pkgFile->LoadPackage(fileIds,
401         [this](const PkgInfoPtr info, const std::vector<uint8_t> &digest, const std::vector<uint8_t> &signature)->int {
402             return Verify(info->digestMethod, digest, signature);
403         });
404     if (ret != PKG_SUCCESS) {
405         PKG_LOGE("Load package fail %s", packagePath.c_str());
406         delete pkgFile;
407         UPDATER_LAST_WORD(ret);
408         return ret;
409     }
410     pkgFiles_.push_back(pkgFile);
411     return PKG_SUCCESS;
412 }
413 
ExtractFile(const std::string & path,PkgManager::StreamPtr output)414 int32_t PkgManagerImpl::ExtractFile(const std::string &path, PkgManager::StreamPtr output)
415 {
416     if (output == nullptr) {
417         PKG_LOGE("Invalid stream");
418         return PKG_INVALID_STREAM;
419     }
420     int32_t ret = PKG_INVALID_FILE;
421     PkgEntryPtr pkgEntry = GetPkgEntry(path);
422     if (pkgEntry != nullptr && pkgEntry->GetPkgFile() != nullptr) {
423         ret = pkgEntry->GetPkgFile()->ExtractFile(pkgEntry, PkgStreamImpl::ConvertPkgStream(output));
424     } else {
425         PKG_LOGE("Can not find file %s", path.c_str());
426     }
427     return ret;
428 }
429 
GetPackageInfo(const std::string & packagePath)430 const PkgInfo *PkgManagerImpl::GetPackageInfo(const std::string &packagePath)
431 {
432     for (auto iter : pkgFiles_) {
433         PkgFilePtr pkgFile = iter;
434         if (pkgFile != nullptr && pkgFile->GetPkgType() == PkgFile::PKG_TYPE_UPGRADE) {
435             return pkgFile->GetPkgInfo();
436         }
437     }
438     return nullptr;
439 }
440 
GetFileInfo(const std::string & path)441 const FileInfo *PkgManagerImpl::GetFileInfo(const std::string &path)
442 {
443     PkgEntryPtr pkgEntry = GetPkgEntry(path);
444     if (pkgEntry != nullptr) {
445         return pkgEntry->GetFileInfo();
446     }
447     return nullptr;
448 }
449 
GetPkgEntry(const std::string & path)450 PkgEntryPtr PkgManagerImpl::GetPkgEntry(const std::string &path)
451 {
452     // Find out pkgEntry by path.
453     for (auto iter : pkgFiles_) {
454         PkgFilePtr pkgFile = iter;
455         PkgEntryPtr pkgEntry = pkgFile->FindPkgEntry(path);
456         if (pkgEntry == nullptr) {
457             continue;
458         }
459         return pkgEntry;
460     }
461     return nullptr;
462 }
463 
CreatePkgStream(StreamPtr & stream,const std::string & fileName,size_t size,int32_t type)464 int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName, size_t size, int32_t type)
465 {
466     PkgStreamPtr pkgStream;
467     int32_t ret = CreatePkgStream(pkgStream, fileName, size, type);
468     if (pkgStream == nullptr) {
469         PKG_LOGE("Failed to create stream");
470         return -1;
471     }
472     stream = pkgStream;
473     return ret;
474 }
475 
CreatePkgStream(StreamPtr & stream,const std::string & fileName,const PkgBuffer & buffer)476 int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer)
477 {
478     PkgStreamPtr pkgStream = new MemoryMapStream(this, fileName, buffer, PkgStream::PkgStreamType_Buffer);
479     if (pkgStream == nullptr) {
480         PKG_LOGE("Failed to create stream");
481         return -1;
482     }
483     stream = pkgStream;
484     return PKG_SUCCESS;
485 }
486 
CreatePkgStream(StreamPtr & stream,const std::string & fileName,PkgStream::ExtractFileProcessor processor,const void * context)487 int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName,
488     PkgStream::ExtractFileProcessor processor, const void *context)
489 {
490     PkgStreamPtr pkgStream;
491     int32_t ret = CreatePkgStream(pkgStream, fileName, processor, context);
492     stream = pkgStream;
493     return ret;
494 }
495 
ClosePkgStream(StreamPtr & stream)496 void PkgManagerImpl::ClosePkgStream(StreamPtr &stream)
497 {
498     PkgStreamPtr pkgStream = static_cast<PkgStreamPtr>(stream);
499     ClosePkgStream(pkgStream);
500     stream = nullptr;
501 }
502 
CreatePkgStream(PkgStreamPtr & stream,const std::string & fileName,size_t size,int32_t type)503 int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string &fileName, size_t size, int32_t type)
504 {
505     stream = nullptr;
506     if (type == PkgStream::PkgStreamType_Write || type == PkgStream::PkgStreamType_Read) {
507         static char const *modeFlags[] = { "rb", "wb+" };
508         char realPath[PATH_MAX + 1] = {};
509 #ifdef _WIN32
510         if (type == PkgStream::PkgStreamType_Read && _fullpath(realPath, fileName.c_str(), PATH_MAX) == nullptr) {
511 #else
512         if (type == PkgStream::PkgStreamType_Read && realpath(fileName.c_str(), realPath) == nullptr) {
513 #endif
514             UPDATER_LAST_WORD(PKG_INVALID_FILE);
515             return PKG_INVALID_FILE;
516         }
517         if (CheckFile(fileName) != PKG_SUCCESS) {
518             UPDATER_LAST_WORD(PKG_INVALID_FILE);
519             PKG_LOGE("Fail to check file %s ", fileName.c_str());
520             return PKG_INVALID_FILE;
521         }
522         std::lock_guard<std::mutex> lock(mapLock_);
523         if (pkgStreams_.find(fileName) != pkgStreams_.end()) {
524             PkgStreamPtr mapStream = pkgStreams_[fileName];
525             mapStream->AddRef();
526             stream = mapStream;
527             return PKG_SUCCESS;
528         }
529         FILE *file = nullptr;
530         if (type == PkgStream::PkgStreamType_Read) {
531             file = fopen(realPath, modeFlags[type]);
532         } else {
533             file = fopen(fileName.c_str(), modeFlags[type]);
534         }
535         PKG_CHECK(file != nullptr, UPDATER_LAST_WORD(PKG_INVALID_FILE);
536             return PKG_INVALID_FILE, "Fail to open file %s ", fileName.c_str());
537         stream = new FileStream(this, fileName, file, type);
538     } else if (type == PkgStream::PkgStreamType_MemoryMap) {
539         if ((size == 0) && (access(fileName.c_str(), 0) != 0)) {
540             UPDATER_LAST_WORD(PKG_INVALID_FILE);
541             return PKG_INVALID_FILE;
542         }
543         size_t fileSize = (size == 0) ? GetFileSize(fileName) : size;
544         PKG_CHECK(fileSize > 0, UPDATER_LAST_WORD(PKG_INVALID_FILE);
545             return PKG_INVALID_FILE, "Fail to check file size %s ", fileName.c_str());
546         uint8_t *memoryMap = MapMemory(fileName, fileSize);
547         PKG_CHECK(memoryMap != nullptr, UPDATER_LAST_WORD(PKG_INVALID_FILE);
548             return PKG_INVALID_FILE, "Fail to map memory %s ", fileName.c_str());
549         PkgBuffer buffer(memoryMap, fileSize);
550         stream = new MemoryMapStream(this, fileName, buffer);
551     } else {
552         UPDATER_LAST_WORD(-1);
553         return -1;
554     }
555     std::lock_guard<std::mutex> lock(mapLock_);
556     pkgStreams_[fileName] = stream;
557     return PKG_SUCCESS;
558 }
559 
560 int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string &fileName,
561     PkgStream::ExtractFileProcessor processor, const void *context)
562 {
563     stream = new ProcessorStream(this, fileName, processor, context);
564     if (stream == nullptr) {
565         PKG_LOGE("Failed to create stream");
566         return -1;
567     }
568     return PKG_SUCCESS;
569 }
570 
571 void PkgManagerImpl::ClosePkgStream(PkgStreamPtr &stream)
572 {
573     PkgStreamPtr mapStream = stream;
574     if (mapStream == nullptr) {
575         return;
576     }
577 
578     std::lock_guard<std::mutex> lock(mapLock_);
579     auto iter = pkgStreams_.find(mapStream->GetFileName());
580     if (iter != pkgStreams_.end()) {
581         mapStream->DelRef();
582         if (mapStream->IsRef()) {
583             return;
584         }
585         pkgStreams_.erase(iter);
586     }
587     delete mapStream;
588     stream = nullptr;
589 }
590 
591 PkgFile::PkgType PkgManagerImpl::GetPkgTypeByName(const std::string &path)
592 {
593     std::size_t pos = path.find_last_of('.');
594     if (pos == std::string::npos) {
595         return PkgFile::PKG_TYPE_NONE;
596     }
597     std::string postfix = path.substr(pos + 1, -1);
598     std::transform(postfix.begin(), postfix.end(), postfix.begin(), ::tolower);
599 
600     if (path.substr(pos + 1, -1).compare("bin") == 0) {
601         return PkgFile::PKG_TYPE_UPGRADE;
602     } else if (path.substr(pos + 1, -1).compare("zip") == 0) {
603         return PkgFile::PKG_TYPE_ZIP;
604     } else if (path.substr(pos + 1, -1).compare("lz4") == 0) {
605         return PkgFile::PKG_TYPE_LZ4;
606     } else if (path.substr(pos + 1, -1).compare("gz") == 0) {
607         return PkgFile::PKG_TYPE_GZIP;
608     }
609     return PkgFile::PKG_TYPE_NONE;
610 }
611 
612 int32_t PkgManagerImpl::VerifyPackage(const std::string &packagePath, const std::string &keyPath,
613     const std::string &version, const PkgBuffer &digest, VerifyCallback cb)
614 {
615     int32_t ret = SetSignVerifyKeyName(keyPath);
616     if (ret != PKG_SUCCESS) {
617         PKG_LOGE("Invalid keyname");
618         return ret;
619     }
620 
621     PkgFile::PkgType type = GetPkgTypeByName(packagePath);
622     if (type != PkgFile::PKG_TYPE_UPGRADE) {
623         ret = VerifyOtaPackage(packagePath);
624     } else if (digest.buffer != nullptr) {
625         ret = VerifyBinFile(packagePath, keyPath, version, digest);
626     } else {
627         PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance();
628         if (pkgManager == nullptr) {
629             PKG_LOGE("Fail to GetPackageInstance");
630             return PKG_INVALID_SIGNATURE;
631         }
632         std::vector<std::string> components;
633         ret = pkgManager->LoadPackage(packagePath, keyPath, components);
634     }
635     cb(ret, VERIFY_FINSH_PERCENT);
636     if (ret != PKG_SUCCESS) {
637         PKG_LOGE("Verify file %s fail", packagePath.c_str());
638         return ret;
639     }
640     PKG_LOGI("Verify file %s success", packagePath.c_str());
641     return ret;
642 }
643 
644 int32_t PkgManagerImpl::GenerateFileDigest(PkgStreamPtr stream,
645     uint8_t digestMethod, uint8_t flags, std::vector<std::vector<uint8_t>> &digestInfos, size_t hashBufferLen)
646 {
647     size_t fileLen = (hashBufferLen == 0) ? stream->GetFileLength() : hashBufferLen;
648     size_t digestLen = DigestAlgorithm::GetDigestLen(digestMethod);
649     size_t signatureLen = DigestAlgorithm::GetSignatureLen(digestMethod);
650     // Check entire package
651     DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(digestMethod);
652     PKG_CHECK(algorithm != nullptr, return PKG_NOT_EXIST_ALGORITHM, "Invalid file %s", stream->GetFileName().c_str());
653     algorithm->Init();
654 
655     // Get verify algorithm
656     DigestAlgorithm::DigestAlgorithmPtr algorithmInner = PkgAlgorithmFactory::GetDigestAlgorithm(digestMethod);
657     PKG_CHECK(algorithm != nullptr, return PKG_NOT_EXIST_ALGORITHM, "Invalid file %s", stream->GetFileName().c_str());
658     algorithmInner->Init();
659 
660     size_t offset = 0;
661     size_t readLen = 0;
662     size_t needReadLen = fileLen;
663     size_t buffSize = BUFFER_SIZE;
664     PkgBuffer buff(buffSize);
665     if (flags & DIGEST_FLAGS_SIGNATURE) {
666         PKG_ONLY_CHECK(SIGN_TOTAL_LEN < fileLen, return PKG_INVALID_SIGNATURE);
667         needReadLen = fileLen - SIGN_TOTAL_LEN;
668     }
669     while (offset < needReadLen) {
670         PKG_ONLY_CHECK((needReadLen - offset) >= buffSize, buffSize = needReadLen - offset);
671         int32_t ret = stream->Read(buff, offset, buffSize, readLen);
672         PKG_CHECK(ret == PKG_SUCCESS, return ret, "read buffer fail %s", stream->GetFileName().c_str());
673         PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_HAS_SIGN, algorithm->Update(buff, readLen));
674         PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_NO_SIGN, algorithmInner->Update(buff, readLen));
675         offset += readLen;
676         PostDecodeProgress(POST_TYPE_VERIFY_PKG, readLen, nullptr);
677         readLen = 0;
678     }
679 
680     // Read last signatureLen
681     if (flags & DIGEST_FLAGS_SIGNATURE) {
682         readLen = 0;
683         int32_t ret = stream->Read(buff, offset, SIGN_TOTAL_LEN, readLen);
684         PKG_CHECK(ret == PKG_SUCCESS, return ret, "read buffer failed %s", stream->GetFileName().c_str());
685         PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_HAS_SIGN, algorithm->Update(buff, readLen));
686         PkgBuffer data(SIGN_TOTAL_LEN);
687         PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_NO_SIGN, algorithmInner->Update(data, SIGN_TOTAL_LEN));
688     }
689     PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_HAS_SIGN,
690         PkgBuffer result(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digestLen); algorithm->Final(result));
691     PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_NO_SIGN,
692         PkgBuffer result(digestInfos[DIGEST_INFO_NO_SIGN].data(), digestLen); algorithmInner->Final(result));
693     if (flags & DIGEST_FLAGS_SIGNATURE) {
694         if (digestMethod == PKG_DIGEST_TYPE_SHA256) {
695             PKG_CHECK(!memcpy_s(digestInfos[DIGEST_INFO_SIGNATURE].data(), signatureLen, buff.buffer, signatureLen),
696                 return PKG_NONE_MEMORY, "GenerateFileDigest memcpy failed");
697         } else {
698             PKG_CHECK(!memcpy_s(digestInfos[DIGEST_INFO_SIGNATURE].data(), signatureLen, buff.buffer + SIGN_SHA256_LEN,
699                 signatureLen), return PKG_NONE_MEMORY, "GenerateFileDigest memcpy failed");
700         }
701     }
702     return PKG_SUCCESS;
703 }
704 
705 int32_t PkgManagerImpl::Verify(uint8_t digestMethod, const std::vector<uint8_t> &digest,
706     const std::vector<uint8_t> &signature)
707 {
708     SignAlgorithm::SignAlgorithmPtr signAlgorithm = PkgAlgorithmFactory::GetVerifyAlgorithm(
709         signVerifyKeyName_, digestMethod);
710     if (signAlgorithm == nullptr) {
711         PKG_LOGE("Invalid sign algo");
712         return PKG_INVALID_SIGNATURE;
713     }
714     return signAlgorithm->VerifyDigest(digest, signature);
715 }
716 
717 int32_t PkgManagerImpl::Sign(PkgStreamPtr stream, size_t offset, const PkgInfoPtr &info)
718 {
719     if (info == nullptr) {
720         PKG_LOGE("Invalid param");
721         return PKG_INVALID_PARAM;
722     }
723     if (info->signMethod == PKG_SIGN_METHOD_NONE) {
724         return PKG_SUCCESS;
725     }
726 
727     size_t digestLen = DigestAlgorithm::GetDigestLen(info->digestMethod);
728     std::vector<std::vector<uint8_t>> digestInfos(DIGEST_INFO_SIGNATURE + 1);
729     digestInfos[DIGEST_INFO_HAS_SIGN].resize(digestLen);
730     int32_t ret = GenerateFileDigest(stream, info->digestMethod, DIGEST_FLAGS_HAS_SIGN, digestInfos);
731     if (ret != PKG_SUCCESS) {
732         PKG_LOGE("Fail to generate signature %s", stream->GetFileName().c_str());
733         return ret;
734     }
735     SignAlgorithm::SignAlgorithmPtr signAlgorithm =
736         PkgAlgorithmFactory::GetSignAlgorithm(signVerifyKeyName_, info->signMethod, info->digestMethod);
737     if (signAlgorithm == nullptr) {
738         PKG_LOGE("Invalid sign algo");
739         return PKG_INVALID_SIGNATURE;
740     }
741     size_t signLen = DigestAlgorithm::GetSignatureLen(info->digestMethod);
742     std::vector<uint8_t> signedData(signLen, 0);
743     // Clear buffer
744     PkgBuffer signBuffer(signedData);
745     ret = stream->Write(signBuffer, signLen, offset);
746     size_t signDataLen = 0;
747     signedData.clear();
748     PkgBuffer digest(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digestLen);
749     ret = signAlgorithm->SignBuffer(digest, signedData, signDataLen);
750     if (ret != PKG_SUCCESS) {
751         PKG_LOGE("Fail to SignBuffer %s", stream->GetFileName().c_str());
752         return ret;
753     }
754     if (signDataLen > signLen) {
755         PKG_LOGE("SignData len %zu more %zu", signDataLen, signLen);
756         return PKG_INVALID_SIGNATURE;
757     }
758     PKG_LOGI("Signature %zu %zu %s", offset, signDataLen, stream->GetFileName().c_str());
759     ret = stream->Write(signBuffer, signDataLen, offset);
760     stream->Flush(offset + signedData.size());
761     if (ret != PKG_SUCCESS) {
762         PKG_LOGE("Fail to Write signature %s", stream->GetFileName().c_str());
763         return ret;
764     }
765     PKG_LOGW("Sign file %s success", stream->GetFileName().c_str());
766     return ret;
767 }
768 
769 int32_t PkgManagerImpl::SetSignVerifyKeyName(const std::string &keyName)
770 {
771     if (access(keyName.c_str(), 0) != 0) {
772         UPDATER_LAST_WORD(PKG_INVALID_FILE);
773         return PKG_INVALID_FILE;
774     }
775     signVerifyKeyName_ = keyName;
776     return PKG_SUCCESS;
777 }
778 
779 int32_t PkgManagerImpl::DecompressBuffer(FileInfoPtr info, const PkgBuffer &buffer, StreamPtr stream) const
780 {
781     if (info == nullptr || buffer.buffer == nullptr || stream == nullptr) {
782         PKG_LOGE("DecompressBuffer Param is null");
783         return PKG_INVALID_PARAM;
784     }
785     PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info);
786     if (algorithm == nullptr) {
787         PKG_LOGE("DecompressBuffer Can not get algorithm for %s", info->identity.c_str());
788         return PKG_INVALID_PARAM;
789     }
790 
791     std::shared_ptr<MemoryMapStream> inStream = std::make_shared<MemoryMapStream>(
792         (PkgManager::PkgManagerPtr)this, info->identity, buffer, PkgStream::PkgStreamType_Buffer);
793     if (inStream == nullptr) {
794         PKG_LOGE("DecompressBuffer Can not create stream for %s", info->identity.c_str());
795         return PKG_INVALID_PARAM;
796     }
797     PkgAlgorithmContext context = {{0, 0}, {buffer.length, 0}, 0, info->digestMethod};
798     int32_t ret = algorithm->Unpack(inStream.get(), PkgStreamImpl::ConvertPkgStream(stream), context);
799     if (ret != PKG_SUCCESS) {
800         PKG_LOGE("Fail Decompress for %s", info->identity.c_str());
801         return ret;
802     }
803     PKG_LOGI("packedSize: %zu unpackedSize: %zu ", buffer.length, context.unpackedSize);
804     PkgStreamImpl::ConvertPkgStream(stream)->Flush(context.unpackedSize);
805     info->packedSize = context.packedSize;
806     info->unpackedSize = context.unpackedSize;
807     algorithm->UpdateFileInfo(info);
808     return PKG_SUCCESS;
809 }
810 
811 int32_t PkgManagerImpl::CompressBuffer(FileInfoPtr info, const PkgBuffer &buffer, StreamPtr stream) const
812 {
813     if (info == nullptr || buffer.buffer == nullptr || stream == nullptr) {
814         PKG_LOGE("CompressBuffer Param is null");
815         return PKG_INVALID_PARAM;
816     }
817     PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info);
818     if (algorithm == nullptr) {
819         PKG_LOGE("CompressBuffer Can not get algorithm for %s", info->identity.c_str());
820         return PKG_INVALID_PARAM;
821     }
822 
823     std::shared_ptr<MemoryMapStream> inStream = std::make_shared<MemoryMapStream>(
824         (PkgManager::PkgManagerPtr)this, info->identity, buffer, PkgStream::PkgStreamType_Buffer);
825     if (inStream == nullptr) {
826         PKG_LOGE("CompressBuffer Can not create stream for %s", info->identity.c_str());
827         return PKG_INVALID_PARAM;
828     }
829     PkgAlgorithmContext context = {{0, 0}, {0, buffer.length}, 0, info->digestMethod};
830     int32_t ret = algorithm->Pack(inStream.get(), PkgStreamImpl::ConvertPkgStream(stream), context);
831     if (ret != PKG_SUCCESS) {
832         PKG_LOGE("Fail Decompress for %s", info->identity.c_str());
833         return ret;
834     }
835     PKG_LOGI("packedSize: %zu unpackedSize: %zu ", context.packedSize, context.unpackedSize);
836     PkgStreamImpl::ConvertPkgStream(stream)->Flush(context.packedSize);
837     info->packedSize = context.packedSize;
838     info->unpackedSize = context.unpackedSize;
839     return PKG_SUCCESS;
840 }
841 
842 void PkgManagerImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context)
843 {
844     if (decodeProgress_ != nullptr) {
845         decodeProgress_(type, writeDataLen, context);
846     }
847 }
848 
849 int32_t PkgManagerImpl::VerifyOtaPackage(const std::string &packagePath)
850 {
851     PkgStreamPtr pkgStream = nullptr;
852     int32_t ret = CreatePkgStream(pkgStream, packagePath, 0, PkgStream::PkgStreamType_Read);
853     if (ret != PKG_SUCCESS) {
854         PKG_LOGE("CreatePackage fail %s", packagePath.c_str());
855         UPDATER_LAST_WORD(PKG_INVALID_FILE);
856         return ret;
857     }
858 
859     PkgVerifyUtil verifyUtil;
860     ret = verifyUtil.VerifyPackageSign(pkgStream);
861     if (ret != PKG_SUCCESS) {
862         PKG_LOGE("Verify zpkcs7 signature failed.");
863         UPDATER_LAST_WORD(ret);
864         ClosePkgStream(pkgStream);
865         return ret;
866     }
867 
868     ClosePkgStream(pkgStream);
869     return PKG_SUCCESS;
870 }
871 
872 int32_t PkgManagerImpl::VerifyBinFile(const std::string &packagePath, const std::string &keyPath,
873     const std::string &version, const PkgBuffer &digest)
874 {
875     PkgStreamPtr stream = nullptr;
876     int32_t ret = CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read);
877     if (ret != PKG_SUCCESS) {
878         PKG_LOGE("Create input stream fail %s", packagePath.c_str());
879         return ret;
880     }
881     size_t fileLen = stream->GetFileLength();
882     if (fileLen <= 0) {
883         PKG_LOGE("invalid file to load");
884         ClosePkgStream(stream);
885         return PKG_INVALID_FILE;
886     }
887 
888     int8_t digestMethod = static_cast<int8_t>(DigestAlgorithm::GetDigestMethod(version));
889     size_t digestLen = DigestAlgorithm::GetDigestLen(digestMethod);
890     size_t signatureLen = DigestAlgorithm::GetSignatureLen(digestMethod);
891     if (digestLen != digest.length) {
892         PKG_LOGE("Invalid digestLen");
893         ClosePkgStream(stream);
894         return PKG_INVALID_PARAM;
895     }
896     std::vector<std::vector<uint8_t>> digestInfos(DIGEST_INFO_SIGNATURE + 1);
897     digestInfos[DIGEST_INFO_HAS_SIGN].resize(digestLen);
898     digestInfos[DIGEST_INFO_NO_SIGN].resize(digestLen);
899     digestInfos[DIGEST_INFO_SIGNATURE].resize(signatureLen);
900 
901     ret = GenerateFileDigest(stream, digestMethod, DIGEST_FLAGS_HAS_SIGN, digestInfos);
902     if (memcmp(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digest.buffer, digest.length) != 0) {
903         PKG_LOGE("Fail to verify package %s", packagePath.c_str());
904         ret = PKG_INVALID_SIGNATURE;
905     }
906 
907     ClosePkgStream(stream);
908     return ret;
909 }
910 } // namespace Hpackage
911