From 66d0a1daf0218103b79174fbeaf730a0943f670b Mon Sep 17 00:00:00 2001 From: yang1946 Date: Tue, 16 Jan 2024 11:49:00 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=AD=BE=E5=90=8D=E8=B6=85?= =?UTF-8?q?=E5=A4=A7=E5=87=BD=E6=95=B0=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yang1946 --- interfaces/innerkits/code_sign_utils/BUILD.gn | 1 + .../include/code_sign_helper.h | 56 ++++++++++ .../code_sign_utils/include/code_sign_utils.h | 12 +- .../code_sign_utils/src/code_sign_helper.cpp | 98 +++++++++++++++++ .../code_sign_utils/src/code_sign_utils.cpp | 103 +++++------------- test/unittest/code_sign_utils_test.cpp | 40 +++++++ 6 files changed, 233 insertions(+), 77 deletions(-) create mode 100644 interfaces/innerkits/code_sign_utils/include/code_sign_helper.h create mode 100644 interfaces/innerkits/code_sign_utils/src/code_sign_helper.cpp diff --git a/interfaces/innerkits/code_sign_utils/BUILD.gn b/interfaces/innerkits/code_sign_utils/BUILD.gn index 534bb06..a781255 100644 --- a/interfaces/innerkits/code_sign_utils/BUILD.gn +++ b/interfaces/innerkits/code_sign_utils/BUILD.gn @@ -23,6 +23,7 @@ ohos_shared_library("libcode_sign_utils") { "${code_signature_root_dir}/utils/src/code_sign_block.cpp", "${code_signature_root_dir}/utils/src/file_helper.cpp", "src/code_sign_enable_multi_task.cpp", + "src/code_sign_helper.cpp", "src/code_sign_utils.cpp", "src/stat_utils.cpp", ] diff --git a/interfaces/innerkits/code_sign_utils/include/code_sign_helper.h b/interfaces/innerkits/code_sign_utils/include/code_sign_helper.h new file mode 100644 index 0000000..aa4ddeb --- /dev/null +++ b/interfaces/innerkits/code_sign_utils/include/code_sign_helper.h @@ -0,0 +1,56 @@ +/* + * 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 CODE_SIGN_HELPER_H +#define CODE_SIGN_HELPER_H + +#include "code_sign_block.h" +#include "code_sign_enable_multi_task.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { + +class CodeSignHelper { +public: + /** + * @brief parse code sign block info + * @param realPath hap real path on disk + * @param entryMap map from entryname in hap to real path on disk + * @param FileType signature file type + * @return err code, see err_code.h + */ + int32_t ParseCodeSignBlock(const std::string &realPath, const EntryMap &entryMap, FileType fileType); + /** + * @brief multithreading code signing enable task + * @param ownerId string to abtain owner ID from the signature file + * @param path hap real path on disk + * @param CallbackFunc enforce code sign callback function address + * @return err code, see err_code.h + */ + int32_t ProcessMultiTask(const std::string &ownerId, const std::string &path, CallbackFunc &func); +private: + int32_t ProcessOneFile(); + int32_t ExecuteMultiTask(int32_t ret, const std::string &ownerId, const std::string &path, CallbackFunc &func); + void ShowCodeSignInfo(const std::string &path, const struct code_sign_enable_arg &arg); +private: + CodeSignBlock codeSignBlock_; + CodeSignEnableMultiTask multiTask_; +}; +} +} +} + +#endif \ No newline at end of file diff --git a/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h b/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h index db90c87..90d51b1 100644 --- a/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h +++ b/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h @@ -123,15 +123,21 @@ public: * @return return ture if Completed */ bool IsCodeSignEnableCompleted(); -private: + /** + * @brief Check if the file path support FsVerity + * @param path file path + * @return err code, see err_code.h + */ static int32_t IsSupportFsVerity(const std::string &path); +private: static int32_t IsFsVerityEnabled(int fd); static int32_t EnableCodeSignForFile(const std::string &path, const struct code_sign_enable_arg &arg); - static void ShowCodeSignInfo(const std::string &path, const struct code_sign_enable_arg &arg); - static int32_t IsValidPathAndFileType(const std::string &path, std::string &realPath, FileType type); void StoredEntryMapInsert(const std::string &moduleName, const EntryMap &entryPathMap); void StoredEntryMapDelete(const std::string &moduleName); void StoredEntryMapSearch(const std::string &moduleName, EntryMap &entryPathMap); + int32_t ProcessCodeSignBlock(const std::string &ownerId, const std::string &path, + FileType type, const std::string &moduleName); + int32_t HandleCodeSignBlockFailure(const std::string &realPath, int32_t ret); private: std::unordered_map storedEntryMap_; std::mutex storedEntryMapLock_; diff --git a/interfaces/innerkits/code_sign_utils/src/code_sign_helper.cpp b/interfaces/innerkits/code_sign_utils/src/code_sign_helper.cpp new file mode 100644 index 0000000..8c3932f --- /dev/null +++ b/interfaces/innerkits/code_sign_utils/src/code_sign_helper.cpp @@ -0,0 +1,98 @@ +/* + * 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 + +#include "code_sign_helper.h" +#include "constants.h" +#include "file_helper.h" +#include "log.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { +int32_t CodeSignHelper::ParseCodeSignBlock(const std::string &realPath, + const EntryMap &entryMap, FileType fileType) +{ + return codeSignBlock_.ParseCodeSignBlock(realPath, entryMap, fileType); +} + +int32_t CodeSignHelper::ProcessMultiTask(const std::string &ownerId, const std::string &path, CallbackFunc &func) +{ + int32_t ret; + do { + ret = ProcessOneFile(); + if (ret == CS_SUCCESS_END) { + ret = CS_SUCCESS; + break; + } else if (ret != CS_SUCCESS) { + return ret; + } + } while (ret == CS_SUCCESS); + return ExecuteMultiTask(ret, ownerId, path, func); +} + +int32_t CodeSignHelper::ProcessOneFile() +{ + std::string targetFile; + struct code_sign_enable_arg arg = {0}; + int32_t ret = codeSignBlock_.GetOneFileAndCodeSignInfo(targetFile, arg); + if (ret != CS_SUCCESS) { + return ret; + } + ShowCodeSignInfo(targetFile, arg); + if (!CheckFilePathValid(targetFile, Constants::ENABLE_APP_BASE_PATH)) { + return CS_ERR_FILE_PATH; + } + ret = CodeSignUtils::IsSupportFsVerity(targetFile); + if (ret != CS_SUCCESS) { + return ret; + } + multiTask_.AddTaskData(targetFile, arg); + return ret; +} + +int32_t CodeSignHelper::ExecuteMultiTask(int32_t ret, const std::string &ownerId, + const std::string &path, CallbackFunc &func) +{ + bool waitStatus = multiTask_.ExecuteEnableCodeSignTask(ret, ownerId, path, func); + if (!waitStatus) { + LOG_ERROR(LABEL, "enable code sign timeout"); + return CS_ERR_ENABLE_TIMEOUT; + } + return ret; +} + +void CodeSignHelper::ShowCodeSignInfo(const std::string &path, const struct code_sign_enable_arg &arg) +{ + uint8_t *salt = reinterpret_cast(arg.salt_ptr); + uint8_t rootHash[64] = {0}; + uint8_t *rootHashPtr = rootHash; + if (arg.flags & CodeSignBlock::CSB_SIGN_INFO_MERKLE_TREE) { + rootHashPtr = reinterpret_cast(arg.root_hash_ptr); + } + + LOG_DEBUG(LABEL, "{ " + "file:%{public}s version:%{public}d hash_algorithm:%{public}d block_size:%{public}d sig_size:%{public}d " + "data_size:%{public}lld salt_size:%{public}d salt:[%{public}d, ..., %{public}d, ..., %{public}d] " + "flags:%{public}d tree_offset:%{public}lld root_hash:[%{public}d, %{public}d, %{public}d, ..., %{public}d, " + "..., %{public}d] }", + path.c_str(), arg.cs_version, arg.hash_algorithm, arg.block_size, arg.sig_size, + arg.data_size, arg.salt_size, salt[0], salt[16], salt[31], arg.flags, arg.tree_offset, // 16, 31 data index + rootHashPtr[0], rootHashPtr[1], rootHashPtr[2], rootHashPtr[32], rootHashPtr[63]); // 2, 32, 63 data index +} +} +} +} \ No newline at end of file diff --git a/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp b/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp index 3fdeebd..d4ff79d 100644 --- a/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp +++ b/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp @@ -31,7 +31,7 @@ #include "cs_hisysevent.h" #include "cs_hitrace.h" -#include "code_sign_enable_multi_task.h" +#include "code_sign_helper.h" #include "constants.h" #include "directory_ex.h" #include "extractor.h" @@ -39,7 +39,6 @@ #include "log.h" #include "stat_utils.h" #include "signer_info.h" -#include "code_sign_block.h" #include "rust_interface.h" namespace OHOS { @@ -210,25 +209,6 @@ int32_t CodeSignUtils::EnforceCodeSignForFile(const std::string &path, const uin return EnableCodeSignForFile(realPath, arg); } -void CodeSignUtils::ShowCodeSignInfo(const std::string &path, const struct code_sign_enable_arg &arg) -{ - uint8_t *salt = reinterpret_cast(arg.salt_ptr); - uint8_t rootHash[64] = {0}; - uint8_t *rootHashPtr = rootHash; - if (arg.flags & CodeSignBlock::CSB_SIGN_INFO_MERKLE_TREE) { - rootHashPtr = reinterpret_cast(arg.root_hash_ptr); - } - - LOG_DEBUG(LABEL, "{ " - "file:%{public}s version:%{public}d hash_algorithm:%{public}d block_size:%{public}d sig_size:%{public}d " - "data_size:%{public}lld salt_size:%{public}d salt:[%{public}d, ..., %{public}d, ..., %{public}d] " - "flags:%{public}d tree_offset:%{public}lld root_hash:[%{public}d, %{public}d, %{public}d, ..., %{public}d, " - "..., %{public}d] }", - path.c_str(), arg.cs_version, arg.hash_algorithm, arg.block_size, arg.sig_size, - arg.data_size, arg.salt_size, salt[0], salt[16], salt[31], arg.flags, arg.tree_offset, // 16, 31 data index - rootHashPtr[0], rootHashPtr[1], rootHashPtr[2], rootHashPtr[32], rootHashPtr[63]); // 2, 32, 63 data index -} - int32_t CodeSignUtils::EnforceCodeSignForAppWithOwnerId(const std::string &ownerId, const std::string &path, const EntryMap &entryPathMap, FileType type, const std::string &moduleName) { @@ -240,51 +220,41 @@ int32_t CodeSignUtils::EnforceCodeSignForAppWithOwnerId(const std::string &owner LOG_DEBUG(LABEL, "Add entryPathMap complete"); return CS_SUCCESS; } + } else if (type >= FILE_TYPE_MAX) { + return CS_ERR_PARAM_INVALID; } + return ProcessCodeSignBlock(ownerId, path, type, moduleName); +} + +int32_t CodeSignUtils::ProcessCodeSignBlock(const std::string &ownerId, const std::string &path, + FileType type, const std::string &moduleName) +{ std::string realPath; - int32_t ret = IsValidPathAndFileType(path, realPath, type); - if (ret != CS_SUCCESS) { - return ret; + if (!OHOS::PathToRealPath(path, realPath)) { + return CS_ERR_FILE_PATH; } + int32_t ret; EntryMap entryMap; - StoredEntryMapSearch(moduleName, entryMap); - CodeSignBlock codeSignBlock; - ret = codeSignBlock.ParseCodeSignBlock(realPath, entryMap, type); - StoredEntryMapDelete(moduleName); + CodeSignHelper codeSignHelper; + { + std::lock_guard lock(storedEntryMapLock_); + StoredEntryMapSearch(moduleName, entryMap); + ret = codeSignHelper.ParseCodeSignBlock(realPath, entryMap, type); + StoredEntryMapDelete(moduleName); + } if (ret != CS_SUCCESS) { - if ((ret == CS_CODE_SIGN_NOT_EXISTS) && InPermissiveMode()) { - LOG_DEBUG(LABEL, "Code sign not exists"); - return CS_SUCCESS; - } - ReportParseCodeSig(realPath, ret); - return ret; + return HandleCodeSignBlockFailure(realPath, ret); } - CodeSignEnableMultiTask multiTask; - do { - std::string targetFile; - struct code_sign_enable_arg arg = {0}; - ret = codeSignBlock.GetOneFileAndCodeSignInfo(targetFile, arg); - if (ret == CS_SUCCESS_END) { - ret = CS_SUCCESS; - break; - } else if (ret != CS_SUCCESS) { - return ret; - } - ShowCodeSignInfo(targetFile, arg); - if (!CheckFilePathValid(targetFile, Constants::ENABLE_APP_BASE_PATH)) { - return CS_ERR_FILE_PATH; - } - ret = IsSupportFsVerity(targetFile); - if (ret != CS_SUCCESS) { - return ret; - } - multiTask.AddTaskData(targetFile, arg); - } while (ret == CS_SUCCESS); - bool waitStatus = multiTask.ExecuteEnableCodeSignTask(ret, ownerId, path, EnableCodeSignForFile); - if (!waitStatus) { - LOG_ERROR(LABEL, "enable code sign timeout"); - return CS_ERR_ENABLE_TIMEOUT; + return codeSignHelper.ProcessMultiTask(ownerId, path, EnableCodeSignForFile); +} + +int32_t CodeSignUtils::HandleCodeSignBlockFailure(const std::string &realPath, int32_t ret) +{ + if ((ret == CS_CODE_SIGN_NOT_EXISTS) && InPermissiveMode()) { + LOG_DEBUG(LABEL, "Code sign not exists"); + return CS_SUCCESS; } + ReportParseCodeSig(realPath, ret); return ret; } @@ -294,19 +264,6 @@ int32_t CodeSignUtils::EnforceCodeSignForApp(const std::string &path, const Entr return EnforceCodeSignForAppWithOwnerId("", path, entryPathMap, type, moduleName); } -int32_t CodeSignUtils::IsValidPathAndFileType(const std::string &path, std::string &realPath, FileType type) -{ - if (!OHOS::PathToRealPath(path, realPath)) { - return CS_ERR_FILE_PATH; - } - - if (type >= FILE_TYPE_MAX) { - return CS_ERR_PARAM_INVALID; - } - - return CS_SUCCESS; -} - int32_t CodeSignUtils::EnableKeyInProfile(const std::string &bundleName, const ByteBuffer &profileBuffer) { int ret = EnableKeyInProfileByRust(bundleName.c_str(), profileBuffer.GetBuffer(), profileBuffer.GetSize()); @@ -384,13 +341,11 @@ void CodeSignUtils::StoredEntryMapInsert(const std::string &moduleName, const En void CodeSignUtils::StoredEntryMapDelete(const std::string &moduleName) { - std::lock_guard lock(storedEntryMapLock_); storedEntryMap_.erase(moduleName); } void CodeSignUtils::StoredEntryMapSearch(const std::string &moduleName, EntryMap &entryPathMap) { - std::lock_guard lock(storedEntryMapLock_); auto iter = storedEntryMap_.find(moduleName); if (iter != storedEntryMap_.end()) { entryPathMap = iter->second; diff --git a/test/unittest/code_sign_utils_test.cpp b/test/unittest/code_sign_utils_test.cpp index cd54b24..a579846 100644 --- a/test/unittest/code_sign_utils_test.cpp +++ b/test/unittest/code_sign_utils_test.cpp @@ -657,6 +657,46 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0025, TestSize.Level0) int32_t ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_SELF, "EntryAbility"); EXPECT_EQ(ret, CS_CODE_SIGN_NOT_EXISTS); } + +/** + * @tc.name: CodeSignUtilsTest_0026 + * @tc.desc: enable code signature in multiple Hap Scenarios + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0026, TestSize.Level0) +{ + EntryMap entryMap; + CodeSignUtils utils; + std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/demo_with_code_sign_block.hap"; + std::string hapRealPath2 = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-release.hap"; + std::string hapRealPath3 = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-debug.hap"; + + std::string filePath1("libs/arm64-v8a/libc++_shared.so"); + std::string targetPath1 = APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/libc++_shared.so"; + entryMap.emplace(filePath1, targetPath1); + std::string filePath2("libs/arm64-v8a/libentry.so"); + std::string targetPath2 = APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/libentry.so"; + entryMap.emplace(filePath2, targetPath2); + + int32_t ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ENTRY_ADD, "EntryAbility"); + EXPECT_EQ(ret, CS_SUCCESS); + entryMap.clear(); + + ret = utils.EnforceCodeSignForAppWithOwnerId("test-app-identifier", + hapRealPath2, entryMap, FILE_ALL, "EntryAbility2"); + EXPECT_EQ(ret, CS_SUCCESS); + + ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ALL, "EntryAbility"); + EXPECT_EQ(ret, CS_SUCCESS); + + ret = utils.EnforceCodeSignForAppWithOwnerId("DEBUG_LIB_ID", + hapRealPath3, entryMap, FILE_ALL, "EntryAbility3"); + EXPECT_EQ(ret, CS_SUCCESS); + + ret = utils.IsCodeSignEnableCompleted(); + EXPECT_EQ(ret, true); +} } // namespace CodeSign } // namespace Security } // namespace OHOS -- Gitee