• 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 "pkg_gzipfile.h"
25 #include "pkg_lz4file.h"
26 #include "pkg_manager.h"
27 #include "pkg_upgradefile.h"
28 #include "pkg_zipfile.h"
29 #include "securec.h"
30 
31 using namespace std;
32 
33 namespace hpackage {
34 constexpr int32_t BUFFER_SIZE = 4096;
35 constexpr int32_t DIGEST_INFO_NO_SIGN = 0;
36 constexpr int32_t DIGEST_INFO_HAS_SIGN = 1;
37 constexpr int32_t DIGEST_INFO_SIGNATURE = 2;
38 constexpr int32_t DIGEST_FLAGS_NO_SIGN = 1;
39 constexpr int32_t DIGEST_FLAGS_HAS_SIGN = 2;
40 constexpr int32_t DIGEST_FLAGS_SIGNATURE = 4;
41 constexpr uint32_t VERIFY_FINSH_PERCENT = 100;
42 constexpr uint32_t VERIFY_DIGEST_PERCENT = 50;
43 
44 static PkgManagerImpl *g_pkgManagerInstance = nullptr;
GetPackageInstance()45 PkgManager::PkgManagerPtr PkgManager::GetPackageInstance()
46 {
47     if (g_pkgManagerInstance == nullptr) {
48         g_pkgManagerInstance = new PkgManagerImpl();
49     }
50     return g_pkgManagerInstance;
51 }
52 
CreatePackageInstance()53 PkgManager::PkgManagerPtr PkgManager::CreatePackageInstance()
54 {
55     PkgManager::PkgManagerPtr impl = new PkgManagerImpl();
56     PKG_LOGI("CreatePackageInstance %p", impl);
57     return impl;
58 }
59 
ReleasePackageInstance(PkgManager::PkgManagerPtr manager)60 void PkgManager::ReleasePackageInstance(PkgManager::PkgManagerPtr manager)
61 {
62     if (manager == nullptr) {
63         return;
64     }
65     PKG_LOGI("ReleasePackageInstance %p", manager);
66     if (g_pkgManagerInstance == manager) {
67         delete g_pkgManagerInstance;
68         g_pkgManagerInstance = nullptr;
69     } else {
70         delete manager;
71     }
72     manager = nullptr;
73 }
74 
~PkgManagerImpl()75 PkgManagerImpl::~PkgManagerImpl()
76 {
77     ClearPkgFile();
78 }
79 
ClearPkgFile()80 void PkgManagerImpl::ClearPkgFile()
81 {
82     auto iter = pkgFiles_.begin();
83     while (iter != pkgFiles_.end()) {
84         PkgFilePtr file = (*iter);
85         delete file;
86         iter = pkgFiles_.erase(iter);
87     }
88     auto iter1 = pkgStreams_.begin();
89     while (iter1 != pkgStreams_.end()) {
90         PkgStreamPtr stream = (*iter1).second;
91         delete stream;
92         iter1 = pkgStreams_.erase(iter1);
93     }
94 }
95 
CreatePackage(const std::string & path,const std::string & keyName,PkgInfoPtr header,std::vector<std::pair<std::string,ZipFileInfo>> & files)96 int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
97     std::vector<std::pair<std::string, ZipFileInfo>> &files)
98 {
99     int32_t ret = SetSignVerifyKeyName(keyName);
100     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Invalid keyname");
101     PKG_CHECK(files.size() > 0 && header != nullptr, return PKG_INVALID_PARAM, "Invalid param");
102     size_t offset = 0;
103     PkgFilePtr pkgFile = CreatePackage<ZipFileInfo>(path, header, files, offset);
104     if (pkgFile == nullptr) {
105         return PKG_INVALID_FILE;
106     }
107     offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset;
108     ret = Sign(pkgFile->GetPkgStream(), offset, header);
109     delete pkgFile;
110     return ret;
111 }
112 
CreatePackage(const std::string & path,const std::string & keyName,PkgInfoPtr header,std::vector<std::pair<std::string,ComponentInfo>> & files)113 int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
114     std::vector<std::pair<std::string, ComponentInfo>> &files)
115 {
116     int32_t ret = SetSignVerifyKeyName(keyName);
117     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Invalid keyname");
118     PKG_CHECK(files.size() > 0 && header != nullptr, return PKG_INVALID_PARAM, "Invalid param");
119     size_t offset = 0;
120     PkgFilePtr pkgFile = CreatePackage<ComponentInfo>(path, header, files, offset);
121     if (pkgFile == nullptr) {
122         return PKG_INVALID_FILE;
123     }
124     offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset;
125     ret = Sign(pkgFile->GetPkgStream(), offset, header);
126     delete pkgFile;
127     return ret;
128 }
129 
CreatePackage(const std::string & path,const std::string & keyName,PkgInfoPtr header,std::vector<std::pair<std::string,Lz4FileInfo>> & files)130 int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string &keyName, PkgInfoPtr header,
131     std::vector<std::pair<std::string, Lz4FileInfo>> &files)
132 {
133     int32_t ret = SetSignVerifyKeyName(keyName);
134     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Invalid keyname");
135     PKG_CHECK(files.size() == 1 && header != nullptr, return PKG_INVALID_PARAM, "Invalid param");
136     size_t offset = 0;
137     PkgFilePtr pkgFile = CreatePackage<Lz4FileInfo>(path, header, files, offset);
138     if (pkgFile == nullptr) {
139         return PKG_INVALID_FILE;
140     }
141     offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset;
142     ret = Sign(pkgFile->GetPkgStream(), offset, header);
143     delete pkgFile;
144     return ret;
145 }
146 
CreatePackage(const std::string & path,PkgInfoPtr header,std::vector<std::pair<std::string,ComponentInfo>> & files,size_t & offset,std::string & hashValue)147 int32_t PkgManagerImpl::CreatePackage(const std::string &path, PkgInfoPtr header,
148     std::vector<std::pair<std::string, ComponentInfo>> &files, size_t &offset, std::string &hashValue)
149 {
150     PKG_CHECK(files.size() > 0 && header != nullptr, return PKG_INVALID_PARAM, "Invalid param");
151     PkgFilePtr pkgFile = CreatePackage<ComponentInfo>(path, header, files, offset);
152     if (pkgFile == nullptr) {
153         return PKG_INVALID_FILE;
154     }
155     int32_t ret = 0;
156     if (header->pkgFlags & PKG_SUPPORT_L1) {
157         size_t digestLen = DigestAlgorithm::GetDigestLen(header->digestMethod);
158         std::vector<std::vector<uint8_t>> digestInfos(DIGEST_INFO_SIGNATURE + 1);
159         digestInfos[DIGEST_INFO_HAS_SIGN].resize(digestLen);
160         ret = GenerateFileDigest(pkgFile->GetPkgStream(),
161             header->digestMethod, DIGEST_FLAGS_HAS_SIGN, digestInfos, offset);
162         offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset;
163         PKG_CHECK(ret == PKG_SUCCESS,
164             return ret, "Fail to generate signature %s", pkgFile->GetPkgStream()->GetFileName().c_str());
165         hashValue = ConvertShaHex(digestInfos[DIGEST_INFO_HAS_SIGN]);
166         PKG_LOGI("PkgManagerImpl::CreatePackage sign offset %zu ", offset);
167     } else {
168         offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset;
169         ret = Sign(pkgFile->GetPkgStream(), offset, header);
170     }
171     delete pkgFile;
172     return ret;
173 }
174 
175 template<class T>
CreatePackage(const std::string & path,PkgInfoPtr header,std::vector<std::pair<std::string,T>> & files,size_t & offset)176 PkgFilePtr PkgManagerImpl::CreatePackage(const std::string &path, PkgInfoPtr header,
177     std::vector<std::pair<std::string, T>> &files, size_t &offset)
178 {
179     PkgStreamPtr stream = nullptr;
180     int32_t ret = CreatePkgStream(stream, path, 0, PkgStream::PkgStreamType_Write);
181     PKG_CHECK(ret == PKG_SUCCESS, return nullptr, "CreatePackage fail %s", path.c_str());
182 
183     PkgFilePtr pkgFile = CreatePackage(PkgStreamImpl::ConvertPkgStream(stream),
184         static_cast<PkgFile::PkgType>(header->pkgType), header);
185     PKG_CHECK(pkgFile != nullptr, ClosePkgStream(stream); return nullptr, "CreatePackage fail %s", path.c_str());
186 
187     PkgStreamPtr inputStream = nullptr;
188     for (size_t i = 0; i < files.size(); i++) {
189         ret = CreatePkgStream(inputStream, files[i].first, 0, PkgStream::PkgStreamType_Read);
190         PKG_CHECK(ret == PKG_SUCCESS, break, "Create stream fail %s", files[i].first.c_str());
191         ret = pkgFile->AddEntry(reinterpret_cast<const FileInfoPtr>(&(files[i].second)), inputStream);
192         PKG_CHECK(ret == PKG_SUCCESS, break, "Add entry fail %s", files[i].first.c_str());
193         ClosePkgStream(inputStream);
194         inputStream = nullptr;
195     }
196     if (ret != PKG_SUCCESS) {
197         ClosePkgStream(inputStream);
198         delete pkgFile;
199         return nullptr;
200     }
201     ret = pkgFile->SavePackage(offset);
202     if (ret != PKG_SUCCESS) {
203         delete pkgFile;
204         return nullptr;
205     }
206     return pkgFile;
207 }
208 
CreatePackage(PkgStreamPtr stream,PkgFile::PkgType type,PkgInfoPtr header)209 PkgFilePtr PkgManagerImpl::CreatePackage(PkgStreamPtr stream, PkgFile::PkgType type, PkgInfoPtr header)
210 {
211     PkgFilePtr pkgFile = nullptr;
212     switch (type) {
213         case PkgFile::PKG_TYPE_UPGRADE:
214             pkgFile = new UpgradePkgFile(this, stream, header);
215             break;
216         case PkgFile::PKG_TYPE_ZIP:
217             pkgFile = new ZipPkgFile(this, stream);
218             break;
219         case PkgFile::PKG_TYPE_LZ4:
220             pkgFile = new Lz4PkgFile(this, stream);
221             break;
222         case PkgFile::PKG_TYPE_GZIP:
223             pkgFile = new GZipPkgFile(this, stream);
224             break;
225         default:
226             return nullptr;
227     }
228     return pkgFile;
229 }
230 
LoadPackageWithoutUnPack(const std::string & packagePath,std::vector<std::string> & fileIds)231 int32_t PkgManagerImpl::LoadPackageWithoutUnPack(const std::string &packagePath,
232     std::vector<std::string> &fileIds)
233 {
234     PkgFile::PkgType pkgType = GetPkgTypeByName(packagePath);
235     int32_t ret = LoadPackage(packagePath, fileIds, pkgType);
236     PKG_CHECK(ret == PKG_SUCCESS, ClearPkgFile(); return ret, "Parse %s fail ", packagePath.c_str());
237     return PKG_SUCCESS;
238 }
239 
ParsePackage(StreamPtr stream,std::vector<std::string> & fileIds,int32_t type)240 int32_t PkgManagerImpl::ParsePackage(StreamPtr stream, std::vector<std::string> &fileIds, int32_t type)
241 {
242     PKG_CHECK(stream != nullptr, return PKG_INVALID_PARAM, "Invalid stream");
243     PkgFilePtr pkgFile = CreatePackage(static_cast<PkgStreamPtr>(stream), static_cast<PkgFile::PkgType>(type), nullptr);
244     PKG_CHECK(pkgFile != nullptr, return PKG_INVALID_PARAM, "Create package fail %s", stream->GetFileName().c_str());
245 
246     int32_t ret = pkgFile->LoadPackage(fileIds,
247         [](const PkgInfoPtr info, const std::vector<uint8_t> &digest, const std::vector<uint8_t> &signature)->int {
248             return PKG_SUCCESS;
249         });
250     PKG_CHECK(ret == PKG_SUCCESS, pkgFile->SetPkgStream(); delete pkgFile;
251         return ret, "Load package fail %s", stream->GetFileName().c_str());
252     pkgFiles_.push_back(pkgFile);
253     return PKG_SUCCESS;
254 }
255 
LoadPackage(const std::string & packagePath,const std::string & keyPath,std::vector<std::string> & fileIds)256 int32_t PkgManagerImpl::LoadPackage(const std::string &packagePath, const std::string &keyPath,
257     std::vector<std::string> &fileIds)
258 {
259     if (access(packagePath.c_str(), 0) != 0) {
260         return PKG_INVALID_FILE;
261     }
262     int32_t ret = SetSignVerifyKeyName(keyPath);
263     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Invalid keyname");
264 
265     // Check if package already loaded
266     for (auto iter : pkgFiles_) {
267         PkgFilePtr pkgFile = iter;
268         if (pkgFile != nullptr && pkgFile->GetPkgStream()->GetFileName().compare(packagePath) == 0) {
269             return PKG_SUCCESS;
270         }
271     }
272 
273     PkgFile::PkgType pkgType = GetPkgTypeByName(packagePath);
274     ret = PKG_INVALID_FILE;
275     unzipToFile_ = ((pkgType == PkgFile::PKG_TYPE_GZIP) ? true : unzipToFile_);
276     if (pkgType == PkgFile::PKG_TYPE_UPGRADE) {
277         ret = LoadPackage(packagePath, fileIds, pkgType);
278         PKG_CHECK(ret == PKG_SUCCESS, ClearPkgFile(); return ret, "Parse %s fail ", packagePath.c_str());
279     } else if (pkgType != PkgFile::PKG_TYPE_NONE) {
280         std::vector<std::string> innerFileNames;
281         ret = LoadPackage(packagePath, innerFileNames, pkgType);
282         PKG_CHECK(ret == PKG_SUCCESS, ClearPkgFile(); return ret, "Unzip %s fail ", packagePath.c_str());
283 
284         std::string path = GetFilePath(packagePath);
285         for (auto name : innerFileNames) {
286             pkgType = GetPkgTypeByName(name);
287             if (pkgType == PkgFile::PKG_TYPE_NONE) {
288                 fileIds.push_back(name);
289                 continue;
290             }
291             ret = ExtraAndLoadPackage(path, name, pkgType, fileIds);
292             PKG_CHECK(ret == PKG_SUCCESS, ClearPkgFile();
293                 return ret, "unpack %s fail in package %s ", name.c_str(), packagePath.c_str());
294         }
295     }
296     return PKG_SUCCESS;
297 }
298 
ExtraAndLoadPackage(const std::string & path,const std::string & name,PkgFile::PkgType type,std::vector<std::string> & fileIds)299 int32_t PkgManagerImpl::ExtraAndLoadPackage(const std::string &path, const std::string &name,
300     PkgFile::PkgType type, std::vector<std::string> &fileIds)
301 {
302     int32_t ret = PKG_SUCCESS;
303     const FileInfo *info = GetFileInfo(name);
304     PKG_CHECK(info != nullptr, return PKG_INVALID_FILE, "Create middle stream fail %s", name.c_str());
305 
306     PkgStreamPtr stream = nullptr;
307     // Extract package to file or memory
308     if (unzipToFile_) {
309         ret = CreatePkgStream(stream, path + name + ".tmp", info->unpackedSize, PkgStream::PkgStreamType_Write);
310     } else {
311         ret = CreatePkgStream(stream, path + name + ".tmp", info->unpackedSize, PkgStream::PkgStreamType_MemoryMap);
312     }
313     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Create middle stream fail %s", name.c_str());
314 
315     ret = ExtractFile(name, stream);
316     PKG_CHECK(ret == PKG_SUCCESS, ClosePkgStream(stream); return ret, "Extract file fail %s", name.c_str());
317     return LoadPackageWithStream(path, fileIds, type, stream);
318 }
319 
LoadPackage(const std::string & packagePath,std::vector<std::string> & fileIds,PkgFile::PkgType type)320 int32_t PkgManagerImpl::LoadPackage(const std::string &packagePath, std::vector<std::string> &fileIds,
321     PkgFile::PkgType type)
322 {
323     PkgStreamPtr stream = nullptr;
324     int32_t ret = CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read);
325     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Create input stream fail %s", packagePath.c_str());
326     return LoadPackageWithStream(packagePath, fileIds, type, stream);
327 }
328 
LoadPackageWithStream(const std::string & packagePath,std::vector<std::string> & fileIds,PkgFile::PkgType type,PkgStreamPtr stream)329 int32_t PkgManagerImpl::LoadPackageWithStream(const std::string &packagePath,
330     std::vector<std::string> &fileIds, PkgFile::PkgType type, PkgStreamPtr stream)
331 {
332     int32_t ret = PKG_SUCCESS;
333     PkgFilePtr pkgFile = CreatePackage(stream, type, nullptr);
334     PKG_CHECK(pkgFile != nullptr, ClosePkgStream(stream);
335         return PKG_INVALID_PARAM, "Create package fail %s", packagePath.c_str());
336 
337     ret = pkgFile->LoadPackage(fileIds,
338         [this](const PkgInfoPtr info, const std::vector<uint8_t> &digest, const std::vector<uint8_t> &signature)->int {
339             return Verify(info->digestMethod, digest, signature);
340         });
341 
342     PKG_CHECK(ret == PKG_SUCCESS, delete pkgFile; return ret, "Load package fail %s", packagePath.c_str());
343     pkgFiles_.push_back(pkgFile);
344     return PKG_SUCCESS;
345 }
346 
ExtractFile(const std::string & name,PkgManager::StreamPtr output)347 int32_t PkgManagerImpl::ExtractFile(const std::string &name, PkgManager::StreamPtr output)
348 {
349     PKG_CHECK(output != nullptr, return PKG_INVALID_STREAM, "Invalid stream");
350     int32_t ret = PKG_INVALID_FILE;
351     PkgEntryPtr pkgEntry = GetPkgEntry(name);
352     if (pkgEntry != nullptr && pkgEntry->GetPkgFile() != nullptr) {
353         ret = pkgEntry->GetPkgFile()->ExtractFile(pkgEntry, PkgStreamImpl::ConvertPkgStream(output));
354     } else {
355         PKG_LOGE("Can not find file %s", name.c_str());
356     }
357     return ret;
358 }
359 
GetPackageInfo(const std::string & packagePath)360 const PkgInfo *PkgManagerImpl::GetPackageInfo(const std::string &packagePath)
361 {
362     for (auto iter : pkgFiles_) {
363         PkgFilePtr pkgFile = iter;
364         if (pkgFile != nullptr && pkgFile->GetPkgType() == PkgFile::PKG_TYPE_UPGRADE) {
365             return pkgFile->GetPkgInfo();
366         }
367     }
368     return nullptr;
369 }
370 
GetFileInfo(const std::string & path)371 const FileInfo *PkgManagerImpl::GetFileInfo(const std::string &path)
372 {
373     PkgEntryPtr pkgEntry = GetPkgEntry(path);
374     if (pkgEntry != nullptr) {
375         return pkgEntry->GetFileInfo();
376     }
377     return nullptr;
378 }
379 
GetPkgEntry(const std::string & fileId)380 PkgEntryPtr PkgManagerImpl::GetPkgEntry(const std::string &fileId)
381 {
382     // Find out pkgEntry by fileId.
383     for (auto iter : pkgFiles_) {
384         PkgFilePtr pkgFile = iter;
385         PkgEntryPtr pkgEntry = pkgFile->FindPkgEntry(fileId);
386         if (pkgEntry == nullptr) {
387             continue;
388         }
389         return pkgEntry;
390     }
391     return nullptr;
392 }
393 
CreatePkgStream(StreamPtr & stream,const std::string & fileName,size_t size,int32_t type)394 int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName, size_t size, int32_t type)
395 {
396     PkgStreamPtr pkgStream;
397     int32_t ret = CreatePkgStream(pkgStream, fileName, size, type);
398     PKG_CHECK(pkgStream != nullptr, return -1, "Failed to create stream");
399     stream = pkgStream;
400     return ret;
401 }
402 
CreatePkgStream(StreamPtr & stream,const std::string & fileName,const PkgBuffer & buffer)403 int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer)
404 {
405     PkgStreamPtr pkgStream = new MemoryMapStream(this, fileName, buffer, PkgStream::PkgStreamType_Buffer);
406     PKG_CHECK(pkgStream != nullptr, return -1, "Failed to create stream");
407     stream = pkgStream;
408     return PKG_SUCCESS;
409 }
410 
CreatePkgStream(StreamPtr & stream,const std::string & fileName,PkgStream::ExtractFileProcessor processor,const void * context)411 int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName,
412     PkgStream::ExtractFileProcessor processor, const void *context)
413 {
414     PkgStreamPtr pkgStream;
415     int32_t ret = CreatePkgStream(pkgStream, fileName, processor, context);
416     stream = pkgStream;
417     return ret;
418 }
419 
ClosePkgStream(StreamPtr & stream)420 void PkgManagerImpl::ClosePkgStream(StreamPtr &stream)
421 {
422     PkgStreamPtr pkgStream = static_cast<PkgStreamPtr>(stream);
423     ClosePkgStream(pkgStream);
424     stream = nullptr;
425 }
426 
CreatePkgStream(PkgStreamPtr & stream,const std::string & fileName,size_t size,int32_t type)427 int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string &fileName, size_t size, int32_t type)
428 {
429     // First assign a NULL value to the outgoing parameter 'stream',
430     // avoid the caller from passing in a non-empty scene
431     stream = nullptr;
432     if (type == PkgStream::PkgStreamType_Write || type == PkgStream::PkgStreamType_Read) {
433         static char const *modeFlags[] = { "rb", "wb+" };
434         int32_t ret = CheckFile(fileName);
435         PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to check file %s ", fileName.c_str());
436 
437         if (pkgStreams_.find(fileName) != pkgStreams_.end()) {
438             PkgStreamPtr mapStream = pkgStreams_[fileName];
439             mapStream->AddRef();
440             stream = mapStream;
441             return PKG_SUCCESS;
442         }
443 
444         FILE *file = nullptr;
445         file = fopen(fileName.c_str(), modeFlags[type]);
446         PKG_CHECK(file != nullptr, return PKG_INVALID_FILE, "Fail to open file %s ", fileName.c_str());
447         stream = new FileStream(this, fileName, file, type);
448     } else if (type == PkgStream::PkgStreamType_MemoryMap) {
449         size_t fileSize = size;
450         if (fileSize == 0) {
451             if (access(fileName.c_str(), 0) != 0) {
452                 return PKG_INVALID_FILE;
453             }
454             fileSize = GetFileSize(fileName);
455         }
456         PKG_CHECK(fileSize > 0, return PKG_INVALID_FILE, "Fail to check file size %s ", fileName.c_str());
457         uint8_t *memoryMap = MapMemory(fileName, fileSize);
458         PKG_CHECK(memoryMap != nullptr, return PKG_INVALID_FILE, "Fail to map memory %s ", fileName.c_str());
459         PkgBuffer buffer(memoryMap, fileSize);
460         stream = new MemoryMapStream(this, fileName, buffer);
461     } else {
462         return -1;
463     }
464     pkgStreams_[fileName] = stream;
465     return PKG_SUCCESS;
466 }
467 
CreatePkgStream(PkgStreamPtr & stream,const std::string & fileName,PkgStream::ExtractFileProcessor processor,const void * context)468 int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string &fileName,
469     PkgStream::ExtractFileProcessor processor, const void *context)
470 {
471     stream = new ProcessorStream(this, fileName, processor, context);
472     PKG_CHECK(stream != nullptr, return -1, "Failed to create stream");
473     return PKG_SUCCESS;
474 }
475 
ClosePkgStream(PkgStreamPtr & stream)476 void PkgManagerImpl::ClosePkgStream(PkgStreamPtr &stream)
477 {
478     PkgStreamPtr mapStream = stream;
479     if (mapStream == nullptr) {
480         return;
481     }
482 
483     auto iter = pkgStreams_.find(mapStream->GetFileName());
484     if (iter != pkgStreams_.end()) {
485         mapStream->DelRef();
486         if (mapStream->IsRef()) {
487             return;
488         }
489         pkgStreams_.erase(iter);
490     }
491     delete mapStream;
492     stream = nullptr;
493 }
494 
GetPkgTypeByName(const std::string & path)495 PkgFile::PkgType PkgManagerImpl::GetPkgTypeByName(const std::string &path)
496 {
497     int32_t pos = path.find_last_of('.');
498     if (pos < 0) {
499         return PkgFile::PKG_TYPE_NONE;
500     }
501     std::string postfix = path.substr(pos + 1, -1);
502     std::transform(postfix.begin(), postfix.end(), postfix.begin(), ::tolower);
503 
504     if (path.substr(pos + 1, -1).compare("bin") == 0) {
505         return PkgFile::PKG_TYPE_UPGRADE;
506     } else if (path.substr(pos + 1, -1).compare("zip") == 0) {
507         return PkgFile::PKG_TYPE_ZIP;
508     } else if (path.substr(pos + 1, -1).compare("lz4") == 0) {
509         return PkgFile::PKG_TYPE_LZ4;
510     } else if (path.substr(pos + 1, -1).compare("gz") == 0) {
511         return PkgFile::PKG_TYPE_GZIP;
512     }
513     return PkgFile::PKG_TYPE_NONE;
514 }
515 
VerifyPackage(const std::string & packagePath,const std::string & keyPath,const std::string & version,const PkgBuffer & digest,VerifyCallback verifyCallback)516 int32_t PkgManagerImpl::VerifyPackage(const std::string &packagePath, const std::string &keyPath,
517     const std::string &version, const PkgBuffer &digest, VerifyCallback verifyCallback)
518 {
519     int32_t ret = SetSignVerifyKeyName(keyPath);
520     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Invalid keyname");
521 
522     PkgStreamPtr stream = nullptr;
523     ret = CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read);
524     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Create input stream fail %s", packagePath.c_str());
525     size_t fileLen = stream->GetFileLength();
526     PKG_CHECK(fileLen > 0, ClosePkgStream(stream); return PKG_INVALID_FILE, "invalid file to load");
527 
528     PkgFile::PkgType type = GetPkgTypeByName(packagePath);
529     int8_t digestMethod = DigestAlgorithm::GetDigestMethod(version);
530     size_t digestLen = DigestAlgorithm::GetDigestLen(digestMethod);
531     size_t signatureLen = DigestAlgorithm::GetSignatureLen(digestMethod);
532     PKG_CHECK(digestLen == digest.length, return PKG_INVALID_PARAM, "Invalid digestLen");
533     std::vector<std::vector<uint8_t>> digestInfos(DIGEST_INFO_SIGNATURE + 1);
534     digestInfos[DIGEST_INFO_HAS_SIGN].resize(digestLen);
535     digestInfos[DIGEST_INFO_NO_SIGN].resize(digestLen);
536     digestInfos[DIGEST_INFO_SIGNATURE].resize(signatureLen);
537 
538     if (type != PkgFile::PKG_TYPE_UPGRADE) {
539         ret = GenerateFileDigest(stream, digestMethod, 0xf, digestInfos); // Grab all data
540         if ((digest.buffer != nullptr)
541             && (memcmp(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digest.buffer, digest.length) != 0)) {
542             PKG_LOGE("Fail to verify package");
543             ret = PKG_INVALID_SIGNATURE;
544         }
545         verifyCallback(ret, VERIFY_DIGEST_PERCENT);
546         if (ret == PKG_SUCCESS) {
547             ret = Verify(digestMethod, digestInfos[DIGEST_INFO_NO_SIGN], digestInfos[DIGEST_INFO_SIGNATURE]);
548             verifyCallback(ret, VERIFY_FINSH_PERCENT);
549         }
550     } else if (digest.buffer != nullptr) {
551         // update.bin include signature infomation, verify entire file.
552         ret = GenerateFileDigest(stream, digestMethod, DIGEST_FLAGS_HAS_SIGN, digestInfos);
553         if (memcmp(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digest.buffer, digest.length) != 0) {
554             PKG_LOGE("Fail to verify package %s", packagePath.c_str());
555             ret = PKG_INVALID_SIGNATURE;
556         }
557         verifyCallback(ret, VERIFY_FINSH_PERCENT);
558     }
559     ClosePkgStream(stream);
560     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Verify file %s fail", packagePath.c_str());
561     PKG_LOGW("Verify file %s success", packagePath.c_str());
562     return ret;
563 }
564 
GenerateFileDigest(PkgStreamPtr stream,uint8_t digestMethod,uint8_t flags,std::vector<std::vector<uint8_t>> & digestInfos,size_t hashBufferLen)565 int32_t PkgManagerImpl::GenerateFileDigest(PkgStreamPtr stream,
566     uint8_t digestMethod, uint8_t flags, std::vector<std::vector<uint8_t>> &digestInfos, size_t hashBufferLen)
567 {
568     size_t fileLen = (hashBufferLen == 0) ? stream->GetFileLength() : hashBufferLen;
569     size_t digestLen = DigestAlgorithm::GetDigestLen(digestMethod);
570     size_t signatureLen = DigestAlgorithm::GetSignatureLen(digestMethod);
571     // Check entire package
572     DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(digestMethod);
573     PKG_CHECK(algorithm != nullptr, return PKG_NOT_EXIST_ALGORITHM, "Invalid file %s", stream->GetFileName().c_str());
574     algorithm->Init();
575 
576     // Get verify algorithm
577     DigestAlgorithm::DigestAlgorithmPtr algorithmInner = PkgAlgorithmFactory::GetDigestAlgorithm(digestMethod);
578     PKG_CHECK(algorithm != nullptr, return PKG_NOT_EXIST_ALGORITHM, "Invalid file %s", stream->GetFileName().c_str());
579     algorithmInner->Init();
580 
581     size_t offset = 0;
582     size_t readLen = 0;
583     size_t needReadLen = fileLen;
584     size_t buffSize = BUFFER_SIZE;
585     PkgBuffer buff(buffSize);
586     if (flags & DIGEST_FLAGS_SIGNATURE) {
587         PKG_ONLY_CHECK(SIGN_TOTAL_LEN < fileLen, return PKG_INVALID_SIGNATURE);
588         needReadLen = fileLen - SIGN_TOTAL_LEN;
589     }
590     while (offset < needReadLen) {
591         PKG_ONLY_CHECK((needReadLen - offset) >= buffSize, buffSize = needReadLen - offset);
592         int32_t ret = stream->Read(buff, offset, buffSize, readLen);
593         PKG_CHECK(ret == PKG_SUCCESS, return ret, "read buffer fail %s", stream->GetFileName().c_str());
594         PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_HAS_SIGN, algorithm->Update(buff, readLen));
595         PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_NO_SIGN, algorithmInner->Update(buff, readLen));
596         offset += readLen;
597         PostDecodeProgress(POST_TYPE_VERIFY_PKG, readLen, nullptr);
598         readLen = 0;
599     }
600 
601     // Read last signatureLen
602     if (flags & DIGEST_FLAGS_SIGNATURE) {
603         readLen = 0;
604         int32_t ret = stream->Read(buff, offset, SIGN_TOTAL_LEN, readLen);
605         PKG_CHECK(ret == PKG_SUCCESS, return ret, "read buffer failed %s", stream->GetFileName().c_str());
606         PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_HAS_SIGN, algorithm->Update(buff, readLen));
607         PkgBuffer data(SIGN_TOTAL_LEN);
608         PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_NO_SIGN, algorithmInner->Update(data, SIGN_TOTAL_LEN));
609     }
610     PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_HAS_SIGN,
611         PkgBuffer result(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digestLen); algorithm->Final(result));
612     PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_NO_SIGN,
613         PkgBuffer result(digestInfos[DIGEST_INFO_NO_SIGN].data(), digestLen); algorithmInner->Final(result));
614     if (flags & DIGEST_FLAGS_SIGNATURE) {
615         if (digestMethod == PKG_DIGEST_TYPE_SHA256) {
616             PKG_CHECK(!memcpy_s(digestInfos[DIGEST_INFO_SIGNATURE].data(), signatureLen, buff.buffer, signatureLen),
617                 return PKG_NONE_MEMORY, "GenerateFileDigest memcpy failed");
618         } else {
619             PKG_CHECK(!memcpy_s(digestInfos[DIGEST_INFO_SIGNATURE].data(), signatureLen, buff.buffer + SIGN_SHA256_LEN,
620                 signatureLen), return PKG_NONE_MEMORY, "GenerateFileDigest memcpy failed");
621         }
622     }
623     return PKG_SUCCESS;
624 }
625 
Verify(uint8_t digestMethod,const std::vector<uint8_t> & digest,const std::vector<uint8_t> & signature)626 int32_t PkgManagerImpl::Verify(uint8_t digestMethod, const std::vector<uint8_t> &digest,
627     const std::vector<uint8_t> &signature)
628 {
629     SignAlgorithm::SignAlgorithmPtr signAlgorithm = PkgAlgorithmFactory::GetVerifyAlgorithm(
630         signVerifyKeyName_, digestMethod);
631     PKG_CHECK(signAlgorithm != nullptr, return PKG_INVALID_SIGNATURE, "Invalid sign algo");
632     return signAlgorithm->VerifyBuffer(digest, signature);
633 }
634 
Sign(PkgStreamPtr stream,size_t offset,const PkgInfoPtr & info)635 int32_t PkgManagerImpl::Sign(PkgStreamPtr stream, size_t offset, const PkgInfoPtr &info)
636 {
637     PKG_CHECK(info != nullptr, return PKG_INVALID_PARAM, "Invalid param");
638     if (info->signMethod == PKG_SIGN_METHOD_NONE) {
639         return PKG_SUCCESS;
640     }
641 
642     size_t digestLen = DigestAlgorithm::GetDigestLen(info->digestMethod);
643     std::vector<std::vector<uint8_t>> digestInfos(DIGEST_INFO_SIGNATURE + 1);
644     digestInfos[DIGEST_INFO_HAS_SIGN].resize(digestLen);
645 
646     int32_t ret = GenerateFileDigest(stream, info->digestMethod, DIGEST_FLAGS_HAS_SIGN, digestInfos);
647     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to generate signature %s", stream->GetFileName().c_str());
648     SignAlgorithm::SignAlgorithmPtr signAlgorithm =
649         PkgAlgorithmFactory::GetSignAlgorithm(signVerifyKeyName_, info->signMethod, info->digestMethod);
650     PKG_CHECK(signAlgorithm != nullptr, return PKG_INVALID_SIGNATURE, "Invalid sign algo");
651 
652     size_t signLen = DigestAlgorithm::GetSignatureLen(info->digestMethod);
653     std::vector<uint8_t> signedData(signLen, 0);
654     // Clear buffer
655     PkgBuffer signBuffer(signedData);
656     ret = stream->Write(signBuffer, signLen, offset);
657     size_t signDataLen = 0;
658     signedData.clear();
659     PkgBuffer digest(digestInfos[DIGEST_INFO_HAS_SIGN].data(), digestLen);
660     ret = signAlgorithm->SignBuffer(digest, signedData, signDataLen);
661     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to SignBuffer %s", stream->GetFileName().c_str());
662     PKG_CHECK(signDataLen <= signLen, return PKG_INVALID_SIGNATURE, "SignData len %zu more %zu", signDataLen, signLen);
663     PKG_LOGI("Signature %zu %zu %s", offset, signDataLen, stream->GetFileName().c_str());
664     ret = stream->Write(signBuffer, signDataLen, offset);
665     stream->Flush(offset + signedData.size());
666     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to Write signature %s", stream->GetFileName().c_str());
667     PKG_LOGW("Sign file %s success", stream->GetFileName().c_str());
668     return ret;
669 }
670 
SetSignVerifyKeyName(const std::string & keyName)671 int32_t PkgManagerImpl::SetSignVerifyKeyName(const std::string &keyName)
672 {
673     if (access(keyName.c_str(), 0) != 0) {
674         return PKG_INVALID_FILE;
675     }
676     signVerifyKeyName_ = keyName;
677     return PKG_SUCCESS;
678 }
679 
DecompressBuffer(FileInfoPtr info,const PkgBuffer & data,StreamPtr output) const680 int32_t PkgManagerImpl::DecompressBuffer(FileInfoPtr info, const PkgBuffer &data, StreamPtr output) const
681 {
682     PKG_CHECK(info != nullptr && data.buffer != nullptr && output != nullptr, return PKG_INVALID_PARAM,
683         "Param is null");
684     PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info);
685     PKG_CHECK(algorithm != nullptr, return PKG_INVALID_PARAM, "Can not get algorithm for %s", info->identity.c_str());
686 
687     std::shared_ptr<MemoryMapStream> inStream = std::make_shared<MemoryMapStream>(
688         (PkgManager::PkgManagerPtr)this, info->identity, data, PkgStream::PkgStreamType_Buffer);
689     PKG_CHECK(inStream != nullptr, return PKG_INVALID_PARAM, "Can not create stream for %s", info->identity.c_str());
690     PkgAlgorithmContext context = {{0, 0}, {data.length, 0}, 0, info->digestMethod};
691     int32_t ret = algorithm->Unpack(inStream.get(), PkgStreamImpl::ConvertPkgStream(output), context);
692     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail Decompress for %s", info->identity.c_str());
693     PKG_LOGI("packedSize: %zu unpackedSize: %zu ", data.length, context.unpackedSize);
694     PkgStreamImpl::ConvertPkgStream(output)->Flush(context.unpackedSize);
695     info->packedSize = context.packedSize;
696     info->unpackedSize = context.unpackedSize;
697     algorithm->UpdateFileInfo(info);
698     return PKG_SUCCESS;
699 }
700 
CompressBuffer(FileInfoPtr info,const PkgBuffer & data,StreamPtr output) const701 int32_t PkgManagerImpl::CompressBuffer(FileInfoPtr info, const PkgBuffer &data, StreamPtr output) const
702 {
703     PKG_CHECK(info != nullptr && data.buffer != nullptr && output != nullptr,
704               return PKG_INVALID_PARAM, "Param is null ");
705     PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info);
706     PKG_CHECK(algorithm != nullptr, return PKG_INVALID_PARAM, "Can not get algorithm for %s", info->identity.c_str());
707 
708     std::shared_ptr<MemoryMapStream> inStream = std::make_shared<MemoryMapStream>(
709         (PkgManager::PkgManagerPtr)this, info->identity, data, PkgStream::PkgStreamType_Buffer);
710     PKG_CHECK(inStream != nullptr, return PKG_INVALID_PARAM, "Can not create stream for %s", info->identity.c_str());
711     PkgAlgorithmContext context = {{0, 0}, {0, data.length}, 0, info->digestMethod};
712     int32_t ret = algorithm->Pack(inStream.get(), PkgStreamImpl::ConvertPkgStream(output), context);
713     PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail Decompress for %s", info->identity.c_str());
714     PKG_LOGI("packedSize: %zu unpackedSize: %zu ", context.packedSize, context.unpackedSize);
715     PkgStreamImpl::ConvertPkgStream(output)->Flush(context.packedSize);
716     info->packedSize = context.packedSize;
717     info->unpackedSize = context.unpackedSize;
718     return PKG_SUCCESS;
719 }
720 
PostDecodeProgress(int type,size_t writeDataLen,const void * context)721 void PkgManagerImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context)
722 {
723     if (decodeProgress_ != nullptr) {
724         decodeProgress_(type, writeDataLen, context);
725     }
726 }
727 } // namespace hpackage
728