• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_update_verify.h"
17 #include "cert_verify.h"
18 #include "directory_ex.h"
19 #include "diff_patch/diff_patch_interface.h" // update diff interface
20 #include "hash_data_verifier.h"
21 #include "log/log.h"
22 #include "json_node.h"
23 #include "openssl/sha.h"
24 #include "parameters.h"
25 #include "scope_guard.h"
26 #include "utils.h"
27 #include "module_constants.h"
28 #include "module_file.h"
29 #include "module_utils.h"
30 
31 namespace OHOS {
32 namespace SysInstaller {
33 using namespace Hpackage;
34 using namespace Updater;
35 
36 namespace {
GetHmpType(const JsonNode & root,std::string & type)37 bool GetHmpType(const JsonNode &root, std::string &type)
38 {
39     const JsonNode &typeJson = root["type"];
40     std::optional<std::string> hmpType = typeJson.As<std::string>();
41     if (!hmpType.has_value()) {
42         LOG(ERROR) << "HmpInfo: Failed to get type val";
43         return false;
44     }
45     type = hmpType.value();
46     return true;
47 }
48 
CheckApiVersion(const std::string & apiVersion)49 bool CheckApiVersion(const std::string &apiVersion)
50 {
51     if (apiVersion.empty()) {
52         LOG(INFO) << "apiVersion is empty, default is true.";
53         return true;
54     }
55     int sysApiVersion = GetDeviceApiVersion();
56     int hmpApiVersion = Utils::String2Int<int>(apiVersion, Utils::N_DEC);
57     if (hmpApiVersion <= sysApiVersion) {
58         return true;
59     }
60     LOG(ERROR) << "sysApiVersion: " << sysApiVersion << "; hmpApiVersion: " << hmpApiVersion;
61     return false;
62 }
63 
CheckSaSdkVersion(const std::string & saSdkVersion)64 bool CheckSaSdkVersion(const std::string &saSdkVersion)
65 {
66     //sasdk_M.S.F.B
67     if (saSdkVersion.empty()) {
68         LOG(INFO) << "saSdkVersion is empty, default is true.";
69         return true;
70     }
71     std::vector<std::string> saSdkVersionVec {};
72     std::string sysSaSdkVersion = GetDeviceSaSdkVersion();
73     if (!ParseVersion(sysSaSdkVersion, "_", saSdkVersionVec)) {
74         LOG(ERROR) << "ParseVersion sysSaSdkVersion failed: " << sysSaSdkVersion;
75         return false;
76     }
77     std::vector<std::string> hmpVersionVec {};
78     if (!ParseVersion(saSdkVersion, "_", hmpVersionVec)) {
79         LOG(ERROR) << "ParseVersion hmpSaSdkVersion failed: " << saSdkVersion;
80         return false;
81     }
82     if (!CompareSaSdkVersion(saSdkVersionVec, hmpVersionVec)) {
83         LOG(ERROR) << "saSdkVersion compare fail, sys:" << sysSaSdkVersion << "; hmp:" << saSdkVersion;
84         return false;
85     }
86     return true;
87 }
88 
GetPackInfoVer(const JsonNode & root,const std::string & key,std::string & version)89 bool GetPackInfoVer(const JsonNode &root, const std::string &key, std::string &version)
90 {
91     const JsonNode &package = root["package"];
92     std::optional<std::string> tmpVersion = package[key].As<std::string>();
93     if (!tmpVersion.has_value()) {
94         LOG(ERROR) << "count get version val";
95         return false;
96     }
97     version = tmpVersion.value();
98     LOG(INFO) << key << " " << version;
99     return true;
100 }
101 
GetPackageType(const JsonNode & root,std::string & type)102 bool GetPackageType(const JsonNode &root, std::string &type)
103 {
104     const JsonNode &typeJson = root["packageType"];
105     std::optional<std::string> hmpPackageType = typeJson.As<std::string>();
106     if (!hmpPackageType.has_value()) {
107         LOG(ERROR) << "HmpInfo: Failed to get type val";
108         return false;
109     }
110     type = hmpPackageType.value();
111     return true;
112 }
113 }
114 
CheckPackInfoVer(const std::string & pkgPackInfoPath)115 bool CheckPackInfoVer(const std::string &pkgPackInfoPath)
116 {
117     std::string packInfo = GetContentFromZip(pkgPackInfoPath, PACK_INFO_NAME);
118     JsonNode root(packInfo);
119     std::string type;
120     if (!GetHmpType(root, type)) {
121         return false;
122     }
123     LOG(INFO) << pkgPackInfoPath << "; type = " << type;
124     std::string apiVersion;
125     if (type == HMP_APP_TYPE && GetPackInfoVer(root, HMP_API_VERSION, apiVersion)) {
126         return CheckApiVersion(apiVersion);
127     }
128     std::string saSdkVersion;
129     if ((type == HMP_SA_TYPE || type == HMP_SA_TYPE_OLD) &&
130         GetPackInfoVer(root, HMP_SA_SDK_VERSION, saSdkVersion)) {
131         return CheckSaSdkVersion(saSdkVersion);
132     }
133     if ((type == HMP_MIX_TYPE || type == HMP_TRAIN_TYPE) &&
134         GetPackInfoVer(root, HMP_SA_SDK_VERSION, saSdkVersion) &&
135         GetPackInfoVer(root, HMP_API_VERSION, apiVersion)) {
136         return CheckApiVersion(apiVersion) && CheckSaSdkVersion(saSdkVersion);
137     }
138     return false;
139 }
140 
CleanErrDir(const std::string & fpInfo)141 void CleanErrDir(const std::string &fpInfo)
142 {
143     if (fpInfo.find(UPDATE_ACTIVE_DIR) != std::string::npos ||
144         fpInfo.find(UPDATE_BACKUP_DIR) != std::string::npos) {
145         LOG(INFO) << "delete err dir :"<< fpInfo;
146         ForceRemoveDirectory(fpInfo.substr(0, fpInfo.rfind("/")));
147     }
148 }
149 
IsIncrementPackage(const std::string & pkgPackInfoPath)150 bool IsIncrementPackage(const std::string &pkgPackInfoPath)
151 {
152     std::string packInfo = GetContentFromZip(pkgPackInfoPath, PACK_INFO_NAME);
153     JsonNode root(packInfo);
154     std::string packageType;
155     if (!GetPackageType(root, packageType)) {
156         LOG(INFO) << pkgPackInfoPath << " not support increment";
157         return false;
158     }
159     LOG(INFO) << pkgPackInfoPath << "; packageType = " << packageType;
160     if (packageType == HMP_INCR_PACKAGE_TYPE) {
161         return true;
162     }
163     return false;
164 }
165 
ReadHashFromPackInfo(const std::string & pkgPackInfoPath,std::string & hashValue)166 bool ReadHashFromPackInfo(const std::string &pkgPackInfoPath, std::string &hashValue)
167 {
168     std::string packInfo = GetContentFromZip(pkgPackInfoPath, PACK_INFO_NAME);
169     JsonNode root(packInfo);
170     const JsonNode &imageHashJson = root["imageHash"];
171     std::optional<std::string> imageHash = imageHashJson.As<std::string>();
172     if (!imageHash.has_value()) {
173         LOG(ERROR) << "HmpInfo: Failed to get imageHash val";
174         return false;
175     }
176     hashValue = imageHash.value();
177     return true;
178 }
179 
RestorePackage(const std::string & dstFile,const std::string & sourceFile)180 bool RestorePackage(const std::string &dstFile, const std::string &sourceFile)
181 {
182     LOG(INFO) << "Start restore file " << dstFile << "; source is " << sourceFile;
183     Timer timer;
184     if (dstFile.find(UPDATE_INSTALL_DIR) == std::string::npos) {
185         LOG(ERROR) << dstFile << " is not installDir, restore fail.";
186         return false;
187     }
188     std::string diffFile = ExtractFilePath(dstFile) + IMG_DIFF_FILE_NAME;
189     std::string restoreImgFile = ExtractFilePath(dstFile) + IMG_FILE_NAME;
190     if (!CheckPathExists(diffFile) || CheckPathExists(restoreImgFile)) {
191         LOG(ERROR) << diffFile << " is not exist or dest image exists, restore fail.";
192         return false;
193     }
194     if (!CheckPathExists(sourceFile)) {
195         LOG(ERROR) << sourceFile << " is not exist.";
196         return false;
197     }
198     int32_t result = Updater::ApplyPatch(diffFile, sourceFile, restoreImgFile);
199     if (result != 0) {
200         LOG(ERROR) << "Restore package failed, ret is " << result << " err:" << strerror(errno);
201         return false;
202     }
203     if (unlink(diffFile.c_str()) != 0) {
204         LOG(WARNING) << "Failed to unlink " << diffFile << " err:" << strerror(errno);
205     }
206     LOG(INFO) << "restore image succ, restore timer:" << timer;
207 
208     std::string hashValue;
209     if (!ReadHashFromPackInfo(dstFile, hashValue)) {
210         LOG(ERROR) << "read hash from pack.info fail";
211         return false;
212     }
213     LOG(INFO) << "read hash, " << hashValue;
214     std::string calculateHash;
215     if (!CalculateSHA256(restoreImgFile, calculateHash)) {
216         LOG(ERROR) << "calculate restore image hash fail";
217         return false;
218     }
219     return (hashValue == calculateHash);
220 }
221 
CalculateSHA256(const std::string & filePath,std::string & digest)222 bool CalculateSHA256(const std::string &filePath, std::string &digest)
223 {
224     char realPath[PATH_MAX] = {0};
225     if (realpath(filePath.c_str(), realPath) == nullptr) {
226         LOG(ERROR) << "invalid file path, " << filePath;
227         return false;
228     }
229     std::ifstream readFile(realPath, std::ios::binary);
230     if (!readFile) {
231         LOG(ERROR) << "open file fail, " << realPath;
232         return false;
233     }
234     SHA256_CTX sha256Context;
235     SHA256_Init(&sha256Context);
236     constexpr int32_t bufferSize = 4096;
237     char buffer[bufferSize] = {0};
238     while (!readFile.eof()) {
239         readFile.read(buffer, sizeof(buffer));
240         SHA256_Update(&sha256Context, buffer, readFile.gcount());
241     }
242     uint8_t digestBuffer[SHA256_DIGEST_LENGTH] = {0};
243     SHA256_Final(digestBuffer, &sha256Context);
244     digest = Utils::ConvertSha256Hex(digestBuffer, SHA256_DIGEST_LENGTH);
245     std::transform(digest.begin(), digest.end(), digest.begin(), ::toupper);
246     LOG(INFO) << "CalculateSHA256, " << digest;
247     return true;
248 }
249 }
250 }