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
23namespace OHOS {
24namespace Global {
25namespace I18n {
26namespace {
27const std::string CUST_GLOBAL_CARRIER_DIR = "/system/etc/LIBPHONENUMBER/mount_dir/";
28const std::string VERSION_FILE = "version.txt";
29const std::string CERT_FILE = "CERT.ENC";
30const std::string VERIFY_FILE = "CERT.SF";
31const std::string MANIFEST_FILE = "MANIFEST.MF";
32const std::string SUB_TYPE = "generic";
33const std::string CFG_PATH =
34    "/data/service/el1/public/update/param_service/install/system/etc/LIBPHONENUMBER/generic/";
35const std::string LOCALE_PATH = "/system/etc/LIBPHONENUMBER/generic/";
36const std::string SAFE_PATH = "/data/service/el1/public/i18n/libphonenumber/";
37const std::string PUBKEY_NAME = "hota_i18n_upgrade_v1.pem";
38const std::vector<std::string> DATA_FILES = {"GeocodingInfo", "MetadataInfo"};
39}
40
41bool 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
62void 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
82bool 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
98bool 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
122void 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
147int main(int argc, char *argv[])
148{
149    HILOG_INFO_I18N("hmos_libphonenumber_mount: UpdateLibphonenumber start");
150    OHOS::Global::I18n::UpdateLibphonenumber();
151    return 0;
152}