• 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 #include <fstream>
16 #include <sys/mount.h>
17 #include "i18n_hilog.h"
18 #include "signature_verifier.h"
19 #include "utils.h"
20 #include "upgrade_utils.h"
21 
22 namespace OHOS {
23 namespace Global {
24 namespace I18n {
25 const std::string UpgradeUtils::CERT_FILE = "CERT.ENC";
26 const std::string UpgradeUtils::VERIFY_FILE = "CERT.SF";
27 const std::string UpgradeUtils::MANIFEST_FILE = "MANIFEST.MF";
28 const size_t UpgradeUtils::VERSION_SIZE = 4;
29 
CheckIfUpdateNecessary(const std::string & updateVersionPath,const std::string & localVersionPath)30 bool UpgradeUtils::CheckIfUpdateNecessary(const std::string& updateVersionPath, const std::string& localVersionPath)
31 {
32     std::string versionUpdate = LoadFileVersion(updateVersionPath);
33     std::string versionLocal = LoadFileVersion(localVersionPath);
34     HILOG_INFO_I18N("UpgradeUtils::CheckIfUpdateNecessary: versionUpdate(%{public}s) versionLocal(%{public}s).",
35         versionUpdate.c_str(), versionLocal.c_str());
36 
37     if (versionLocal.empty() || versionUpdate.empty()) {
38         return false;
39     }
40     return CompareVersion(versionLocal, versionUpdate);
41 }
42 
CheckFileIntegrity(const std::string & cfgPath,const std::string & pubkeyPath,std::vector<std::string> & filesList)43 bool UpgradeUtils::CheckFileIntegrity(const std::string& cfgPath, const std::string& pubkeyPath,
44     std::vector<std::string>& filesList)
45 {
46     std::string certPath = cfgPath + CERT_FILE;
47     std::string verifyPath = cfgPath + VERIFY_FILE;
48     std::string manifestPath = cfgPath + MANIFEST_FILE;
49     if (!SignatureVerifier::VerifyCertFile(certPath, verifyPath, pubkeyPath, manifestPath)) {
50         HILOG_ERROR_I18N("UpgradeUtils::CheckFileIntegrity: VerifyCertFile error.");
51         return false;
52     }
53     return SignatureVerifier::VerifyUpdateFile(cfgPath, manifestPath, filesList);
54 }
55 
CopyDataFile(const std::string & srcPath,const std::string & dstPath,const std::vector<std::string> & filesList)56 bool UpgradeUtils::CopyDataFile(const std::string& srcPath, const std::string& dstPath,
57     const std::vector<std::string>& filesList)
58 {
59     if (!IsDirExist(dstPath.c_str())) {
60         HILOG_ERROR_I18N("UpgradeUtils::CopyDataFile: dstPath is not exist.");
61         return false;
62     }
63 
64     std::filesystem::path dstPathDir(dstPath);
65     ClearDir(dstPathDir);
66 
67     bool copySuccess = true;
68     for (const auto& file : filesList) {
69         std::filesystem::path srcFile = std::filesystem::path(srcPath) / file;
70         std::filesystem::path dstFile = std::filesystem::path(dstPath) / file;
71         if (!CopySingleFile(srcFile, dstFile)) {
72             HILOG_ERROR_I18N("UpgradeUtils::CopyDataFile: Copy failed for %{public}s.", file.c_str());
73             copySuccess = false;
74             break;
75         }
76     }
77 
78     if (!copySuccess) {
79         HILOG_ERROR_I18N("UpgradeUtils::CopyDataFile: CopyDataFile error, clearing the safe directory...");
80         ClearDir(dstPathDir);
81     }
82 
83     return copySuccess;
84 }
85 
FileDirMount(const std::string & srcDirPath,const std::string & dstDirPath)86 bool UpgradeUtils::FileDirMount(const std::string& srcDirPath, const std::string& dstDirPath)
87 {
88     if (!IsDirExist(srcDirPath.c_str()) || !IsDirExist(dstDirPath.c_str())) {
89         HILOG_ERROR_I18N("UpgradeUtils::FileDirMount: srcDirPath or dstDirPath not exist.");
90         return false;
91     }
92 
93     std::string cotaOpkeyVersionDir = srcDirPath;
94     std::string custOpkeyVersionDir = dstDirPath;
95 
96     if (mount(cotaOpkeyVersionDir.c_str(), custOpkeyVersionDir.c_str(), nullptr, MS_BIND, nullptr) != 0) {
97         HILOG_ERROR_I18N("UpgradeUtils::FileDirMount: Fail to mount, errno %{public}s.", strerror(errno));
98         return false;
99     }
100 
101     if (mount(nullptr, custOpkeyVersionDir.c_str(), nullptr, MS_REMOUNT | MS_BIND | MS_RDONLY, nullptr) != 0) {
102         HILOG_ERROR_I18N("UpgradeUtils::FileDirMount: Fail to mount read only, errno %{public}s.", strerror(errno));
103         if (umount(custOpkeyVersionDir.c_str()) != 0) {
104             HILOG_ERROR_I18N("UpgradeUtils::FileDirMount: Error during unmount, errno %{public}s.", strerror(errno));
105         }
106         return false;
107     }
108 
109     HILOG_INFO_I18N("UpgradeUtils::FileDirMount: Succeeded in mounting the file path.");
110     return true;
111 }
112 
LoadFileVersion(const std::string & versionPath)113 std::string UpgradeUtils::LoadFileVersion(const std::string& versionPath)
114 {
115     std::string version;
116     char* result = realpath(versionPath.c_str(), nullptr);
117     if (result == nullptr) {
118         HILOG_ERROR_I18N("UpgradeUtils::LoadFileVersion: realpath error: %{public}s.", strerror(errno));
119         return version;
120     }
121     std::ifstream file(result);
122     free(result);
123     result = nullptr;
124     if (!file.is_open()) {
125         HILOG_ERROR_I18N("UpgradeUtils::LoadFileVersion: open version file failed.");
126         return version;
127     }
128     std::string line;
129     std::vector<std::string> strs;
130     while (std::getline(file, line)) {
131         Split(line, "=", strs);
132         if (strs.size() < SignatureVerifier::MIN_SIZE) {
133             continue;
134         }
135         if (strs[0] == "version") {
136             version = trim(strs[1]);
137             break;
138         }
139     }
140     return version;
141 }
142 
143 // compare version
CompareVersion(const std::string & preVersion,const std::string & curVersion)144 bool UpgradeUtils::CompareVersion(const std::string& preVersion, const std::string& curVersion)
145 {
146     std::vector<std::string> preVersionStr;
147     std::vector<std::string> curVersionStr;
148     Split(preVersion, ".", preVersionStr);
149     Split(curVersion, ".", curVersionStr);
150     if (curVersionStr.size() != VERSION_SIZE || preVersionStr.size() != VERSION_SIZE) {
151         HILOG_ERROR_I18N("UpgradeUtils::CompareVersion: Parse version failed.");
152         return false;
153     }
154     for (size_t i = 0; i < VERSION_SIZE; i++) {
155         int32_t status = 0;
156         int32_t preVersionNum = ConvertString2Int(preVersionStr.at(i), status);
157         if (status != 0) {
158             HILOG_ERROR_I18N("UpgradeUtils::CompareVersion: preVersionStr convert to int failed.");
159             return false;
160         }
161         int32_t curVersionNum = ConvertString2Int(curVersionStr.at(i), status);
162         if (status != 0) {
163             HILOG_ERROR_I18N("UpgradeUtils::CompareVersion: curVersionStr convert to int failed.");
164             return false;
165         }
166         if (preVersionNum < curVersionNum) {
167             return true;
168         } else if (preVersionNum > curVersionNum) {
169             return false;
170         }
171     }
172     return false;
173 }
174 
CopySingleFile(const std::filesystem::path & srcFile,const std::filesystem::path & dstFile)175 bool UpgradeUtils::CopySingleFile(const std::filesystem::path& srcFile, const std::filesystem::path& dstFile)
176 {
177     if (!FileExist(srcFile.c_str())) {
178         HILOG_ERROR_I18N("UpgradeUtils::copySingleFile: Source file does not exist.");
179         return false;
180     }
181 
182     if (!EnsureDirectoryExists(dstFile.parent_path())) {
183         HILOG_ERROR_I18N("UpgradeUtils::copySingleFile: Target file dir not exist.");
184         return false;
185     }
186     if (!FileCopy(srcFile.c_str(), dstFile.c_str())) {
187         HILOG_ERROR_I18N("UpgradeUtils::copySingleFile: Failed to copy file.");
188         return false;
189     }
190     return true;
191 }
192 
EnsureDirectoryExists(const std::filesystem::path & dirPath)193 bool UpgradeUtils::EnsureDirectoryExists(const std::filesystem::path& dirPath)
194 {
195     std::error_code errCode;
196     if (!std::filesystem::exists(dirPath)) {
197         std::filesystem::create_directories(dirPath, errCode);
198         if (errCode) {
199             HILOG_ERROR_I18N("UpgradeUtils::EnsureDirectoryExists: failed to create directory, Error %{public}s",
200                 errCode.message().c_str());
201             return false;
202         }
203     }
204     return true;
205 }
206 }
207 }
208 }