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 <filesystem>
16 #include <string>
17 #include <sys/mount.h>
18 #include "i18n_hilog.h"
19 #include "signature_verifier.h"
20 #include "utils.h"
21 
22 
23 namespace OHOS {
24 namespace Global {
25 namespace I18n {
26 namespace {
27 const std::string CUST_GLOBAL_CARRIER_DIR = "/system/etc/LIBPHONENUMBER/mount_dir/";
28 const std::string VERSION_FILE = "version.txt";
29 const std::string CERT_FILE = "CERT.ENC";
30 const std::string VERIFY_FILE = "CERT.SF";
31 const std::string MANIFEST_FILE = "MANIFEST.MF";
32 const std::string SUB_TYPE = "generic";
33 const std::string CFG_PATH =
34     "/data/service/el1/public/update/param_service/install/system/etc/LIBPHONENUMBER/generic/";
35 const std::string LOCALE_PATH = "/system/etc/LIBPHONENUMBER/generic/";
36 const std::string SAFE_PATH = "/data/service/el1/public/i18n/libphonenumber/";
37 const std::string PUBKEY_NAME = "hota_i18n_upgrade_v1.pem";
38 const std::vector<std::string> DATA_FILES = {"GeocodingInfo", "MetadataInfo"};
39 }
40 
Mount()41 bool Mount()
42 {
43     if (!IsDirExist(CUST_GLOBAL_CARRIER_DIR.c_str()) ||
44         !IsDirExist(SAFE_PATH.c_str())) {
45         HILOG_ERROR_I18N("Mount: CUST_GLOBAL_CARRIER_DIR or CFG_PATH not exist");
46         return false;
47     }
48 
49     std::string cotaOpkeyVersionDir = SAFE_PATH;
50     std::string custOpkeyVersionDir = CUST_GLOBAL_CARRIER_DIR;
51 
52     if (mount(cotaOpkeyVersionDir.c_str(), custOpkeyVersionDir.c_str(), nullptr, MS_BIND, nullptr) != 0) {
53         HILOG_ERROR_I18N("Mount: fail to mount: opkey(%{public}s) errno(%{public}s)",
54             cotaOpkeyVersionDir.c_str(), strerror(errno));
55         return false;
56     } else {
57         HILOG_INFO_I18N("Mount: success to mount cotaDir to custDir: opkey(%{public}s)", cotaOpkeyVersionDir.c_str());
58     }
59     return true;
60 }
61 
CopyDataFile()62 void CopyDataFile()
63 {
64     if (!IsDirExist(SAFE_PATH.c_str())) {
65         HILOG_INFO_I18N("CopyDataFile: SAFE_PATH not exist");
66         return;
67     }
68 
69     for (size_t i = 0; i < DATA_FILES.size(); i++) {
70         std::string srcPath = CFG_PATH + DATA_FILES[i];
71         std::string dstPath = SAFE_PATH + DATA_FILES[i];
72         if (!FileExist(srcPath)) {
73             HILOG_INFO_I18N("CopyDataFile: %{public}s not exist", DATA_FILES[i].c_str());
74             continue;
75         }
76         if (!FileCopy(srcPath, dstPath)) {
77             HILOG_INFO_I18N("CopyDataFile: copy %{public}s failed", DATA_FILES[i].c_str());
78         }
79     }
80 }
81 
CheckIfUpdateNecessary()82 bool CheckIfUpdateNecessary()
83 {
84     std::string versionUpdate = SignatureVerifier::LoadFileVersion(CFG_PATH + VERSION_FILE);
85     std::string versionLocale = SignatureVerifier::LoadFileVersion(LOCALE_PATH + VERSION_FILE);
86     HILOG_INFO_I18N("CheckIfUpdateNecessary: Verify: versionUpdate(%{public}s) versionLocale(%{public}s)",
87         versionUpdate.c_str(), versionLocale.c_str());
88 
89     if (versionLocale.length() == 0 || versionUpdate.length() == 0) {
90         return false;
91     }
92     if (SignatureVerifier::CompareVersion(versionLocale, versionUpdate) <= 0) {
93         return false;
94     }
95     return true;
96 }
97 
CheckFileIntegrity()98 bool CheckFileIntegrity()
99 {
100     std::string certPath = CFG_PATH + CERT_FILE;
101     std::string verifyPath = CFG_PATH + VERIFY_FILE;
102     std::string pubkeyPath = LOCALE_PATH + PUBKEY_NAME;
103     std::string manifestPath = CFG_PATH + MANIFEST_FILE;
104     if (!SignatureVerifier::VerifyCertFile(certPath, verifyPath, pubkeyPath, manifestPath)) {
105         HILOG_ERROR_I18N("CheckFileIntegrity: VerifyCertFile error");
106         return false;
107     }
108 
109     for (size_t i = 0; i < DATA_FILES.size(); i++) {
110         HILOG_ERROR_I18N("CheckFileIntegrity: file to verify (%{public}s)", DATA_FILES[i].c_str());
111         std::string filePath = CFG_PATH + DATA_FILES[i];
112         if (FileExist(filePath.c_str()) &&
113             !SignatureVerifier::VerifyParamFile(DATA_FILES[i], CFG_PATH, manifestPath)) {
114             HILOG_ERROR_I18N("CheckFileIntegrity: VerifyParamFile error");
115             return false;
116         }
117     }
118 
119     return true;
120 }
121 
UpdateLibphonenumber()122 void UpdateLibphonenumber()
123 {
124     if (!CheckIfUpdateNecessary()) {
125         HILOG_INFO_I18N("UpdateLibphonenumber: CheckIfUpdateNecessary error, no need to update");
126         return;
127     }
128     if (!CheckFileIntegrity()) {
129         HILOG_INFO_I18N("UpdateLibphonenumber: CheckFileIntegrity error, no need to update");
130         return;
131     }
132 
133     CopyDataFile();
134 
135     if (!Mount()) {
136         HILOG_INFO_I18N("UpdateLibphonenumber: mount error");
137         return;
138     }
139 
140     HILOG_INFO_I18N("UpdateLibphonenumber: UpdateLibphonenumber");
141 }
142 
143 }
144 }
145 }
146 
main(int argc,char * argv[])147 int main(int argc, char *argv[])
148 {
149     HILOG_INFO_I18N("hmos_libphonenumber_mount: UpdateLibphonenumber start");
150     OHOS::Global::I18n::UpdateLibphonenumber();
151     return 0;
152 }