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