!694 libphonenumber升级方案变更

Merge pull request !694 from LY/master
This commit is contained in:
openharmony_ci 2024-05-28 09:46:09 +00:00 committed by Gitee
commit 06fb6dd45e
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
22 changed files with 235 additions and 691 deletions

View File

@ -121,7 +121,6 @@ ohos_shared_library("intl_util") {
"src/taboo.cpp",
"src/taboo_utils.cpp",
"src/utils.cpp",
"src/verify_sign_tool.cpp",
]
version_script = "libintl_util.map"
cflags_cc = [

View File

@ -32,7 +32,7 @@ class SignatureVerifier {
public:
static bool VerifyCertFile(const std::string& certPath,
const std::string& verifyPath, const std::string& pubkeyPath, const std::string& manifestPath);
static std::string VerifyParamFile(const std::string& filePath,
static bool VerifyParamFile(const std::string& filePath,
const std::string& manifestPath, const std::string& absFilePath);
static std::string LoadFileVersion(const std::string& versionPath);
static int CompareVersion(std::string& preVersion, std::string& curVersion);
@ -41,7 +41,7 @@ private:
static bool VerifyRsa(RSA* pubkey, const std::string& digest, const std::string& sign);
static std::string CalcFileSha256Digest(const std::string& path);
static void CalcBase64(uint8_t* input, uint32_t inputLen, std::string& encodedStr);
static int CalcFileShaOriginal(const std::string& filePath, unsigned char* hash, size_t len);
static int CalcFileShaOriginal(const std::string& filePath, unsigned char* hash);
static bool VerifyFileSign(const std::string& pubkeyPath, const std::string& signPath,
const std::string& digestPath);
static std::string GetFileStream(const std::string& filePath);

View File

@ -38,6 +38,7 @@ std::string GetISO3Language(const std::string& language);
std::string GetISO3Country(const std::string& country);
std::string trim(std::string &s);
bool FileExist(const std::string& path);
bool FileCopy(const std::string& srcPath, const std::string& dstPath);
bool IsLegalPath(const std::string& path);
void Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest);
bool IsDirExist(const char *path);

View File

@ -1,85 +0,0 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except", "in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_GLOBAL_I18N_VERIFY_SIGN_TOOL_H
#define OHOS_GLOBAL_I18N_VERIFY_SIGN_TOOL_H
#include <openssl/rsa.h>
#include <string>
#include <vector>
#include "preferences.h"
#include "preferences_helper.h"
namespace OHOS {
namespace Global {
namespace I18n {
enum VerifyStatus {
VERIFY_FAILED = 0,
VERIFY_START = 1,
VERIFY_SUCCESS = 2
};
class VerifySignTool {
public:
static std::pair<int, int> Parse();
private:
static VerifyStatus Verify();
static bool VerifyCertFile();
static bool VerifyConfigFiles();
static bool VerifyDigest();
static std::string VerifyParamFile(const std::string& filePath);
static VerifyStatus VerifyCertAndConfig(std::string& version);
static VerifyStatus GetVerifyInfo();
static bool VerifyFileSign(const std::string& pubkeyPath, const std::string& signPath,
const std::string& digestPath);
static bool VerifyRsa(RSA* pubkey, const std::string& digest, const std::string& sign);
static std::string CalcFileSha256Digest(const std::string& path);
static void CalcBase64(uint8_t* input, int inputLen, std::string& encodedStr);
static int CalcFileShaOriginal(const std::string& filePath, unsigned char* hash, size_t len);
static std::string LoadFileVersion(std::string& versionPath);
static int CompareVersion(std::string& preVersion, std::string& curVersion);
static bool IsLegalPath(const std::string& path);
static void Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest);
static std::string trim(std::string &s);
static std::string GetFileStream(const std::string& filePath);
static bool FileExist(const std::string& path);
static const int HASH_BUFFER_SIZE;
static const int MIN_SIZE;
static const int VERSION_SIZE;
static const std::string VERSION_FILE;
static const std::string METADATA_FILE;
static const std::string GEOCODING_FILE;
static const std::string CERT_FILE;
static const std::string VERIFY_FILE;
static const std::string MANIFEST_FILE;
static const std::string CONFIG_TYPE;
static const std::string SUB_TYPE;
static const std::string CFG_PATH;
static const std::string LOCALE_PATH;
static const std::string PUBKEY_NAME;
static const std::string PREFERENCE_PATH;
static const std::string VERSION_NAME;
static const std::string VERIFY_CERT_NAME;
static const std::string METADATA_DIGEST_NAME;
static const std::string GEOCODING_DIGEST_NAME;
static std::shared_ptr<NativePreferences::Preferences> preferences;
};
} // namespace I18n
} // namespace Global
} // namespace OHOS
#endif

View File

@ -26,7 +26,7 @@
#include "i18n_hilog.h"
#include "signature_verifier.h"
#include "utils.h"
namespace OHOS {
namespace Global {
namespace I18n {
@ -34,7 +34,7 @@ namespace {
const int32_t BASE64_ENCODE_PACKET_LEN = 3;
const int32_t BASE64_ENCODE_LEN_OF_EACH_GROUP_DATA = 4;
}
const int SignatureVerifier::HASH_BUFFER_SIZE = 4096;
const int SignatureVerifier::MIN_SIZE = 2;
const int SignatureVerifier::VERSION_SIZE = 4;
@ -62,7 +62,7 @@ std::string SignatureVerifier::LoadFileVersion(const std::string& versionPath)
file.close();
return version;
}
// compare version
int SignatureVerifier::CompareVersion(std::string& preVersion, std::string& curVersion)
{
@ -115,17 +115,17 @@ bool SignatureVerifier::VerifyCertFile(const std::string& certPath, const std::s
// verify param file digest
std::string SignatureVerifier::VerifyParamFile(const std::string& fileName, const std::string& filePath,
bool SignatureVerifier::VerifyParamFile(const std::string& fileName, const std::string& filePath,
const std::string& manifestPath)
{
std::ifstream file(manifestPath);
if (!file.good()) {
return "manifestPath error";
return false;
}
std::string absFilePath = filePath + fileName;
std::ifstream paramFile(absFilePath);
if (!paramFile.good()) {
return "paramFile error";
return false;
}
std::string sha256Digest;
std::string line;
@ -136,7 +136,7 @@ std::string SignatureVerifier::VerifyParamFile(const std::string& fileName, cons
std::vector<std::string> strs;
Split(nextLine, ":", strs);
if (strs.size() < MIN_SIZE) {
return "strs wrong";
return false;
}
sha256Digest = strs[1];
sha256Digest = trim(sha256Digest);
@ -144,13 +144,13 @@ std::string SignatureVerifier::VerifyParamFile(const std::string& fileName, cons
}
}
if (sha256Digest.empty()) {
return "empty";
return false;
}
std::string fileDigest = CalcFileSha256Digest(absFilePath);
if (fileDigest == sha256Digest) {
return fileDigest;
return true;
}
return "unknow error";
return false;
}
@ -224,7 +224,7 @@ bool SignatureVerifier::VerifyRsa(RSA* pubkey, const std::string& digest, const
std::string SignatureVerifier::CalcFileSha256Digest(const std::string& path)
{
unsigned char res[SHA256_DIGEST_LENGTH] = {0};
CalcFileShaOriginal(path, res, SHA256_DIGEST_LENGTH);
CalcFileShaOriginal(path, res);
std::string dist;
CalcBase64(res, SHA256_DIGEST_LENGTH, dist);
return dist;
@ -239,9 +239,9 @@ void SignatureVerifier::CalcBase64(uint8_t* input, uint32_t inputLen, std::strin
encodedStr = std::string(reinterpret_cast<char*>(base64Str.get()), outLen);
}
int SignatureVerifier::CalcFileShaOriginal(const std::string& filePath, unsigned char* hash, size_t len)
int SignatureVerifier::CalcFileShaOriginal(const std::string& filePath, unsigned char* hash)
{
if (filePath.empty() || hash == nullptr || !IsLegalPath(filePath) || len < SHA256_DIGEST_LENGTH) {
if (filePath.empty() || hash == nullptr || !IsLegalPath(filePath)) {
return -1;
}
FILE* fp = fopen(filePath.c_str(), "rb");

View File

@ -213,7 +213,25 @@ bool FileExist(const std::string& path)
}
return status;
}
bool FileCopy(const std::string& srcPath, const std::string& dstPath)
{
try {
std::filesystem::copy(srcPath.c_str(), dstPath.c_str());
return true;
} catch (const std::filesystem::filesystem_error &except) {
HILOG_ERROR_I18N("utils: FileCopy failed because filesystem_error, error message: %{public}s.",
except.code().message().c_str());
} catch (const std::__h::__fs::filesystem::filesystem_error &except) {
HILOG_ERROR_I18N("utils: FileCopy failed because filesystem_error, error message: %{public}s.",
except.code().message().c_str());
} catch (const std::bad_alloc &except) {
HILOG_ERROR_I18N("utils: FileCopy failed because bad_alloc, error message: %{public}s.",
except.what());
}
return false;
}
bool IsLegalPath(const std::string& path)
{
if (path.find("./") != std::string::npos ||

View File

@ -1,511 +0,0 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstdlib>
#include <fcntl.h>
#include <filesystem>
#include <fstream>
#include <climits>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
#include <sstream>
#include <unistd.h>
#include "i18n_hilog.h"
#include "verify_sign_tool.h"
#include "utils.h"
namespace OHOS {
namespace Global {
namespace I18n {
namespace {
const int32_t BASE64_ENCODE_PACKET_LEN = 3;
const int32_t BASE64_ENCODE_LEN_OF_EACH_GROUP_DATA = 4;
}
const int VerifySignTool::HASH_BUFFER_SIZE = 4096;
const int VerifySignTool::MIN_SIZE = 2;
const int VerifySignTool::VERSION_SIZE = 4;
const std::string VerifySignTool::VERSION_FILE = "version.txt";
const std::string VerifySignTool::METADATA_FILE = "MetadataInfo";
const std::string VerifySignTool::GEOCODING_FILE = "GeocodingInfo";
const std::string VerifySignTool::CERT_FILE = "CERT.ENC";
const std::string VerifySignTool::VERIFY_FILE = "CERT.SF";
const std::string VerifySignTool::MANIFEST_FILE = "MANIFEST.MF";
const std::string VerifySignTool::CONFIG_TYPE = "LIBPHONENUMBER";
const std::string VerifySignTool::SUB_TYPE = "generic";
const std::string VerifySignTool::CFG_PATH =
"/data/service/el1/public/update/param_service/install/system/etc/LIBPHONENUMBER/generic/";
const std::string VerifySignTool::LOCALE_PATH = "/system/etc/LIBPHONENUMBER/generic/";
const std::string VerifySignTool::PUBKEY_NAME = "hota_i18n_upgrade_v1.pem";
const std::string VerifySignTool::PREFERENCE_PATH = "/data/service/el1/public/i18n/libphonenumber";
const std::string VerifySignTool::VERSION_NAME = "version";
const std::string VerifySignTool::VERIFY_CERT_NAME = "verify_cert";
const std::string VerifySignTool::METADATA_DIGEST_NAME = "metadata_digest";
const std::string VerifySignTool::GEOCODING_DIGEST_NAME = "geocoding_digest";
std::shared_ptr<NativePreferences::Preferences> VerifySignTool::preferences = nullptr;
std::pair<int, int> VerifySignTool::Parse()
{
std::pair<int, int> fds = {-1, -1};
VerifyStatus status = Verify();
if (status == VERIFY_FAILED) {
return fds;
} else if (status == VERIFY_START) {
if (!VerifyDigest()) {
return fds;
}
}
std::string metadataPath = CFG_PATH + METADATA_FILE;
int metadataFd = open(metadataPath.c_str(), O_RDONLY);
std::string geocodingPath = CFG_PATH + GEOCODING_FILE;
int geocodingFd = open(geocodingPath.c_str(), O_RDONLY);
fds.first = metadataFd;
fds.second = geocodingFd;
return fds;
}
// verify MetadataInfo/GeocodingInfo digest
bool VerifySignTool::VerifyDigest()
{
std::string metadataDigest = preferences->GetString(METADATA_DIGEST_NAME, "");
if (metadataDigest.length() != 0) {
std::string metadataPath = CFG_PATH + METADATA_FILE;
if (CalcFileSha256Digest(metadataPath) != metadataDigest) {
return false;
}
}
std::string geocodingDigest = preferences->GetString(GEOCODING_DIGEST_NAME, "");
if (geocodingDigest.length() != 0) {
std::string geocodingPath = CFG_PATH + GEOCODING_FILE;
if (CalcFileSha256Digest(geocodingPath) != geocodingDigest) {
return false;
}
}
return true;
}
// verify all update file
VerifyStatus VerifySignTool::Verify()
{
std::string versionUpdatePath = CFG_PATH + VERSION_FILE;
std::string versionUpdate = LoadFileVersion(versionUpdatePath);
if (versionUpdate.length() == 0) {
return VERIFY_FAILED;
}
std::string versionLocalePath = LOCALE_PATH + VERSION_FILE;
std::string versionLocale = LoadFileVersion(versionLocalePath);
if (versionLocale.length() == 0) {
return VERIFY_FAILED;
}
int status;
if (preferences == nullptr) {
OHOS::NativePreferences::Options opt(PREFERENCE_PATH);
preferences = NativePreferences::PreferencesHelper::GetPreferences(opt, status);
if (status != 0) {
preferences = nullptr;
}
}
status = CompareVersion(versionLocale, versionUpdate);
if (status <= 0) {
return VERIFY_FAILED;
} else {
std::string versionPrefer = preferences->GetString(VERSION_NAME, "");
status = CompareVersion(versionPrefer, versionUpdate);
if (versionPrefer == "" || status > 0) {
return VerifyCertAndConfig(versionUpdate);
} else if (status == 0) {
return GetVerifyInfo();
}
}
return VERIFY_FAILED;
}
std::string VerifySignTool::LoadFileVersion(std::string& versionPath)
{
std::string version;
if (!FileExist(versionPath.c_str())) {
return version;
}
if (!CheckTzDataFilePath(versionPath)) {
return version;
}
std::ifstream file(versionPath);
std::string line;
std::vector<std::string> strs;
while (std::getline(file, line)) {
Split(line, "=", strs);
if (strs.size() < MIN_SIZE) {
continue;
}
if (strs[0] == VERSION_NAME) {
version = trim(strs[1]);
break;
}
}
file.close();
return version;
}
// compare version
int VerifySignTool::CompareVersion(std::string& preVersion, std::string& curVersion)
{
std::vector<std::string> preVersionstr;
std::vector<std::string> curVersionstr;
Split(preVersion, ".", preVersionstr);
Split(curVersion, ".", curVersionstr);
if (curVersionstr.size() != VERSION_SIZE || preVersionstr.size() != VERSION_SIZE) {
return -1;
}
for (int i = 0; i < VERSION_SIZE; i++) {
if (atoi(preVersionstr.at(i).c_str()) < atoi(curVersionstr.at(i).c_str())) {
return 1;
} else if (atoi(preVersionstr.at(i).c_str()) > atoi(curVersionstr.at(i).c_str())) {
return -1;
}
}
return 0;
}
// determine if the certificate file has been verified
VerifyStatus VerifySignTool::GetVerifyInfo()
{
bool isVerifyCert = false;
if (preferences != nullptr) {
isVerifyCert = preferences->GetBool(VERIFY_CERT_NAME, false);
}
return isVerifyCert ? VERIFY_START : VERIFY_FAILED;
}
// verify certificate file and config file
VerifyStatus VerifySignTool::VerifyCertAndConfig(std::string& version)
{
int status;
if (VerifyCertFile() && VerifyConfigFiles()) {
if (preferences != nullptr) {
status = preferences->PutBool(VERIFY_CERT_NAME, true);
if (status == 0) {
preferences->PutString(VERSION_NAME, version);
}
preferences->Flush();
}
return VERIFY_SUCCESS;
} else {
if (preferences != nullptr) {
status = preferences->PutBool(VERIFY_CERT_NAME, false);
if (status == 0) {
preferences->PutString(VERSION_NAME, version);
}
preferences->Flush();
}
return VERIFY_FAILED;
}
}
// // verify certificate file
bool VerifySignTool::VerifyCertFile()
{
std::string certPath = CFG_PATH + CERT_FILE;
std::string verifyPath = CFG_PATH + VERIFY_FILE;
std::string pubkeyPath = LOCALE_PATH + PUBKEY_NAME;
if (!VerifyFileSign(pubkeyPath, certPath, verifyPath)) {
return false;
}
std::ifstream file(verifyPath);
if (!file.good()) {
return false;
}
std::string line;
std::string sha256Digest;
std::getline(file, line);
file.close();
std::vector<std::string> strs;
Split(line, ":", strs);
if (strs.size() < MIN_SIZE) {
return false;
}
sha256Digest = strs[1];
sha256Digest = trim(sha256Digest);
std::string manifestPath = CFG_PATH + MANIFEST_FILE;
std::string manifestDigest = CalcFileSha256Digest(manifestPath);
if (sha256Digest == manifestDigest) {
return true;
}
return false;
}
// verify config file
bool VerifySignTool::VerifyConfigFiles()
{
std::string versionPath = CFG_PATH + VERSION_FILE;
if (!FileExist(versionPath.c_str())) {
return false;
}
if (VerifyParamFile(VERSION_FILE).length() == 0) {
return false;
}
std::string metadataPath = CFG_PATH + METADATA_FILE;
std::string metadataDigest = VerifyParamFile(METADATA_FILE);
if (FileExist(metadataPath.c_str()) && metadataDigest.length() == 0) {
return false;
}
std::string geocodingDigest = VerifyParamFile(GEOCODING_FILE);
std::string geocodingPath = CFG_PATH + GEOCODING_FILE;
if (FileExist(geocodingPath.c_str()) && geocodingDigest.length() == 0) {
return false;
}
if (preferences != nullptr) {
if (metadataDigest.length() != 0) {
preferences->PutString(METADATA_DIGEST_NAME, metadataDigest);
}
if (geocodingDigest.length() != 0) {
preferences->PutString(GEOCODING_DIGEST_NAME, geocodingDigest);
}
preferences->Flush();
}
return true;
}
// verify param file digest
std::string VerifySignTool::VerifyParamFile(const std::string& filePath)
{
std::string manifestPath = CFG_PATH + MANIFEST_FILE;
std::ifstream file(manifestPath);
if (!file.good()) {
return "";
}
std::string absFilePath = CFG_PATH + filePath;
if (!CheckTzDataFilePath(absFilePath)) {
return "";
}
std::string sha256Digest;
std::string line;
while (std::getline(file, line)) {
if (line.find("Name: " + filePath) != std::string::npos) {
std::string nextLine;
std::getline(file, nextLine);
std::vector<std::string> strs;
Split(nextLine, ":", strs);
if (strs.size() < MIN_SIZE) {
return "";
}
sha256Digest = strs[1];
sha256Digest = trim(sha256Digest);
break;
}
}
if (sha256Digest.empty()) {
return "";
}
std::string fileDigest = CalcFileSha256Digest(absFilePath);
if (fileDigest == sha256Digest) {
return fileDigest;
}
return "";
}
std::string VerifySignTool::trim(std::string &s)
{
if (s.empty()) {
return s;
}
s.erase(0, s.find_first_not_of(" "));
s.erase(s.find_last_not_of(" ") + 1);
return s;
}
// verify cert file sign
bool VerifySignTool::VerifyFileSign(const std::string& pubkeyPath, const std::string& signPath,
const std::string& digestPath)
{
if (!FileExist(pubkeyPath.c_str())) {
return false;
}
if (!FileExist(signPath.c_str())) {
return false;
}
if (!FileExist(digestPath.c_str())) {
return false;
}
std::string signStr = GetFileStream(signPath);
std::string digestStr = GetFileStream(digestPath);
RSA* pubkey = RSA_new();
bool verify = false;
if (pubkey != nullptr && !signStr.empty() && !digestStr.empty()) {
BIO* bio = BIO_new_file(pubkeyPath.c_str(), "r");
if (PEM_read_bio_RSA_PUBKEY(bio, &pubkey, nullptr, nullptr) == nullptr) {
BIO_free(bio);
return false;
}
verify = VerifyRsa(pubkey, digestStr, signStr);
BIO_free(bio);
}
RSA_free(pubkey);
return verify;
}
bool VerifySignTool::VerifyRsa(RSA* pubkey, const std::string& digest, const std::string& sign)
{
EVP_PKEY* evpKey = EVP_PKEY_new();
if (evpKey == nullptr) {
return false;
}
if (EVP_PKEY_set1_RSA(evpKey, pubkey) != 1) {
return false;
}
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
EVP_MD_CTX_init(ctx);
if (ctx == nullptr) {
EVP_PKEY_free(evpKey);
return false;
}
if (EVP_VerifyInit_ex(ctx, EVP_sha256(), nullptr) != 1) {
EVP_PKEY_free(evpKey);
EVP_MD_CTX_free(ctx);
return false;
}
if (EVP_VerifyUpdate(ctx, digest.c_str(), digest.size()) != 1) {
EVP_PKEY_free(evpKey);
EVP_MD_CTX_free(ctx);
return false;
}
char* signArr = const_cast<char*>(sign.c_str());
if (EVP_VerifyFinal(ctx, reinterpret_cast<unsigned char *>(signArr), sign.size(), evpKey) != 1) {
EVP_PKEY_free(evpKey);
EVP_MD_CTX_free(ctx);
return false;
}
EVP_PKEY_free(evpKey);
EVP_MD_CTX_free(ctx);
return true;
}
std::string VerifySignTool::CalcFileSha256Digest(const std::string& path)
{
unsigned char res[SHA256_DIGEST_LENGTH] = {0};
CalcFileShaOriginal(path, res, SHA256_DIGEST_LENGTH);
std::string dist;
CalcBase64(res, SHA256_DIGEST_LENGTH, dist);
return dist;
}
void VerifySignTool::CalcBase64(uint8_t* input, int inputLen, std::string& encodedStr)
{
size_t base64Len = static_cast<size_t>(ceil(static_cast<long double>(inputLen) / BASE64_ENCODE_PACKET_LEN) *
BASE64_ENCODE_LEN_OF_EACH_GROUP_DATA + 1);
std::unique_ptr<unsigned char[]> base64Str = std::make_unique<unsigned char[]>(base64Len);
int encodeLen = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(base64Str.get()), input, inputLen);
size_t outLen = static_cast<size_t>(encodeLen);
encodedStr = std::string(reinterpret_cast<char*>(base64Str.get()), outLen);
}
int VerifySignTool::CalcFileShaOriginal(const std::string& filePath, unsigned char* hash, size_t len)
{
if (filePath.empty() || hash == nullptr || !IsLegalPath(filePath) || len < SHA256_DIGEST_LENGTH) {
return -1;
}
FILE* fp = fopen(filePath.c_str(), "rb");
if (fp == nullptr) {
return -1;
}
size_t n;
char buffer[HASH_BUFFER_SIZE] = {0};
SHA256_CTX ctx;
SHA256_Init(&ctx);
while ((n = fread(buffer, 1, sizeof(buffer), fp))) {
SHA256_Update(&ctx, reinterpret_cast<unsigned char*>(buffer), n);
}
SHA256_Final(hash, &ctx);
if (fclose(fp) == -1) {
return -1;
}
return 0;
}
// load file content
std::string VerifySignTool::GetFileStream(const std::string& filePath)
{
if (filePath.length() >= PATH_MAX) {
return "";
}
char* resolvedPath = new char[PATH_MAX + 1];
if (realpath(filePath.c_str(), resolvedPath) == nullptr) {
delete[] resolvedPath;
return "";
}
std::ifstream file(filePath, std::ios::in | std::ios::binary);
if (!file.good()) {
delete[] resolvedPath;
return "";
}
std::stringstream inFile;
inFile << file.rdbuf();
delete[] resolvedPath;
return inFile.str();
}
bool VerifySignTool::IsLegalPath(const std::string& path)
{
if (path.find("./") != std::string::npos ||
path.find("../") != std::string::npos) {
return false;
}
return true;
}
void VerifySignTool::Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest)
{
if (src == "") {
return;
}
std::string::size_type begin = 0;
std::string::size_type end = src.find(sep);
while (end != std::string::npos) {
dest.push_back(src.substr(begin, end - begin));
begin = end + sep.size();
end = src.find(sep, begin);
}
if (begin != src.size()) {
dest.push_back(src.substr(begin));
}
}
bool VerifySignTool::FileExist(const std::string& path)
{
bool status = false;
try {
status = std::filesystem::exists(path.c_str());
} catch (const std::filesystem::filesystem_error &except) {
HILOG_ERROR_I18N("FileExist failed because filesystem_error, error message: %{public}s.",
except.code().message().c_str());
return false;
} catch (const std::__h::__fs::filesystem::filesystem_error &except) {
HILOG_ERROR_I18N("FileExist failed because filesystem_error, error message: %{public}s.",
except.code().message().c_str());
return false;
} catch (const std::bad_alloc &except) {
HILOG_ERROR_I18N("FileExist failed because bad_alloc, error message: %{public}s.",
except.what());
return false;
}
return status;
}
}
}
}

View File

@ -15,11 +15,13 @@ import("//build/ohos.gni")
group("i18n_service_ability") {
deps = [
":hmos_cust_libphonenumber_mount",
":hmos_cust_timezone_mount",
":i18n_sa",
":i18n_sa_client",
"./etc:i18n_sa_etc",
"./etc:prefabrication",
"./etc:prefabrication_libphonenumber",
"./etc:prefabrication_timezone",
"./etc:version_txt",
]
}
@ -109,3 +111,18 @@ ohos_executable("hmos_cust_timezone_mount") {
part_name = "i18n"
subsystem_name = "global"
}
ohos_executable("hmos_cust_libphonenumber_mount") {
sources = [ "src/hmos_libphonenumber_mount.cpp" ]
include_dirs = [ "../frameworks/intl/include" ]
deps = [ "../frameworks/intl:intl_util" ]
external_deps = [
"hilog:libhilog",
"openssl:libcrypto_shared",
"openssl:libssl_shared",
]
install_images = [ "system" ]
part_name = "i18n"
subsystem_name = "global"
}

View File

@ -22,14 +22,21 @@ ohos_prebuilt_etc("i18n_sa_etc") {
ohos_prebuilt_etc("version_txt") {
source = "./timezone/version.txt"
module_install_dir = "etc/TIMEZONE/generic/"
module_install_dir = "etc/TIMEZONE/generic/current/"
subsystem_name = "global"
part_name = "i18n"
}
ohos_prebuilt_etc("prefabrication") {
ohos_prebuilt_etc("prefabrication_timezone") {
source = "./timezone/prefabrication"
module_install_dir = "etc/tzdata_distro/"
subsystem_name = "global"
part_name = "i18n"
}
ohos_prebuilt_etc("prefabrication_libphonenumber") {
source = "./libphonenumber/prefabrication"
module_install_dir = "etc/LIBPHONENUMBER/mount_dir/"
subsystem_name = "global"
part_name = "i18n"
}

View File

@ -3,8 +3,10 @@
{
"name": "boot",
"cmds": [
"mkdir /data/service/el1/public/i18n/ 0777 i18n_service i18n_service",
"exec /system/bin/hmos_cust_timezone_mount"
"mkdir /data/service/el1/public/i18n/ 0744 i18n_service i18n_service",
"mkdir /data/service/el1/public/i18n/libphonenumber/ 0744 i18n_service i18n_service",
"exec /system/bin/hmos_cust_timezone_mount",
"exec /system/bin/hmos_cust_libphonenumber_mount"
]
}
],

View File

@ -0,0 +1,14 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except", "in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@ -38,7 +38,6 @@ public:
I18nErrorCode SetUsingLocalDigit(bool flag) override;
I18nErrorCode AddPreferredLanguage(const std::string &language, int32_t index) override;
I18nErrorCode RemovePreferredLanguage(int32_t index) override;
std::pair<int, int> VerifyLibphonenumberUpdate() override;
/**
* @brief Trigger unload i18n service after one request finished, but service will not unload
* until there no request in 10s.

View File

@ -89,13 +89,6 @@ public:
*/
static I18nErrorCode RemovePreferredLanguage(int32_t index);
/**
* @brief Verify the libphonenumber upgrade file.
*
* @return corresponding file descriptor {metadataFd, geocodingFd}.
*/
static std::pair<int, int> VerifyLibphonenumberUpdate();
private:
/**
* @brief Get the proxy of i18n service to access service.

View File

@ -91,13 +91,6 @@ public:
*/
I18nErrorCode RemovePreferredLanguage(int32_t index);
/**
* @brief Verify the libphonenumber upgrade file.
*
* @return corresponding file descriptor {metadataFd, geocodingFd}.
*/
std::pair<int, int> VerifyLibphonenumberUpdate();
private:
static I18nErrorCode ProcessReply(int32_t reply);
static inline BrokerDelegator<I18nServiceAbilityProxy> delegator_;

View File

@ -73,7 +73,6 @@ private:
int32_t SetUsingLocalDigitInner(MessageParcel &data, MessageParcel &reply);
int32_t AddPreferredLanguageInner(MessageParcel &data, MessageParcel &reply);
int32_t RemovePreferredLanguageInner(MessageParcel &data, MessageParcel &reply);
int32_t VerifyLibphonenumberUpdateInner(MessageParcel &data, MessageParcel &reply);
};
} // namespace I18n
} // namespace Global

View File

@ -33,7 +33,6 @@ public:
virtual I18nErrorCode SetUsingLocalDigit(bool flag) = 0;
virtual I18nErrorCode AddPreferredLanguage(const std::string &language, int32_t index) = 0;
virtual I18nErrorCode RemovePreferredLanguage(int32_t index) = 0;
virtual std::pair<int, int> VerifyLibphonenumberUpdate() = 0;
// I18n service request code.
enum class ILocaleConfigAbilityCode {

View File

@ -0,0 +1,153 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except", "in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <filesystem>
#include <string>
#include <sys/mount.h>
#include "i18n_hilog.h"
#include "signature_verifier.h"
#include "utils.h"
namespace OHOS {
namespace Global {
namespace I18n {
namespace {
const std::string CUST_GLOBAL_CARRIER_DIR = "/system/etc/LIBPHONENUMBER/mount_dir/";
const std::string VERSION_FILE = "version.txt";
const std::string CERT_FILE = "CERT.ENC";
const std::string VERIFY_FILE = "CERT.SF";
const std::string MANIFEST_FILE = "MANIFEST.MF";
const std::string SUB_TYPE = "generic";
const std::string CFG_PATH =
"/data/service/el1/public/update/param_service/install/system/etc/LIBPHONENUMBER/generic/";
const std::string LOCALE_PATH = "/system/etc/LIBPHONENUMBER/generic/";
const std::string SAFE_PATH = "/data/service/el1/public/i18n/libphonenumber/";
const std::string PUBKEY_NAME = "hota_i18n_upgrade_v1.pem";
const std::vector<std::string> DATA_FILES = {"GeocodingInfo", "MetadataInfo"};
}
bool Mount()
{
if (!IsDirExist(CUST_GLOBAL_CARRIER_DIR.c_str()) ||
!IsDirExist(SAFE_PATH.c_str())) {
HILOG_ERROR_I18N("Mount: CUST_GLOBAL_CARRIER_DIR or CFG_PATH not exist");
return false;
}
int ret = 0;
std::string cotaOpkeyVersionDir = SAFE_PATH;
std::string custOpkeyVersionDir = CUST_GLOBAL_CARRIER_DIR;
if (mount(cotaOpkeyVersionDir.c_str(), custOpkeyVersionDir.c_str(), nullptr, MS_BIND, nullptr) != 0) {
HILOG_ERROR_I18N("Mount: fail to mount: opkey(%{public}s) errno(%{public}s)",
cotaOpkeyVersionDir.c_str(), strerror(errno));
ret = false;
} else {
HILOG_INFO_I18N("Mount: success to mount cotaDir to custDir: opkey(%{public}s)", cotaOpkeyVersionDir.c_str());
}
return true;
}
void CopyDataFile()
{
if (!IsDirExist(SAFE_PATH.c_str())) {
HILOG_INFO_I18N("CopyDataFile: SAFE_PATH not exist");
return;
}
for (size_t i = 0; i < DATA_FILES.size(); i++) {
std::string srcPath = CFG_PATH + DATA_FILES[i];
std::string dstPath = SAFE_PATH + DATA_FILES[i];
if (!FileExist(srcPath)) {
HILOG_INFO_I18N("CopyDataFile: %{public}s not exist", DATA_FILES[i].c_str());
continue;
}
if (!FileCopy(srcPath, dstPath)) {
HILOG_INFO_I18N("CopyDataFile: copy %{public}s failed", DATA_FILES[i].c_str());
}
}
}
bool CheckIfUpdateNecessary()
{
std::string versionUpdate = SignatureVerifier::LoadFileVersion(CFG_PATH + VERSION_FILE);
std::string versionLocale = SignatureVerifier::LoadFileVersion(LOCALE_PATH + VERSION_FILE);
HILOG_INFO_I18N("CheckIfUpdateNecessary: Verify: versionUpdate(%{public}s) versionLocale(%{public}s)",
versionUpdate.c_str(), versionLocale.c_str());
if (versionLocale.length() == 0 || versionUpdate.length() == 0) {
return false;
}
if (SignatureVerifier::CompareVersion(versionLocale, versionUpdate) <= 0) {
return false;
}
return true;
}
bool CheckFileIntegrity()
{
std::string certPath = CFG_PATH + CERT_FILE;
std::string verifyPath = CFG_PATH + VERIFY_FILE;
std::string pubkeyPath = LOCALE_PATH + PUBKEY_NAME;
std::string manifestPath = CFG_PATH + MANIFEST_FILE;
if (!SignatureVerifier::VerifyCertFile(certPath, verifyPath, pubkeyPath, manifestPath)) {
HILOG_ERROR_I18N("CheckFileIntegrity: VerifyCertFile error");
return false;
}
for (size_t i = 0; i < DATA_FILES.size(); i++) {
HILOG_ERROR_I18N("CheckFileIntegrity: file to verify (%{public}s)", DATA_FILES[i].c_str());
std::string filePath = CFG_PATH + DATA_FILES[i];
if (FileExist(filePath.c_str()) &&
!SignatureVerifier::VerifyParamFile(DATA_FILES[i], CFG_PATH, manifestPath)) {
HILOG_ERROR_I18N("CheckFileIntegrity: VerifyParamFile error");
return false;
}
}
return true;
}
void UpdateLibphonenumber()
{
if (!CheckIfUpdateNecessary()) {
HILOG_INFO_I18N("UpdateLibphonenumber: CheckIfUpdateNecessary error, no need to update");
return;
}
if (!CheckFileIntegrity()) {
HILOG_INFO_I18N("UpdateLibphonenumber: CheckFileIntegrity error, no need to update");
return;
}
CopyDataFile();
if (!Mount()) {
HILOG_INFO_I18N("UpdateLibphonenumber: mount error");
return;
}
HILOG_INFO_I18N("UpdateLibphonenumber: UpdateLibphonenumber");
}
}
}
}
int main(int argc, char *argv[])
{
HILOG_INFO_I18N("hmos_libphonenumber_mount: UpdateLibphonenumber start");
OHOS::Global::I18n::UpdateLibphonenumber();
return 0;
}

View File

@ -31,11 +31,9 @@ const std::string MANIFEST_FILE = "MANIFEST.MF";
const std::string SUB_TYPE = "generic";
const std::string CFG_PATH =
"/data/service/el1/public/update/param_service/install/system/etc/TIMEZONE/generic/current/";
const std::string LOCALE_PATH = "/system/etc/TIMEZONE/generic/";
const std::string LOCALE_PATH = "/system/etc/TIMEZONE/generic/current/";
const std::string PUBKEY_PATH = "/system/etc/LIBPHONENUMBER/generic/";
const std::string PUBKEY_NAME = "hota_i18n_upgrade_v1.pem";
const std::string VVERSION_NAME = "version";
const std::string VERIFY_CERT_NAME = "verify_cert";
const std::vector<std::string> DATA_FILES = {"tzdata", "device_timezones.xml", "version.txt",
"distro_version", "tzlookup.xml", "device_city_dispname/bo_CN.xml", "device_city_dispname/root.xml",
"device_city_dispname/ug.xml", "device_city_dispname/zh_Hans.xml", "device_city_dispname/zh_HK.xml",
@ -98,12 +96,10 @@ bool CheckFileIntegrity()
HILOG_ERROR_I18N("CheckFileIntegrity: file not exist (%{public}s)", DATA_FILES[i].c_str());
return false;
}
std::string dig = SignatureVerifier::VerifyParamFile(DATA_FILES[i], CFG_PATH, manifestPath);
if (dig.length() == 0) {
if (!SignatureVerifier::VerifyParamFile(DATA_FILES[i], CFG_PATH, manifestPath)) {
HILOG_ERROR_I18N("CheckFileIntegrity: VerifyParamFile error");
return false;
}
HILOG_INFO_I18N("CheckFileIntegrity: VerifyParamFile success: (%{public}s)", dig.c_str());
}
return true;

View File

@ -22,7 +22,6 @@
#include "preferences.h"
#include "preferences_helper.h"
#include "system_ability_definition.h"
#include "verify_sign_tool.h"
#include "i18n_service_ability.h"
namespace OHOS {
@ -77,11 +76,6 @@ I18nErrorCode I18nServiceAbility::RemovePreferredLanguage(int32_t index)
return PreferredLanguage::RemovePreferredLanguage(index);
}
std::pair<int, int> I18nServiceAbility::VerifyLibphonenumberUpdate()
{
return VerifySignTool::Parse();
}
void I18nServiceAbility::UnloadI18nServiceAbility()
{
if (handler != nullptr) {

View File

@ -106,23 +106,6 @@ I18nErrorCode I18nServiceAbilityClient::RemovePreferredLanguage(int32_t index)
}
return i18nServiceAbilityObj->RemovePreferredLanguage(index);
}
std::pair<int, int> I18nServiceAbilityClient::VerifyLibphonenumberUpdate()
{
I18nErrorCode err = I18nErrorCode::SUCCESS;
sptr<II18nServiceAbility> i18nServiceAbilityObj = GetProxy(err);
if (i18nServiceAbilityObj == nullptr) {
return {-1, -1};
}
return i18nServiceAbilityObj->VerifyLibphonenumberUpdate();
}
extern "C" void VerifyLibphonenumberUpdate(int* metadataFd, int* geocodingFd)
{
std::pair<int, int> fds = I18nServiceAbilityClient::VerifyLibphonenumberUpdate();
*metadataFd = fds.first;
*geocodingFd = fds.second;
}
} // namespace I18n
} // namespace Global
} // namespace OHOS

View File

@ -112,20 +112,6 @@ I18nErrorCode I18nServiceAbilityProxy::RemovePreferredLanguage(int32_t index)
return ProcessReply(reply.ReadInt32());
}
std::pair<int, int> I18nServiceAbilityProxy::VerifyLibphonenumberUpdate()
{
MessageParcel data;
MessageParcel reply;
MessageOption option;
data.WriteInterfaceToken(DESCRIPTOR);
Remote()->SendRequest(static_cast<uint32_t>(ILocaleConfigAbilityCode::VERIFY_LIBPHONENUMBER_UPDATE),
data, reply, option);
int metadataFd = reply.ReadFileDescriptor();
int geocodingFd = reply.ReadFileDescriptor();
std::pair<int, int> fds = {metadataFd, geocodingFd};
return fds;
}
I18nErrorCode I18nServiceAbilityProxy::ProcessReply(int32_t reply)
{
I18nErrorCode err = static_cast<I18nErrorCode>(reply);

View File

@ -85,8 +85,6 @@ void I18nServiceAbilityStub::InitInnerFuncMap()
&I18nServiceAbilityStub::AddPreferredLanguageInner;
innerFuncMap[static_cast<uint32_t>(ILocaleConfigAbilityCode::REMOVE_PREFERRED_LANGUAGE)] =
&I18nServiceAbilityStub::RemovePreferredLanguageInner;
innerFuncMap[static_cast<uint32_t>(ILocaleConfigAbilityCode::VERIFY_LIBPHONENUMBER_UPDATE)] =
&I18nServiceAbilityStub::VerifyLibphonenumberUpdateInner;
}
/**
@ -254,17 +252,6 @@ int32_t I18nServiceAbilityStub::RemovePreferredLanguageInner(MessageParcel &data
Memory::MemMgrClient::GetInstance().SetCritical(pid, false, I18N_SA_ID);
return 0;
}
int32_t I18nServiceAbilityStub::VerifyLibphonenumberUpdateInner(MessageParcel &data, MessageParcel &reply)
{
int pid = getpid();
Memory::MemMgrClient::GetInstance().SetCritical(pid, true, I18N_SA_ID);
std::pair<int, int> fds = VerifyLibphonenumberUpdate();
reply.WriteFileDescriptor(fds.first);
reply.WriteFileDescriptor(fds.second);
Memory::MemMgrClient::GetInstance().SetCritical(pid, false, I18N_SA_ID);
return 0;
}
} // namespace I18n
} // namespace Global
} // namespace OHOS