1 /*
2 * Copyright (c) 2023 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
16 #include "module_file_repository.h"
17
18 #include "directory_ex.h"
19 #include "log/log.h"
20 #include "module_constants.h"
21 #include "module_utils.h"
22
23 namespace OHOS {
24 namespace SysInstaller {
25 using namespace Updater;
26 using std::string;
27
~ModuleFileRepository()28 ModuleFileRepository::~ModuleFileRepository()
29 {
30 Clear();
31 }
32
GetInstance()33 ModuleFileRepository &ModuleFileRepository::GetInstance()
34 {
35 static ModuleFileRepository instance;
36 return instance;
37 }
38
InitRepository(const std::unordered_set<int32_t> & saIdSet)39 void ModuleFileRepository::InitRepository(const std::unordered_set<int32_t> &saIdSet)
40 {
41 string allPath[] = {MODULE_PREINSTALL_DIR, UPDATE_INSTALL_DIR, UPDATE_ACTIVE_DIR};
42 for (string &path : allPath) {
43 std::vector<string> files;
44 GetDirFiles(path, files);
45 std::unordered_map<int32_t, ModuleFile> fileMap;
46 for (string &file : files) {
47 ProcessFile(saIdSet, path, file, fileMap);
48 }
49 moduleFileMap_.emplace(path, std::move(fileMap));
50 }
51 }
52
ProcessFile(const std::unordered_set<int32_t> & saIdSet,const string & path,const string & file,std::unordered_map<int32_t,ModuleFile> & fileMap) const53 void ModuleFileRepository::ProcessFile(const std::unordered_set<int32_t> &saIdSet, const string &path,
54 const string &file, std::unordered_map<int32_t, ModuleFile> &fileMap) const
55 {
56 if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
57 return;
58 }
59 std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
60 if (moduleFile == nullptr || saIdSet.find(moduleFile->GetSaId()) == saIdSet.end()) {
61 return;
62 }
63 string pubkey = moduleFile->GetPublicKey();
64 if (path != MODULE_PREINSTALL_DIR) {
65 pubkey = GetPublicKey(moduleFile->GetSaId());
66 if (!CheckFilePath(*moduleFile, path)) {
67 return;
68 }
69 if (!ModuleFile::VerifyModulePackageSign(file)) {
70 LOG(ERROR) << "verify sign failed of " << file;
71 return;
72 }
73 }
74 if (moduleFile->GetImageStat().has_value() && !moduleFile->VerifyModuleVerity(pubkey)) {
75 LOG(ERROR) << "verify verity failed of " << file;
76 return;
77 }
78 fileMap.emplace(moduleFile->GetSaId(), std::move(*moduleFile));
79 }
80
GetModuleFile(const std::string & pathPrefix,const int32_t saId) const81 std::unique_ptr<ModuleFile> ModuleFileRepository::GetModuleFile(const std::string &pathPrefix, const int32_t saId) const
82 {
83 auto mapIter = moduleFileMap_.find(pathPrefix);
84 if (mapIter == moduleFileMap_.end()) {
85 LOG(ERROR) << "Invalid path prefix " << pathPrefix;
86 return nullptr;
87 }
88 std::unordered_map<int32_t, ModuleFile> fileMap = mapIter->second;
89 auto fileIter = fileMap.find(saId);
90 if (fileIter == fileMap.end()) {
91 LOG(INFO) << saId << " not found in " << pathPrefix;
92 return nullptr;
93 }
94 ModuleFile file = fileIter->second;
95 return std::make_unique<ModuleFile>(std::move(file));
96 }
97
IsPreInstalledModule(const ModuleFile & moduleFile) const98 bool ModuleFileRepository::IsPreInstalledModule(const ModuleFile &moduleFile) const
99 {
100 std::unique_ptr<ModuleFile> preInstalledModule = GetModuleFile(MODULE_PREINSTALL_DIR, moduleFile.GetSaId());
101 if (preInstalledModule == nullptr) {
102 return false;
103 }
104 return preInstalledModule->GetPath() == moduleFile.GetPath();
105 }
106
GetPublicKey(const int32_t saId) const107 string ModuleFileRepository::GetPublicKey(const int32_t saId) const
108 {
109 std::unique_ptr<ModuleFile> preInstalledModule = GetModuleFile(MODULE_PREINSTALL_DIR, saId);
110 if (preInstalledModule == nullptr) {
111 return "";
112 }
113 return preInstalledModule->GetPublicKey();
114 }
115
CheckFilePath(const ModuleFile & moduleFile,const string & prefix) const116 bool ModuleFileRepository::CheckFilePath(const ModuleFile &moduleFile, const string &prefix) const
117 {
118 std::unique_ptr<ModuleFile> preInstalledModule = GetModuleFile(MODULE_PREINSTALL_DIR, moduleFile.GetSaId());
119 if (preInstalledModule == nullptr) {
120 return false;
121 }
122 string prePath = preInstalledModule->GetPath();
123 string curPath = moduleFile.GetPath();
124 return prePath.substr(strlen(MODULE_PREINSTALL_DIR), prePath.length()) ==
125 curPath.substr(prefix.length(), curPath.length());
126 }
127
Clear()128 void ModuleFileRepository::Clear()
129 {
130 for (auto mapIter = moduleFileMap_.begin(); mapIter != moduleFileMap_.end(); ++mapIter) {
131 std::unordered_map<int32_t, ModuleFile> &fileMap = mapIter->second;
132 for (auto fileIter = fileMap.begin(); fileIter != fileMap.end(); ++fileIter) {
133 fileIter->second.ClearVerifiedData();
134 }
135 fileMap.clear();
136 }
137 moduleFileMap_.clear();
138 }
139 } // SysInstaller
140 } // namespace OHOS