diff --git a/bundle.json b/bundle.json index 39019e5e34bd39b0334760e035608b5c8d8ae956..bb85ed3244c4790c9fd047ab037c2b3cf9b0030c 100644 --- a/bundle.json +++ b/bundle.json @@ -49,7 +49,8 @@ "bounds_checking_function", "rust_rust-openssl", "selinux", - "rust_cxx" + "rust_cxx", + "elfio" ], "third_party": [] }, diff --git a/interfaces/inner_api/code_sign_utils/BUILD.gn b/interfaces/inner_api/code_sign_utils/BUILD.gn index 2388b49d18515b96f4cdb2c586a98d36b483f04d..1edb4c4514ea3107a25fd6e6dcae7348c785db78 100644 --- a/interfaces/inner_api/code_sign_utils/BUILD.gn +++ b/interfaces/inner_api/code_sign_utils/BUILD.gn @@ -28,6 +28,7 @@ ohos_shared_library("libcode_sign_utils") { sources = [ "${code_signature_root_dir}/utils/src/code_sign_block.cpp", "${code_signature_root_dir}/utils/src/file_helper.cpp", + "${code_signature_root_dir}/utils/src/elf_code_sign_block.cpp", "src/code_sign_enable_multi_task.cpp", "src/code_sign_helper.cpp", "src/code_sign_utils.cpp", @@ -69,6 +70,7 @@ ohos_shared_library("libcode_sign_utils") { "hisysevent:libhisysevent", "hitrace:hitrace_meter", "openssl:libcrypto_shared", + "elfio:elfio", ] install_enable = true diff --git a/interfaces/inner_api/code_sign_utils/include/code_sign_utils.h b/interfaces/inner_api/code_sign_utils/include/code_sign_utils.h index 52d9425234b467983bcc8afe861c4569efb42c4c..157499e9377f9df5c31070ffbcc1561358d950c6 100644 --- a/interfaces/inner_api/code_sign_utils/include/code_sign_utils.h +++ b/interfaces/inner_api/code_sign_utils/include/code_sign_utils.h @@ -45,6 +45,13 @@ enum CodeSignInfoFlag { class CodeSignUtils { public: + /** + * @brief Enforce code signature for elf file + * @param path file path + * @return err code, see err_code.h + */ + static int32_t EnforceCodeSignForELF(const std::string &path); + /** * @brief Enforce code signature for a hap * @param entryPath map from entryname in hap to real path on disk diff --git a/interfaces/inner_api/code_sign_utils/src/code_sign_utils.cpp b/interfaces/inner_api/code_sign_utils/src/code_sign_utils.cpp index a9fa7aa5814924e0794a8ac6b31cd7cede5d907e..ce42d60a2157166abd67f987cda4cef661ac9b82 100644 --- a/interfaces/inner_api/code_sign_utils/src/code_sign_utils.cpp +++ b/interfaces/inner_api/code_sign_utils/src/code_sign_utils.cpp @@ -40,6 +40,7 @@ #include "stat_utils.h" #include "signer_info.h" #include "rust_interface.h" +#include "elf_code_sign_block.h" namespace OHOS { namespace Security { @@ -54,6 +55,17 @@ constexpr uint32_t HASH_PAGE_SIZE = 4096; } \ } while (0) +int32_t CodeSignUtils::EnforceCodeSignForELF(const std::string &path) +{ + LOG_INFO("Start to enforce codesign elf file: path = %{public}s", path.c_str()); + std::string realPath; + if (!OHOS::PathToRealPath(path, realPath)) { + return CS_ERR_FILE_PATH; + } + ElfCodeSignBlock elfCodeSignBlock; + return elfCodeSignBlock.EnforceCodeSign(realPath, EnableCodeSignForFile); +} + int32_t CodeSignUtils::EnforceCodeSignForApp(const EntryMap &entryPath, const std::string &signatureFile) { diff --git a/utils/BUILD.gn b/utils/BUILD.gn index 37dcd9af81e93c581b72e90ce0cbc5e44ef50207..dcc35246847b1b64993002b49ea7ab7f4a710a2a 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -36,6 +36,7 @@ ohos_source_set("fsverity_sign_src_set") { "fsverity-utils:libfsverity_utils", "hilog:libhilog", "openssl:libcrypto_shared", + "elfio:elfio", ] part_name = "code_signature" subsystem_name = "security" diff --git a/utils/include/elf_code_sign_block.h b/utils/include/elf_code_sign_block.h new file mode 100644 index 0000000000000000000000000000000000000000..83cfdc5129a6e46bab3dbb1868475918c59dbe9d --- /dev/null +++ b/utils/include/elf_code_sign_block.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025 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 ELF_CODE_SIGN_BLOCK_H +#define ELF_CODE_SIGN_BLOCK_H + +#include +#include +#include +#include +#include +#include "errcode.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { + +#pragma pack(push, 1) + +typedef struct { + uint32_t type; + uint32_t length; + uint8_t version; + uint8_t hashAlgorithm; + uint8_t logBlockSize; + uint8_t saltSize; + uint32_t signSize; + uint64_t dataSize; + uint8_t rootHash[64]; + uint8_t salt[32]; + uint32_t flags; + uint8_t reserevd_1[4]; + uint64_t treeOffset; + uint8_t reserevd_2[127]; + uint8_t csVerson; + uint8_t signature[0]; +} ElfSignInfo; + +#pragma pack(pop) + +typedef int32_t CallbackFunc(const std::string &path, const struct code_sign_enable_arg &arg); + +class ElfCodeSignBlock { +public: + ElfCodeSignBlock(); + ~ElfCodeSignBlock(); + + int32_t EnforceCodeSign(const std::string &realPath, CallbackFunc &func); + +private: + + static constexpr uint32_t CSB_FS_VERITY_DESCRIPTOR_TYPE = 0x1; + static constexpr int SIGN_BLOCK_HEADER_SIZE = 32; + static constexpr uint32_t CSB_FSVERITY_BLOCK_SIZE = 12; + static const std::string CODE_SIGN_SECTION; + + int32_t ParseSignBlock(const std::string &realPath); + + std::unique_ptr signHeaderBuffer_; + std::unique_ptr signBlockBuffer_; + const ElfSignInfo *signInfo_ = nullptr; + +}; +} // CodeSign namespace +} // Security namespace +} // OHOS namespace +#endif diff --git a/utils/src/elf_code_sign_block.cpp b/utils/src/elf_code_sign_block.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4adeb0a81b204a32cd1a54867a9f333841a14f0 --- /dev/null +++ b/utils/src/elf_code_sign_block.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 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 "elf_code_sign_block.h" +#include +#include +#include + +#include "constants.h" +#include "directory_ex.h" +#include "log.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { + +const std::string ElfCodeSignBlock::CODE_SIGN_SECTION = ".codesign"; + +ElfCodeSignBlock::ElfCodeSignBlock() +{ +} + +ElfCodeSignBlock::~ElfCodeSignBlock() +{ +} + +int32_t ElfCodeSignBlock::EnforceCodeSign(const std::string &realPath, CallbackFunc &func) +{ + int32_t ret = ParseSignBlock(realPath); + if (ret != CS_SUCCESS) { + return ret; + } + auto signInfo = signInfo_; + struct code_sign_enable_arg arg = {0}; + arg.version = 1; + arg.cs_version = signInfo->csVerson; + arg.hash_algorithm = signInfo->hashAlgorithm; + arg.block_size = 1 << signInfo->logBlockSize; + arg.salt_ptr = reinterpret_cast(signInfo->salt); + arg.salt_size = signInfo->saltSize; + arg.sig_size = signInfo->signSize; + arg.sig_ptr = reinterpret_cast(signInfo->signature); + arg.data_size = signInfo->dataSize; + arg.tree_offset = signInfo->treeOffset; + arg.root_hash_ptr = reinterpret_cast(signInfo->rootHash); + arg.flags |= signInfo->flags; + int8_t *sign_ptr = reinterpret_cast(arg.sig_ptr); + LOG_DEBUG("sign_ptr = %{public}d %{public}d %{public}d %{public}d %{public}d ", + sign_ptr[0], sign_ptr[1], sign_ptr[2], sign_ptr[10], sign_ptr[11]); + return func(realPath, arg); +} + +int32_t ElfCodeSignBlock::ParseSignBlock(const std::string &realPath) +{ + auto fileSize = std::filesystem::file_size(realPath); + if (fileSize < SIGN_BLOCK_HEADER_SIZE) { + LOG_ERROR("file size is too small"); + return CS_CODE_SIGN_NOT_EXISTS; + } + ELFIO::elfio elfReader; + if (!elfReader.load(realPath)) { + LOG_ERROR("[SignElf] Failed to load input ELF file"); + return CS_ERR_FILE_INVALID; + } + ELFIO::section* sec = elfReader.sections[CODE_SIGN_SECTION]; + if (!sec) { + LOG_ERROR("[SignElf] .codesign section not exists"); + return CS_CODE_SIGN_NOT_EXISTS; + } + + ELFIO::Elf64_Off secOff = sec->get_offset(); + LOG_DEBUG("secOff = %{public}llu ", secOff); + + return 0; +} +} // CodeSign namespace +} // Security namespace +} // OHOS namespace