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