diff --git a/README_zh.md b/README_zh.md index c066d7fe4123cddbcf388244837c560102de7a53..526a39910c2aae81d0a9536dd15e7378eb026bf1 100644 --- a/README_zh.md +++ b/README_zh.md @@ -44,10 +44,13 @@ | int32_t EnforceCodeSignForApp(const EntryMap &entryPath, const std::string &signatureFile); | 对hap使能代码签名 | | int32_t EnforceCodeSignForApp(const std::string &path, const EntryMap &entryPathMap, FileType type, uint32_t flag); | 对hap使能代码签名 | | int32_t EnforceCodeSignForFile(const std::string &path, const ByteBuffer &signature); | 对文件使能代码签名 | +| int32_t EnforceCodeSignForFile(const std::string &path); | 对二进制文件使能代码签名 | | int32_t EnforceCodeSignForAppWithOwnerId(std::string ownerId, const std::string &path, const EntryMap &entryPathMap, FileType type, uint32_t flag); | 对hap使能代码签名和OwnerId校验 | | int ParseOwnerIdFromSignature(const ByteBuffer &sigbuffer, std::string &ownerID); | 从签名中解析OwnerId | | int32_t EnableKeyInProfile(const std::string &bundleName, const ByteBuffer &profileBuffer); | 信任开发者证书 | | int32_t RemoveKeyInProfile(const std::string &bundleName); | 撤销已信任的开发者证书 | +| int32_t EnableKey(const CertPathInfo &info); | 信任开发者证书 | +| int32_t RemoveKey(const CertPathInfo &info); | 撤销已信任的开发者证书 | | int32_t InitLocalCertificate(ByteBuffer &cert); | 初始化本地签名证书 | | int32_t SignLocalCode(const std::string &filePath, ByteBuffer &signature); | 本地代码签名 | | int32_t SignLocalCode(const std::string &ownerID, const std::string &filePath, ByteBuffer &signature); | 带OwnerId的本地代码签名 | diff --git a/bundle.json b/bundle.json index 92e1ec868a0ba94f8ab9c45da7ca3190fcf872ee..2be2e522c5cebce1614bd348e339195f54135e03 100644 --- a/bundle.json +++ b/bundle.json @@ -17,6 +17,7 @@ "//base/security/code_signature/hisysevent.yaml" ], "features": [ + "code_signature_support_binary_enable", "code_signature_support_oh_code_sign", "code_signature_enable_xpm_mode", "code_signature_support_oh_release_app", @@ -50,7 +51,8 @@ "bounds_checking_function", "rust_rust-openssl", "selinux", - "rust_cxx" + "rust_cxx", + "elfio" ], "third_party": [] }, diff --git a/code_signature.gni b/code_signature.gni index b8466b701b6bf6de0365443b1bf8618a857607d1..555694a593d8aba6b28595263fbee21f3d414827 100644 --- a/code_signature.gni +++ b/code_signature.gni @@ -27,6 +27,7 @@ declare_args() { code_signature_support_app_allow_list = false code_signature_screenlock_mgr_enable = false code_signature_support_local_debugger = false + code_signature_support_binary_enable = false if (defined(global_parts_info) && defined(global_parts_info.theme_screenlock_mgr)) { code_signature_screenlock_mgr_enable = true diff --git a/interfaces/inner_api/code_sign_utils/BUILD.gn b/interfaces/inner_api/code_sign_utils/BUILD.gn index 1ec18b50206745015d872d9ae6b1f69dacf00c4b..fab97f8b79062c0afc83a1782bf78a8bc94207f7 100644 --- a/interfaces/inner_api/code_sign_utils/BUILD.gn +++ b/interfaces/inner_api/code_sign_utils/BUILD.gn @@ -16,6 +16,9 @@ import("../../../code_signature.gni") config("public_code_sign_utils_configs") { include_dirs = [ "include" ] + if (code_signature_support_binary_enable) { + include_dirs += [ "${code_signature_root_dir}/services/key_enable/utils/include" ] + } } ohos_shared_library("libcode_sign_utils") { @@ -71,6 +74,12 @@ ohos_shared_library("libcode_sign_utils") { "hitrace:hitrace_meter", "openssl:libcrypto_shared", ] + if (code_signature_support_binary_enable) { + sources += [ "${code_signature_root_dir}/utils/src/elf_code_sign_block.cpp" ] + deps += [ "${code_signature_root_dir}/services/key_enable/utils:libkey_enable_utils" ] + defines += [ "SUPPORT_BINARY_ENABLE" ] + external_deps += [ "elfio:elfio" ] + } install_enable = true part_name = "code_signature" 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..afd9da05cbd9f4150000942d5000d36b27ae6307 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 @@ -25,6 +25,9 @@ #include #include "byte_buffer.h" #include "errcode.h" +#ifdef SUPPORT_BINARY_ENABLE +#include "cert_path.h" +#endif namespace OHOS { namespace Security { @@ -113,6 +116,30 @@ public: * @return err code, see err_code.h */ static int32_t RemoveKeyInProfile(const std::string &bundleName); + +#ifdef SUPPORT_BINARY_ENABLE + /** + * @brief Enable certificate path + * @param info CertPathInfo structure containing path information + * @return err code, see err_code.h + */ + static int32_t EnableKey(const CertPathInfo &info); + + /** + * @brief Remove certificate path + * @param info CertPathInfo structure containing path information + * @return err code, see err_code.h + */ + static int32_t RemoveKey(const CertPathInfo &info); + + /** + * @brief Enforce code signature for elf file + * @param path file path + * @return err code, see err_code.h + */ + static int32_t EnforceCodeSignForFile(const std::string &path); +#endif + /** * @brief Whether enabling code signing for app compiled by oh-sdk * @return return ture if support oh-sdk code sign 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 45a318d44cf0319c232f0343b389fc974fd67865..1f7cbf042a8f7f25ac8c83397bcb8ecec6d77e71 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 @@ -41,6 +41,9 @@ #include "signer_info.h" #include "rust_interface.h" #include "data_size_report_adapter.h" +#ifdef SUPPORT_BINARY_ENABLE +#include "elf_code_sign_block.h" +#endif namespace OHOS { namespace Security { @@ -277,6 +280,29 @@ int32_t CodeSignUtils::RemoveKeyInProfile(const std::string &bundleName) return CS_ERR_PROFILE; } +#ifdef SUPPORT_BINARY_ENABLE +int32_t CodeSignUtils::EnableKey(const CertPathInfo &info) +{ + return static_cast(AddCertPath(info)); +} + +int32_t CodeSignUtils::RemoveKey(const CertPathInfo &info) +{ + return static_cast(RemoveCertPath(info)); +} + +int32_t CodeSignUtils::EnforceCodeSignForFile(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); +} +#endif + bool CodeSignUtils::InPermissiveMode() { #ifdef SUPPORT_PERMISSIVE_MODE diff --git a/interfaces/inner_api/common/include/errcode.h b/interfaces/inner_api/common/include/errcode.h index 184ccd98989c462e4a2d63bd7b858126901a6eea..4f25050053c00227565fad67720dc862f2fc5256 100644 --- a/interfaces/inner_api/common/include/errcode.h +++ b/interfaces/inner_api/common/include/errcode.h @@ -100,6 +100,8 @@ enum SignBlockErrCode { CS_ERR_INVALID_EXTENSION_OFFSET = -0x622, CS_ERR_INVALID_PAGE_INFO_EXTENSION = -0x623, CS_ERR_EXTENSION_SIGN_SIZE = -0x624, + CS_ERR_SECTION_OFFSET = -0x625, + CS_ERR_SECTION_SIZE = -0x626, }; enum JitCodeSignErrCode { diff --git a/services/key_enable/utils/src/cert_path.cpp b/services/key_enable/utils/src/cert_path.cpp index c4618255b0fda8778835e657271cfbb7c49f180d..c122a3178b1bddfd0b09ccde388b3042b4db831a 100644 --- a/services/key_enable/utils/src/cert_path.cpp +++ b/services/key_enable/utils/src/cert_path.cpp @@ -23,7 +23,7 @@ #include #include #include -#include "log.h" +#include "log_rust.h" #include "errcode.h" using namespace OHOS::Security::CodeSign; diff --git a/services/key_enable/utils/src/devices_security.cpp b/services/key_enable/utils/src/devices_security.cpp index d1e4e8f4b34474ae81124a4e9c88942a21305649..84464fd49bd1e75d5d24c40a7c654c4188873ae5 100644 --- a/services/key_enable/utils/src/devices_security.cpp +++ b/services/key_enable/utils/src/devices_security.cpp @@ -22,7 +22,7 @@ #include #include -#include "log.h" +#include "log_rust.h" using namespace OHOS::Security::CodeSign; diff --git a/services/key_enable/utils/src/key_utils.cpp b/services/key_enable/utils/src/key_utils.cpp index 82a33cb55e4547138f0ef44927597694b72c4ecd..8c6c4b096eaf69e8575477002c6dc85a535bfb59 100644 --- a/services/key_enable/utils/src/key_utils.cpp +++ b/services/key_enable/utils/src/key_utils.cpp @@ -20,7 +20,7 @@ #include #include -#include "log.h" +#include "log_rust.h" constexpr int KEYCTL_RESTRICT_KEYRING = 29; diff --git a/services/key_enable/utils/src/unlock_event_helper.cpp b/services/key_enable/utils/src/unlock_event_helper.cpp index a71f4a7e77c46267f5bc8a098e427d2b35fad609..b57e9864671ed06342b0ec740ca35f183e1ae196 100644 --- a/services/key_enable/utils/src/unlock_event_helper.cpp +++ b/services/key_enable/utils/src/unlock_event_helper.cpp @@ -18,7 +18,7 @@ #include #include "datetime_ex.h" -#include "log.h" +#include "log_rust.h" #ifdef SCREENLOCK_MANAGER_ENABLED #include "screenlock_manager.h" 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..fefd80e4ce8446f7d876a51a4b883114dbaaf24c --- /dev/null +++ b/utils/include/elf_code_sign_block.h @@ -0,0 +1,77 @@ +/* + * 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 reserved_1[12]; + uint8_t reserved_2[127]; + uint8_t csVersion; + 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 uint16_t ELF_CS_VERSION = 0x3; + static constexpr uint32_t CSB_FS_VERITY_DESCRIPTOR_TYPE = 0x1; + static constexpr uint32_t CSB_FSVERITY_BLOCK_SIZE = 12; + static const std::string CODE_SIGN_SECTION; + + int32_t ParseSignBlock(const std::string &realPath); + int32_t CheckElfSignInfo(const uint64_t csBlockSize); + + std::unique_ptr signBlockBuffer_; + const ElfSignInfo *signInfo_ = nullptr; +}; +} // CodeSign namespace +} // Security namespace +} // OHOS namespace +#endif diff --git a/utils/include/log.h b/utils/include/log.h index 5bae85a9f4df78f9d2130402609db05523cf9b13..6e47c79d35e238e11663c338ec40c0c605fc60bb 100644 --- a/utils/include/log.h +++ b/utils/include/log.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-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 @@ -18,7 +18,6 @@ #include "hilog/log.h" -#ifndef LOG_RUST #ifdef LOG_TAG #undef LOG_TAG #endif @@ -35,25 +34,4 @@ #define LOG_ERROR(fmt, ...) HILOG_ERROR(LOG_CORE, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) #define LOG_FATAL(fmt, ...) HILOG_FATAL(LOG_CORE, "[%{public}s]:" fmt, __func__, ##__VA_ARGS__) -#else // LOG_RUST -namespace OHOS { -namespace Security { -namespace CodeSign { -static constexpr unsigned int SECURITY_DOMAIN = 0xD005A06; -static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN, "CODE_SIGN"}; - -#define LOG_DEBUG(label, fmt, ...) \ - OHOS::HiviewDFX::HiLog::Debug(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) -#define LOG_INFO(label, fmt, ...) \ - OHOS::HiviewDFX::HiLog::Info(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) -#define LOG_WARN(label, fmt, ...) \ - OHOS::HiviewDFX::HiLog::Warn(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) -#define LOG_ERROR(label, fmt, ...) \ - OHOS::HiviewDFX::HiLog::Error(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) -#define LOG_FATAL(label, fmt, ...) \ - OHOS::HiviewDFX::HiLog::Fatal(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) -} -} -} -#endif #endif // CODE_SIGN_LOG_H diff --git a/utils/include/log_rust.h b/utils/include/log_rust.h new file mode 100644 index 0000000000000000000000000000000000000000..17b5a46e8a10d4b2ef00e59ef0d9f4b91e8886db --- /dev/null +++ b/utils/include/log_rust.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025-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 CODE_SIGN_LOG_RUST_H +#define CODE_SIGN_LOG_RUST_H + +#include "hilog/log.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { +static constexpr unsigned int SECURITY_DOMAIN = 0xD005A06; +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN, "CODE_SIGN"}; + +#define LOG_DEBUG(label, fmt, ...) \ + OHOS::HiviewDFX::HiLog::Debug(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) +#define LOG_INFO(label, fmt, ...) \ + OHOS::HiviewDFX::HiLog::Info(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) +#define LOG_WARN(label, fmt, ...) \ + OHOS::HiviewDFX::HiLog::Warn(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) +#define LOG_ERROR(label, fmt, ...) \ + OHOS::HiviewDFX::HiLog::Error(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) +#define LOG_FATAL(label, fmt, ...) \ + OHOS::HiviewDFX::HiLog::Fatal(label, "%{public}s: " fmt, __func__, ##__VA_ARGS__) +} +} +} + +#endif // CODE_SIGN_LOG_RUST_H diff --git a/utils/src/elf_code_sign_block.cpp b/utils/src/elf_code_sign_block.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d405a9a5dfc55ebb9cd2e151676a8507ce1cb2e3 --- /dev/null +++ b/utils/src/elf_code_sign_block.cpp @@ -0,0 +1,124 @@ +/* + * 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 { + +constexpr uint32_t PAGE_SIZE = 4096; +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 = signInfo->version; + arg.cs_version = signInfo->csVersion; + 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.root_hash_ptr = reinterpret_cast(signInfo->rootHash); + arg.flags |= signInfo->flags; + return func(realPath, arg); +} + +int32_t ElfCodeSignBlock::ParseSignBlock(const std::string &realPath) +{ + auto fileSize = std::filesystem::file_size(realPath); + if (fileSize < PAGE_SIZE) { + LOG_ERROR("file size is too small"); + return CS_CODE_SIGN_NOT_EXISTS; + } + ELFIO::elfio elfReader; + if (!elfReader.load(realPath)) { + LOG_ERROR("failed to load input ELF file"); + return CS_ERR_FILE_INVALID; + } + ELFIO::section *sec = elfReader.sections[CODE_SIGN_SECTION]; + if (!sec) { + LOG_ERROR("codesign section is not found"); + return CS_CODE_SIGN_NOT_EXISTS; + } + ELFIO::Elf64_Off secOffElf64 = sec->get_offset(); + uint64_t secOff = static_cast(secOffElf64); + if (secOff % PAGE_SIZE != 0) { + LOG_ERROR("codesign section offset is not aligned"); + return CS_ERR_SECTION_OFFSET; + } + const char *data = sec->get_data(); + uint64_t csBlockSize = sec->get_size(); + if (csBlockSize == 0 || csBlockSize % PAGE_SIZE != 0) { + return CS_ERR_SECTION_SIZE; + } + signBlockBuffer_ = std::make_unique(csBlockSize); + if (memcpy_s(signBlockBuffer_.get(), csBlockSize, data, csBlockSize) != EOK) { + return CS_ERR_MEMORY; + } + signInfo_ = reinterpret_cast(signBlockBuffer_.get()); + return CheckElfSignInfo(csBlockSize); +} + +int32_t ElfCodeSignBlock::CheckElfSignInfo(const uint64_t csBlockSize) +{ + if (signInfo_->type != CSB_FS_VERITY_DESCRIPTOR_TYPE) { + return CS_ERR_SEGMENT_FSVERITY_TYPE; + } + if (signInfo_->length > csBlockSize) { + LOG_ERROR("signInfo length is larger than cs block size"); + return CS_ERR_BLOCK_SIZE; + } + if (signInfo_->version != 1) { + return CS_ERR_FSVERITY_VERSION; + } + if (signInfo_->logBlockSize != CSB_FSVERITY_BLOCK_SIZE) { + return CS_ERR_FSVERITY_BLOCK_SIZE; + } + if (signInfo_->csVersion != ELF_CS_VERSION) { + LOG_ERROR("csVersion is not equal to ELF_CS_VERSION"); + return CS_ERR_BLOCK_VERSION; + } + if (signInfo_->signSize >= signInfo_->length || signInfo_->signSize == 0) { + return CS_ERR_SO_SIGN_SIZE; + } + return CS_SUCCESS; +} +} // CodeSign namespace +} // Security namespace +} // OHOS namespace