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