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