diff --git a/binary_sign_tool/BUILD.gn b/binary_sign_tool/BUILD.gn index d955c181d7d4d3cdacd128fd91c5b2c68b5f3128..733ffddd947c6d0645b67556b6bc2a69ccaaa0b0 100644 --- a/binary_sign_tool/BUILD.gn +++ b/binary_sign_tool/BUILD.gn @@ -12,8 +12,7 @@ # limitations under the License. import("cmd/signature_tools_cmd.gni") - -# import("codesigning/signature_tools_codesigning.gni") +import("codesigning/signature_tools_codesigning.gni") import("common/signature_tools_common.gni") import("hap/signature_tools_hap.gni") import("profile/signature_tools_profile.gni") @@ -54,7 +53,7 @@ signature_tools_main_src = [ ohos_executable("binary-sign-tool") { signature_tools_main_include += signature_tools_utils_include - # signature_tools_main_include += signature_tools_codesigning_include + signature_tools_main_include += signature_tools_codesigning_include signature_tools_main_include += signature_tools_common_include signature_tools_main_include += signature_tools_hap_include signature_tools_main_include += signature_tools_profile_include @@ -63,8 +62,7 @@ ohos_executable("binary-sign-tool") { # 在 //developtools/signaturetools/services/utils 模块里面定义编译脚本 signature_tools_utils.gni signature_tools_main_src += signature_tools_utils_src - - # signature_tools_main_src += signature_tools_codesigning_src + signature_tools_main_src += signature_tools_codesigning_src signature_tools_main_src += signature_tools_common_src signature_tools_main_src += signature_tools_hap_src signature_tools_main_src += signature_tools_profile_src diff --git a/binary_sign_tool/api/include/sign_tool_service_impl.h b/binary_sign_tool/api/include/sign_tool_service_impl.h index 3520547a80e476c72e9c212ae9de245fe95e864d..149fbfb48f27f8ff16b819436f38ff3d980d055f 100644 --- a/binary_sign_tool/api/include/sign_tool_service_impl.h +++ b/binary_sign_tool/api/include/sign_tool_service_impl.h @@ -30,9 +30,6 @@ public: SignToolServiceImpl() = default; virtual ~SignToolServiceImpl() = default; bool Sign(Options* options)override; - -private: - bool SignAdHoc(Options* options); }; } // namespace SignatureTools } // namespace OHOS diff --git a/binary_sign_tool/api/src/sign_tool_service_impl.cpp b/binary_sign_tool/api/src/sign_tool_service_impl.cpp index 3fe16f3d2a632f5fbaee0e7dd3f5df39f6621618..44147135cbf970e89616a24f6d4fa1f3b2d1646e 100644 --- a/binary_sign_tool/api/src/sign_tool_service_impl.cpp +++ b/binary_sign_tool/api/src/sign_tool_service_impl.cpp @@ -20,6 +20,7 @@ #include "profile_info.h" #include "profile_verify.h" #include "signature_tools_errno.h" +#include "ad_hoc_sign_provider.h" #include "local_sign_provider.h" #include "signature_tools_log.h" #include "param_constants.h" @@ -35,12 +36,12 @@ bool SignToolServiceImpl::Sign(Options* options) SIGNATURE_TOOLS_LOGE("inFile is not a elf file"); return false; } - if (options->GetString(Options::AD_HOC) == ParamConstants::AD_HOC_TYPE_1) { - return SignAdHoc(options); - } std::string mode = options->GetString(Options::MODE); + std::string adhoc = options->GetString(Options::AD_HOC); std::shared_ptr signProvider; - if (LOCAL_SIGN == mode) { + if (ParamConstants::AD_HOC_TYPE_1 == adhoc) { + signProvider = std::make_shared(); + } else if (LOCAL_SIGN == mode) { signProvider = std::make_shared(); } else if (REMOTE_SIGN == mode) { signProvider = std::make_shared(); @@ -72,21 +73,5 @@ int SignToolServiceImpl::GetProvisionContent(const std::string& input, std::stri } return 0; } - -bool SignToolServiceImpl::SignAdHoc(Options* options) -{ - std::string inFile = options->GetString(Options::IN_FILE); - std::string outFile = options->GetString(Options::OUT_FILE); - std::string tmpOutFile = outFile; - if (outFile == inFile) { - tmpOutFile = "tmp-signed-elf"; - } - bool ret = std::filesystem::copy_file(inFile, tmpOutFile, std::filesystem::copy_options::overwrite_existing); - if (!ret) { - SIGNATURE_TOOLS_LOGE("Error: SignAdHoc failed"); - return false; - } - return FileUtils::CopyTmpFileAndDel(tmpOutFile, outFile); -} } // namespace SignatureTools } // namespace OHOS diff --git a/binary_sign_tool/cmd/include/cmd_util.h b/binary_sign_tool/cmd/include/cmd_util.h deleted file mode 100644 index 00e8996d5fc4139282ab6d6b23de5fadf6df869c..0000000000000000000000000000000000000000 --- a/binary_sign_tool/cmd/include/cmd_util.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 SIGNATRUETOOLS_CMD_UTIL_H -#define SIGNATRUETOOLS_CMD_UTIL_H - -#include -#include -#include -#include -#include -#include - -#include "params.h" -#include "params_trust_list.h" -#include "sign_tool_service_impl.h" -#include "signature_tools_log.h" -#include "verify_hap_openssl_utils.h" - -namespace OHOS { -namespace SignatureTools { -class CmdUtil final { -public: - static bool Convert2Params(char** args, const size_t size, const ParamsSharedPtr& param); - static bool JudgeSignAlgType(const std::string& signAlg); - static bool String2Bool(Options* options, const std::string& option); - static bool UpdateParamForCheckInFile(Options* options, const std::initializer_list& inFileKeys); - static bool UpdateParamForCheckOutFile(Options* options, const std::initializer_list& outFileKeys); - static constexpr int ARGS_MIN_LEN = 2; - -private: - static int GetCommandParameterKey(const char strChar, std::string& strChars, - std::vector& trustList, std::string& keyStandBy); - static bool ValidAndPutParam(const ParamsSharedPtr& params, const std::string& key, char* value); - static const std::regex INTEGER_PATTERN; -}; -} // namespace SignatureTools -} // namespace OHOS -#endif diff --git a/binary_sign_tool/cmd/include/help.h b/binary_sign_tool/cmd/include/help.h index a4b797f088ac93e290e30972bd54f0b09215e871..c59a16cd86ca79f716416bc65ac01b696da8b4ec 100644 --- a/binary_sign_tool/cmd/include/help.h +++ b/binary_sign_tool/cmd/include/help.h @@ -24,10 +24,10 @@ namespace OHOS { namespace SignatureTools { const std::string HELP_TXT_HEADER = R"( -USAGE: [options] +USAGE: [options] )"; -const std::string SIGN_APP_HELP_TXT = R"( +const std::string SIGN_HELP_TXT = R"( sign[options]: -mode : signature mode, required fields, including localSign/remoteSign/remoteResign; -keyAlias : key alias, required fields; @@ -62,23 +62,12 @@ const std::string SIGN_APP_HELP_TXT = R"( -profileFile "/home/signed-profile.p7b" -inFile "/home/app1-unsigned.hap" -signAlg SHA256withECDSA )"; -const std::string VERIFY_APP_HELP_TXT = R"( - verify-app[options]: - -inFile : signed application package file, hap or bin format, required fields; - -outCertChain : signed certificate chain file, required fields; - -outProfile : profile file in application package, required fields; - - EXAMPLE: - verify-app-inFile "/home/app1-signed.hap" -outCertChain "outCertChain.cer" -outProfile "outprofile.p7b" -)"; - const std::string HELP_END_TXT = R"( COMMANDS : sign : application package signature - verify-app : application package file verification )"; /* help.txt all content */ -const std::string HELP_TXT = HELP_TXT_HEADER + SIGN_APP_HELP_TXT + VERIFY_APP_HELP_TXT + HELP_END_TXT; +const std::string HELP_TXT = HELP_TXT_HEADER + SIGN_HELP_TXT + HELP_END_TXT; } } #endif \ No newline at end of file diff --git a/binary_sign_tool/cmd/include/params_run_tool.h b/binary_sign_tool/cmd/include/params_run_tool.h deleted file mode 100644 index dce33852b2e635d7643892feac5b9362f2217ba3..0000000000000000000000000000000000000000 --- a/binary_sign_tool/cmd/include/params_run_tool.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 SIGNATRUETOOLS_HAP_SIGN_TOOL_H -#define SIGNATRUETOOLS_HAP_SIGN_TOOL_H - -#include -#include -#include - -#include "cmd_util.h" -#include "sign_tool_service_impl.h" -#include "signature_tools_log.h" -#include "params_trust_list.h" -#include "string_utils.h" - -namespace OHOS { -namespace SignatureTools { -class ParamsRunTool final { -public: - ParamsRunTool() = delete; - static bool ProcessCmd(char** args, size_t size); - static bool DispatchParams(const ParamsSharedPtr& params, SignToolServiceImpl& api); - static bool RunSignApp(Options* params, SignToolServiceImpl& api); - static bool CheckProfile(Options& params); - static void PrintHelp(); - static void Version(); - -private: - static const std::string VERSION; -}; -} // namespace SignatureTools -} // namespace OHOS -#endif // SIGNATRUETOOLS_HAP_SIGN_TOOL_H diff --git a/binary_sign_tool/cmd/signature_tools_cmd.gni b/binary_sign_tool/cmd/signature_tools_cmd.gni index 2681dd6a70dfe8f9c534dac9c527903151b75989..95d75cdaa58b24da66c257d4c4421d5ecb4ce7fc 100644 --- a/binary_sign_tool/cmd/signature_tools_cmd.gni +++ b/binary_sign_tool/cmd/signature_tools_cmd.gni @@ -12,11 +12,14 @@ # limitations under the License. import("../signature_tools.gni") -signature_tools_cmd_include = [ "${signature_tools_cmd}/include" ] +signature_tools_cmd_include = [ + "${signature_tools_cmd}/include", + "${hapsigntool_cpp_cmd}/include", +] signature_tools_cmd_src = [ "${signature_tools_cmd}/src/cmd_util.cpp", "${signature_tools_cmd}/src/params_run_tool.cpp", "${signature_tools_cmd}/src/params_trust_list.cpp", - "${signature_tools_cmd}/src/params.cpp", + "${hapsigntool_cpp_cmd}/src/params.cpp", ] diff --git a/binary_sign_tool/cmd/src/cmd_util.cpp b/binary_sign_tool/cmd/src/cmd_util.cpp index efb9b46b0c384c04b1e60145099249dc6f06a7ad..6b2b5b1572e49ab9fc94964b873c46df8e285ac2 100644 --- a/binary_sign_tool/cmd/src/cmd_util.cpp +++ b/binary_sign_tool/cmd/src/cmd_util.cpp @@ -87,18 +87,6 @@ static bool UpdateParamForVariantInt(const ParamsSharedPtr& param) return false; } } - if (options->count(Options::BASIC_CONSTRAINTS_PATH_LEN)) { - int basicConstraintsPathLen = 0; - std::string val = options->GetString(Options::BASIC_CONSTRAINTS_PATH_LEN); - if (!StringUtils::CheckStringToint(val, basicConstraintsPathLen)) { - PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, "Invalid parameter '" - + val + "', You should fill in the numbers"); - return false; - } - (*options)[Options::BASIC_CONSTRAINTS_PATH_LEN] = basicConstraintsPathLen; - } else if (param->GetMethod() == GENERATE_CA || param->GetMethod() == GENERATE_CERT) { - (*options)[Options::BASIC_CONSTRAINTS_PATH_LEN] = DEFAULT_BASIC_CONSTRAINTS_PATH_LEN; - } if (!UpdateParamForVariantCertInt(param)) { return false; } @@ -278,29 +266,6 @@ static bool UpdateParamForOutform(const ParamsSharedPtr& param) return true; } -// Check "remoteSign" additional parameters are required -static bool UpdateParamForCheckRemoteSignProfile(const ParamsSharedPtr& param) -{ - Options* options = param->GetOptions(); - std::set signProfileRemoteParams{ParamConstants::PARAM_REMOTE_SERVER, - ParamConstants::PARAM_REMOTE_USERNAME, - ParamConstants::PARAM_REMOTE_USERPWD, - ParamConstants::PARAM_REMOTE_ONLINEAUTHMODE, - ParamConstants::PARAM_REMOTE_SIGNERPLUGIN}; - - if (param->GetMethod() == SIGN_PROFILE && options->count(Options::MODE) && - options->GetString(Options::MODE) == REMOTE_SIGN) { - for (const std::string& key : signProfileRemoteParams) { - if (options->count(key) == 0) { - PrintErrorNumberMsg("COMMAND_ERROR", COMMAND_ERROR, "sign profile RemoteSign absence param '" - + key + "'"); - return false; - } - } - } - return true; -} - static bool UpdateParam(const ParamsSharedPtr& param) { if (!UpdateParamForVariantInt(param)) { @@ -321,9 +286,6 @@ static bool UpdateParam(const ParamsSharedPtr& param) if (!UpdateParamForOutform(param)) { return false; } - if (!UpdateParamForCheckRemoteSignProfile(param)) { - return false; - } return true; } diff --git a/binary_sign_tool/cmd/src/params.cpp b/binary_sign_tool/cmd/src/params.cpp deleted file mode 100644 index a8c51f833c980c40dba26a17c921f61dca9c2da4..0000000000000000000000000000000000000000 --- a/binary_sign_tool/cmd/src/params.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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. - */ - -#include "params.h" - -namespace OHOS { -namespace SignatureTools { -Params::Params() : options(new Options) { -} - -Params::~Params() -{ - if (options) { - delete options; - options = NULL; - } -} - -std::string Params::GetMethod() -{ - return method; -} - -void Params::SetMethod(const std::string& method) -{ - this->method = method; -} - -Options* Params::GetOptions() -{ - return options; -} - -std::unordered_set Params::InitParamField(const std::vector& paramFields) -{ - return std::unordered_set(paramFields.begin(), paramFields.end()); -} - -bool Params::GetSignatureAlgorithm(const std::string& signatureAlgorithm, - SignatureAlgorithmHelper& out) -{ - if (signatureAlgorithm == ParamConstants::HAP_SIG_ALGORITHM_SHA256_ECDSA) { - out = SignatureAlgorithmHelper::ECDSA_WITH_SHA256_INSTANCE; - return true; - } else if (signatureAlgorithm == ParamConstants::HAP_SIG_ALGORITHM_SHA384_ECDSA) { - out = SignatureAlgorithmHelper::ECDSA_WITH_SHA384_INSTANCE; - return true; - } else { - SIGNATURE_TOOLS_LOGE("get Signature Algorithm failed not support %s", signatureAlgorithm.c_str()); - return false; - } - return true; -} - -} // namespace SignatureTools -} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/cmd/src/params_run_tool.cpp b/binary_sign_tool/cmd/src/params_run_tool.cpp index 61727cc4e276054a5fc252cdcdfb4e475428862b..1136bf6dc50ec331bff8b5887537a0c3294b77ec 100644 --- a/binary_sign_tool/cmd/src/params_run_tool.cpp +++ b/binary_sign_tool/cmd/src/params_run_tool.cpp @@ -78,15 +78,15 @@ bool ParamsRunTool::RunSignApp(Options* params, SignToolServiceImpl& api) if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_FILE})) { return false; } - if (params->GetString(Options::AD_HOC) == ParamConstants::AD_HOC_TYPE_1) { - return api.Sign(params); - } std::string mode = params->GetString(Options::MODE); if (!StringUtils::CaseCompare(mode, LOCAL_SIGN) && !StringUtils::CaseCompare(mode, REMOTE_SIGN)) { PrintErrorNumberMsg("COMMAND_ERROR", COMMAND_ERROR, "not support command param '" + mode + "'"); return false; } + if (params->GetString(Options::AD_HOC) == ParamConstants::AD_HOC_TYPE_1) { + return api.Sign(params); + } if (StringUtils::CaseCompare(mode, LOCAL_SIGN)) { if (!params->Required({Options::KEY_STORE_FILE, Options::KEY_ALIAS, Options::APP_CERT_FILE})) { return false; @@ -109,6 +109,10 @@ bool ParamsRunTool::CheckProfile(Options& params) { std::string profileFile = params.GetString(Options::PROFILE_FILE); std::string profileSigned = params.GetString(Options::PROFILE_SIGNED); + if (profileFile.empty()) { + SIGNATURE_TOOLS_LOGI("[SignElf] No profile file"); + return true; + } if (profileSigned == DEFAULT_PROFILE_SIGNED_1) { if (!FileUtils::ValidFileType(profileFile, {"p7b"})) { return false; diff --git a/binary_sign_tool/cmd/src/params_trust_list.cpp b/binary_sign_tool/cmd/src/params_trust_list.cpp index d91f1ab3a3bca07df83623205d8b8b083adc8008..9b6bff64813267dd0e4bc4f35cd410f778ca729c 100644 --- a/binary_sign_tool/cmd/src/params_trust_list.cpp +++ b/binary_sign_tool/cmd/src/params_trust_list.cpp @@ -26,10 +26,7 @@ namespace SignatureTools { const std::string options = "[options]:"; const std::vector commands = { - SIGN_PROFILE + options, - VERIFY_PROFILE + options, SIGN_ELF + options, - VERIFY_APP + options }; ParamsTrustList ParamsTrustList::GetInstance() diff --git a/binary_sign_tool/cmd/include/params.h b/binary_sign_tool/codesigning/fsverity/include/fs_verity_generator.h similarity index 31% rename from binary_sign_tool/cmd/include/params.h rename to binary_sign_tool/codesigning/fsverity/include/fs_verity_generator.h index 06cf85b36ccc069d5d0b6010170ad8045818a4b0..b15045673669d4462548f6b9925b6719965aa205 100644 --- a/binary_sign_tool/cmd/include/params.h +++ b/binary_sign_tool/codesigning/fsverity/include/fs_verity_generator.h @@ -12,40 +12,82 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef SIGNATURETOOLS_FSVERITY_GENERATOR_H +#define SIGNATURETOOLS_FSVERITY_GENERATOR_H -#ifndef SIGNATRUETOOLS_PARAMS_H -#define SIGNATRUETOOLS_PARAMS_H - -#include -#include -#include -#include -#include #include +#include +#include -#include "options.h" -#include "signature_algorithm_helper.h" -#include "param_constants.h" +#include "merkle_tree.h" +#include "merkle_tree_builder.h" +#include "fs_verity_descriptor.h" +#include "fs_verity_digest.h" namespace OHOS { namespace SignatureTools { -class Params { +class FsVerityGenerator { public: - static std::unordered_set InitParamField(const std::vector& paramFields); - static bool GetSignatureAlgorithm(const std::string& signatureAlgorithm, SignatureAlgorithmHelper& out); - Params(); - ~Params(); - std::string GetMethod(); - void SetMethod(const std::string& method); - Options* GetOptions(); + MerkleTree* GenerateMerkleTree(std::istream& inputStream, long size, + const FsVerityHashAlgorithm& fsVerityHashAlgorithm); + bool GenerateFsVerityDigest(std::istream& inputStream, long size, int flags); + std::vector GetFsVerityDigest() + { + return fsVerityDigest; + } -private: - Options* options; - std::string method; -}; + std::vector GetDescriptorDigest() + { + return descriptorDigest; + } + + std::vector GetTreeBytes() + { + return treeBytes; + } + + std::vector GetRootHash() + { + return rootHash; + } -using ParamsSharedPtr = std::shared_ptr; + std::vector GetSalt() + { + return salt; + } + int GetSaltSize() + { + return salt.empty() ? 0 : salt.size(); + } + + void SetCsOffset(uint64_t& csOffset) + { + this->csOffset = csOffset; + } + + static uint8_t GetFsVerityHashAlgorithm() + { + return FS_VERITY_HASH_ALGORITHM.GetId(); + } + + static uint8_t GetLog2BlockSize() + { + return LOG_2_OF_FSVERITY_HASH_PAGE_SIZE; + } + +protected: + std::vector salt; + +private: + static const FsVerityHashAlgorithm FS_VERITY_HASH_ALGORITHM; + static const int8_t LOG_2_OF_FSVERITY_HASH_PAGE_SIZE; + std::vector descriptorDigest; + std::vector fsVerityDigest; + std::vector treeBytes; + std::vector rootHash; + uint64_t csOffset = 0; +}; } // namespace SignatureTools } // namespace OHOS -#endif // SIGNATRUETOOLS_PARAMS_H +#endif // SIGNATURETOOLS_FSVERITY_GENERATOR_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/include/merkle_tree_builder.h b/binary_sign_tool/codesigning/fsverity/include/merkle_tree_builder.h new file mode 100644 index 0000000000000000000000000000000000000000..123df7d16c652ab06419815ddf792300261e1eca --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/include/merkle_tree_builder.h @@ -0,0 +1,79 @@ +/* + * 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 SIGNATURETOOLS_MERKLE_TREE_BUILDER_H +#define SIGNATURETOOLS_MERKLE_TREE_BUILDER_H + +#include +#include +#include +#include +#include +#include + +#include "thread_pool.h" +#include "byte_buffer.h" +#include "merkle_tree.h" +#include "fs_digest_utils.h" +#include "signature_tools_log.h" + +namespace OHOS { +namespace SignatureTools { +class MerkleTreeBuilder { +public: + MerkleTreeBuilder(); + MerkleTree* GenerateMerkleTree(std::istream& inputStream, long size, + const FsVerityHashAlgorithm& fsVerityHashAlgorithm); + + void SetCsOffset(uint64_t& csOffset) + { + this->csOffset = csOffset; + } + +private: + static const int FSVERITY_HASH_PAGE_SIZE; + static const int64_t INPUTSTREAM_MAX_SIZE; + static const int CHUNK_SIZE; + static const long MAX_READ_SIZE; + static const int MAX_PROCESSORS; + static const int BLOCKINGQUEUE; + static ByteBuffer* Slice(ByteBuffer* buffer, int begin, int end); + static std::vector GetOffsetArrays(long dataSize, int digestSize); + static std::vector GetLevelSize(long dataSize, int digestSize); + static long GetChunkCount(long dataSize, long divisor); + static long GetFullChunkSize(long dataSize, long divisor, long multiplier); + void SetAlgorithm(const std::string& algorithm); + void TransInputStreamToHashData(std::istream& inputStream, long size, + ByteBuffer* outputBuffer, int bufStartIdx); + std::vector> GetDataHashes(std::istream& inputStream, long size); + + void RunHashTask(std::vector>& hashes, ByteBuffer* buffer, + int readChunkIndex, int bufStartIdx); + void TransInputDataToHashData(ByteBuffer* inputBuffer, ByteBuffer* outputBuffer, + int64_t bufStartIdx, int64_t outputStartIdx); + void GenerateHashDataByInputData(std::istream& inputStream, long size, ByteBuffer* outputBuffer, + std::vector& offsetArrays, int digestSize); + void GenerateHashDataByHashData(ByteBuffer* buffer, std::vector& offsetArrays, int digestSize); + MerkleTree* GetMerkleTree(ByteBuffer* dataBuffer, long inputDataSize, + FsVerityHashAlgorithm fsVerityHashAlgorithm); + void DataRoundupChunkSize(ByteBuffer* data, long originalDataSize, int digestSize); + bool CheckCalculateHashResult; + const int POOL_SIZE = std::min(MAX_PROCESSORS, static_cast(std::thread::hardware_concurrency())); + std::string mAlgorithm = "SHA-256"; + std::shared_ptr mPools; + uint64_t csOffset = 0; +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATURETOOLS_MERKLE_TREE_BUILDER_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/src/fs_verity_descriptor.cpp b/binary_sign_tool/codesigning/fsverity/src/fs_verity_descriptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..249baf85e3178beacb1c538b9c13d16a47789abf --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/src/fs_verity_descriptor.cpp @@ -0,0 +1,93 @@ +/* + * 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. + */ +#include "fs_verity_descriptor.h" + +namespace OHOS { +namespace SignatureTools { +FsVerityDescriptor::FsVerityDescriptor() +{} + +void FsVerityDescriptor::ToByteArray(std::vector &ret) +{ + std::unique_ptr buffer = std::make_unique(ByteBuffer(DESCRIPTOR_SIZE)); + buffer->PutByte(VERSION); + buffer->PutByte(hashAlgorithm); + buffer->PutByte(log2BlockSize); + if (saltSize > SALT_SIZE) { + PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Salt is too long"); + ret = std::vector(); + return; + } + buffer->PutByte(saltSize); + buffer->PutInt32(signSize); + buffer->PutInt64(fileSize); + WriteBytesWithSize(buffer.get(), rawRootHash, ROOT_HASH_FILED_SIZE); + WriteBytesWithSize(buffer.get(), salt, SALT_SIZE); + buffer->PutInt32(flags); + std::vector emptyVector; + WriteBytesWithSize(buffer.get(), emptyVector, RESERVED_SIZE_AFTER_FLAGS); + buffer->PutInt64(merkleTreeOffset); + WriteBytesWithSize(buffer.get(), emptyVector, RESERVED_SIZE_AFTER_TREE_OFFSET); + buffer->PutByte(csVersion); + buffer->Flip(); + char dataArr[DESCRIPTOR_SIZE] = { 0 }; + buffer->GetData(dataArr, DESCRIPTOR_SIZE); + ret = std::vector(dataArr, dataArr + DESCRIPTOR_SIZE); + return; +} + +void FsVerityDescriptor::GetByteForGenerateDigest(std::vector &ret) +{ + std::unique_ptr buffer = std::make_unique(ByteBuffer(DESCRIPTOR_SIZE)); + buffer->PutByte(VERSION); + buffer->PutByte(hashAlgorithm); + buffer->PutByte(log2BlockSize); + if (saltSize > SALT_SIZE) { + PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Salt is too long"); + ret = std::vector(); + return; + } + buffer->PutByte(saltSize); + buffer->PutInt32(0); + buffer->PutInt64(fileSize); + WriteBytesWithSize(buffer.get(), rawRootHash, ROOT_HASH_FILED_SIZE); + WriteBytesWithSize(buffer.get(), salt, SALT_SIZE); + buffer->PutInt32(flags); + std::vector emptyVector; + WriteBytesWithSize(buffer.get(), emptyVector, RESERVED_SIZE_AFTER_FLAGS); + buffer->PutInt64(merkleTreeOffset); + WriteBytesWithSize(buffer.get(), emptyVector, RESERVED_SIZE_AFTER_TREE_OFFSET); + buffer->PutByte(csVersion); + buffer->Flip(); + char dataArr[DESCRIPTOR_SIZE] = { 0 }; + buffer->GetData(dataArr, DESCRIPTOR_SIZE); + ret = std::vector(dataArr, dataArr + DESCRIPTOR_SIZE); + return; +} + +void FsVerityDescriptor::WriteBytesWithSize(ByteBuffer* buffer, std::vector& src, int size) +{ + int pos = buffer->GetPosition(); + if (!src.empty()) { + if (src.size() > size) { + buffer->PutData(0, src.data(), src.size()); + } else { + buffer->PutData(src.data(), src.size()); + } + } + buffer->SetPosition(pos + size); +} +} // namespace SignatureTools +} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/src/fs_verity_generator.cpp b/binary_sign_tool/codesigning/fsverity/src/fs_verity_generator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5da83541bbff566beefbb16f1cf2aa515319bdee --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/src/fs_verity_generator.cpp @@ -0,0 +1,68 @@ +/* + * 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. + */ +#include "fs_verity_generator.h" + +namespace OHOS { +namespace SignatureTools { +const FsVerityHashAlgorithm FS_SHA256(1, "SHA-256", 256 / 8); +const FsVerityHashAlgorithm FS_SHA512(2, "SHA-512", 512 / 8); +const int8_t FsVerityGenerator::LOG_2_OF_FSVERITY_HASH_PAGE_SIZE = 12; +const uint8_t ELF_CODE_SIGN_VERSION = 0x3; +const FsVerityHashAlgorithm FsVerityGenerator::FS_VERITY_HASH_ALGORITHM = FS_SHA256; + +MerkleTree* FsVerityGenerator::GenerateMerkleTree(std::istream& inputStream, long size, + const FsVerityHashAlgorithm& fsVerityHashAlgorithm) +{ + std::unique_ptrbuilder = std::make_unique(MerkleTreeBuilder()); + builder->SetCsOffset(csOffset); + return builder->GenerateMerkleTree(inputStream, size, fsVerityHashAlgorithm); +} + +bool FsVerityGenerator::GenerateFsVerityDigest(std::istream& inputStream, long size, int flags) +{ + MerkleTree* merkleTree = GenerateMerkleTree(inputStream, size, FS_SHA256); + if (merkleTree == nullptr) { + return false; + } + std::shared_ptr merkleTree_ptr(merkleTree); + // sign size is 0, + std::unique_ptr builder = std::make_unique(); + builder->SetFileSize(size) + .SetHashAlgorithm(FS_SHA256.GetId()) + .SetLog2BlockSize(LOG_2_OF_FSVERITY_HASH_PAGE_SIZE) + .SetSaltSize((uint8_t)GetSaltSize()) + .SetSalt(salt) + .SetRawRootHash(merkleTree_ptr->rootHash) + .SetFlags(flags) + .SetCsVersion(ELF_CODE_SIGN_VERSION); + std::vector fsVerityDescriptor; + builder->Build().GetByteForGenerateDigest(fsVerityDescriptor); + DigestUtils digestUtils(HASH_SHA256); + std::stringstream ss; + for (const auto& elem : fsVerityDescriptor) { + ss << elem; + } + digestUtils.AddData(ss.str()); + std::string result = digestUtils.Result(DigestUtils::Type::BINARY); + for (long i = 0; i < result.size(); i++) { + descriptorDigest.push_back(result[i]); + } + FsVerityDigest::GetFsVerityDigest(FS_SHA256.GetId(), descriptorDigest, fsVerityDigest); + treeBytes = merkleTree_ptr->tree; + rootHash = merkleTree_ptr->rootHash; + return true; +} +} // namespace SignatureTools +} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/src/merkle_tree_builder.cpp b/binary_sign_tool/codesigning/fsverity/src/merkle_tree_builder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e23042cf2e741fc833b0c70d64f45d99189a37a --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/src/merkle_tree_builder.cpp @@ -0,0 +1,304 @@ +/* + * 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. + */ +#include + +#include "merkle_tree_builder.h" + +using namespace OHOS::SignatureTools::Uscript; +namespace OHOS { +namespace SignatureTools { + +const int MerkleTreeBuilder::FSVERITY_HASH_PAGE_SIZE = 4096; +const int64_t MerkleTreeBuilder::INPUTSTREAM_MAX_SIZE = 4503599627370496L; +const int MerkleTreeBuilder::CHUNK_SIZE = 4096; +const long MerkleTreeBuilder::MAX_READ_SIZE = 4194304L; +const int MerkleTreeBuilder::MAX_PROCESSORS = 32; +const int MerkleTreeBuilder::BLOCKINGQUEUE = 4; + +void MerkleTreeBuilder::SetAlgorithm(const std::string& algorithm) +{ + mAlgorithm = algorithm; +} + +void MerkleTreeBuilder::TransInputStreamToHashData(std::istream& inputStream, + long size, ByteBuffer* outputBuffer, int bufStartIdx) +{ + if (size == 0 || static_cast(size) > INPUTSTREAM_MAX_SIZE) { + SIGNATURE_TOOLS_LOGE("invalid input stream size"); + CheckCalculateHashResult = false; + return; + } + std::vector> hashes = GetDataHashes(inputStream, size); + int32_t writeSize = 0; + for (const auto& hash : hashes) { + outputBuffer->PutData(writeSize + bufStartIdx, hash.data(), hash.size()); + writeSize += hash.size(); + } + outputBuffer->SetLimit(outputBuffer->GetCapacity() - bufStartIdx); + outputBuffer->SetCapacity(outputBuffer->GetCapacity() - bufStartIdx); + outputBuffer->SetPosition(writeSize); +} + +std::vector> MerkleTreeBuilder::GetDataHashes(std::istream& inputStream, long size) +{ + int count = (int)(GetChunkCount(size, MAX_READ_SIZE)); + int chunks = (int)(GetChunkCount(size, CHUNK_SIZE)); + std::vector> hashes(chunks); + std::vector> thread_results; + long readOffset = 0L; + for (int i = 0; i < count; i++) { + long readLimit = std::min(readOffset + MAX_READ_SIZE, size); + int readSize = (int)((readLimit - readOffset)); + int fullChunkSize = (int)(GetFullChunkSize(readSize, CHUNK_SIZE, CHUNK_SIZE)); + ByteBuffer* byteBuffer(new ByteBuffer(fullChunkSize)); + std::vector buffer(CHUNK_SIZE); + int num = 0; + int offset = 0; + int flag = 0; + int len = CHUNK_SIZE; + while (num > 0 || flag == 0) { + inputStream.read((buffer.data()), len); + if (inputStream.fail() && !inputStream.eof()) { + PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "Error occurred while reading data"); + CheckCalculateHashResult = false; + return std::vector>(); + } + num = inputStream.gcount(); + byteBuffer->PutData(buffer.data(), num); + offset += num; + len = std::min(CHUNK_SIZE, readSize - offset); + if (len <= 0 || offset == readSize) { + break; + } + flag = 1; + } + if (offset != readSize) { + PrintErrorNumberMsg("READ_FILE_ERROR", IO_ERROR, "Error reading buffer from input"); + CheckCalculateHashResult = false; + return std::vector>(); + } + byteBuffer->Flip(); + int readChunkIndex = (int)(GetFullChunkSize(MAX_READ_SIZE, CHUNK_SIZE, i)); + thread_results.push_back(mPools->Enqueue(&MerkleTreeBuilder::RunHashTask, this, std::ref(hashes), + byteBuffer, readChunkIndex, 0)); + readOffset += readSize; + } + for (auto& thread_result : thread_results) { + thread_result.wait(); + } + return hashes; +} + +ByteBuffer* MerkleTreeBuilder::Slice(ByteBuffer* buffer, int begin, int end) +{ + ByteBuffer* tmpBuffer = buffer->Duplicate(); + tmpBuffer->SetPosition(0); + tmpBuffer->SetLimit(end); + tmpBuffer->SetPosition(begin); + return &tmpBuffer->slice_for_codesigning(); +} + +std::vector MerkleTreeBuilder::GetOffsetArrays(long dataSize, int digestSize) +{ + std::vector levelSize = GetLevelSize(dataSize, digestSize); + std::vector levelOffset(levelSize.size() + 1); + levelOffset[0] = 0; + for (long i = 0; i < levelSize.size(); i++) { + levelOffset[i + 1] = levelOffset[i] + levelSize[levelSize.size() - i - 1]; + } + return levelOffset; +} + +std::vector MerkleTreeBuilder::GetLevelSize(long dataSize, int digestSize) +{ + std::vector levelSize; + + long fullChunkSize = 0L; + long originalDataSize = dataSize; + do { + fullChunkSize = GetFullChunkSize(originalDataSize, CHUNK_SIZE, digestSize); + int size = GetFullChunkSize(fullChunkSize, CHUNK_SIZE, CHUNK_SIZE); + levelSize.push_back(size); + originalDataSize = fullChunkSize; + } while (fullChunkSize > CHUNK_SIZE); + return levelSize; +} + +void MerkleTreeBuilder::RunHashTask(std::vector>& hashes, + ByteBuffer* buffer, int readChunkIndex, int bufStartIdx) +{ + int offset = 0; + + std::shared_ptr bufferPtr(buffer); + int bufferSize = bufferPtr->GetCapacity(); + int index = readChunkIndex; + while (offset < bufferSize) { + ByteBuffer* chunk = Slice(bufferPtr.get(), offset, offset + CHUNK_SIZE); + std::vector tmpByte(CHUNK_SIZE); + chunk->GetData(offset + bufStartIdx, tmpByte.data(), CHUNK_SIZE); + bool isCsSection = (csOffset != 0 && csOffset / 4096 == index); + if (isCsSection) { + SIGNATURE_TOOLS_LOGI("CsSection index = %d", index); + } + DigestUtils digestUtils(HASH_SHA256); + std::string tmpByteStr(tmpByte.begin(), tmpByte.end()); + digestUtils.AddData(tmpByteStr); + std::string result = digestUtils.Result(DigestUtils::Type::BINARY); + std::vector hashEle; + for (long i = 0; i < result.size(); i++) { + if (isCsSection) { + hashEle.push_back(0); + } else { + hashEle.push_back(result[i]); + } + } + hashes[index++] = hashEle; + offset += CHUNK_SIZE; + delete chunk; + } +} + +void MerkleTreeBuilder::TransInputDataToHashData(ByteBuffer* inputBuffer, ByteBuffer* outputBuffer, + int64_t inputStartIdx, int64_t outputStartIdx) +{ + long size = inputBuffer->GetCapacity(); + int chunks = (int)GetChunkCount(size, CHUNK_SIZE); + std::vector> hashes(chunks); + long readOffset = 0L; + int startChunkIndex = 0; + while (readOffset < size) { + long readLimit = std::min(readOffset + MAX_READ_SIZE, size); + ByteBuffer* buffer = Slice(inputBuffer, (int)readOffset, (int)readLimit); + buffer->SetPosition(0); + int readChunkIndex = startChunkIndex; + RunHashTask(hashes, buffer, readChunkIndex, inputStartIdx); + int readSize = (int)(readLimit - readOffset); + startChunkIndex += (int)GetChunkCount(readSize, CHUNK_SIZE); + readOffset += readSize; + inputStartIdx += readSize; + } + int32_t writeSize = 0; + for (const auto& hash : hashes) { + outputBuffer->PutData(writeSize + outputStartIdx, hash.data(), hash.size()); + writeSize += hash.size(); + } +} + +OHOS::SignatureTools::MerkleTreeBuilder::MerkleTreeBuilder() :mPools(new Uscript::ThreadPool(POOL_SIZE)) +{ + CheckCalculateHashResult = true; +} + +MerkleTree* MerkleTreeBuilder::GenerateMerkleTree(std::istream& inputStream, long size, + const FsVerityHashAlgorithm& fsVerityHashAlgorithm) +{ + SetAlgorithm(fsVerityHashAlgorithm.GetHashAlgorithm()); + int digestSize = fsVerityHashAlgorithm.GetOutputByteSize(); + std::vector offsetArrays = GetOffsetArrays(size, digestSize); + std::unique_ptr allHashBuffer = std::make_unique + (ByteBuffer(offsetArrays[offsetArrays.size() - 1])); + GenerateHashDataByInputData(inputStream, size, allHashBuffer.get(), offsetArrays, digestSize); + GenerateHashDataByHashData(allHashBuffer.get(), offsetArrays, digestSize); + + if (CheckCalculateHashResult) { + return GetMerkleTree(allHashBuffer.get(), size, fsVerityHashAlgorithm); + } + return nullptr; +} + +void MerkleTreeBuilder::GenerateHashDataByInputData(std::istream& inputStream, long size, ByteBuffer* outputBuffer, + std::vector& offsetArrays, int digestSize) +{ + int64_t inputDataOffsetBegin = offsetArrays[offsetArrays.size() - 2]; + int64_t inputDataOffsetEnd = offsetArrays[offsetArrays.size() - 1]; + ByteBuffer* hashBuffer = Slice(outputBuffer, 0, inputDataOffsetEnd); + TransInputStreamToHashData(inputStream, size, hashBuffer, inputDataOffsetBegin); + DataRoundupChunkSize(hashBuffer, size, digestSize); + delete hashBuffer; +} + +void MerkleTreeBuilder::GenerateHashDataByHashData(ByteBuffer* buffer, + std::vector& offsetArrays, int digestSize) +{ + for (int i = offsetArrays.size() - 3; i >= 0; i--) { + int64_t generateOffset = offsetArrays[i]; + int64_t originalOffset = offsetArrays[i + 1]; + ByteBuffer* generateHashBuffer = Slice(buffer, offsetArrays[i], offsetArrays[i + 1] + offsetArrays[i]); + ByteBuffer* readOnlyBuffer = buffer->Duplicate(); + ByteBuffer* originalHashBuffer = Slice(readOnlyBuffer, offsetArrays[i + 1], offsetArrays[i + 2]); + TransInputDataToHashData(originalHashBuffer, generateHashBuffer, originalOffset, generateOffset); + DataRoundupChunkSize(generateHashBuffer, originalHashBuffer->GetCapacity(), digestSize); + delete originalHashBuffer; + delete readOnlyBuffer; + delete generateHashBuffer; + } +} + +MerkleTree* MerkleTreeBuilder::GetMerkleTree(ByteBuffer* dataBuffer, long inputDataSize, + FsVerityHashAlgorithm fsVerityHashAlgorithm) +{ + int digestSize = fsVerityHashAlgorithm.GetOutputByteSize(); + dataBuffer->Flip(); + std::vector rootHash; + std::vector tree; + if (inputDataSize <= FSVERITY_HASH_PAGE_SIZE) { + ByteBuffer* fsVerityHashPageBuffer = Slice(dataBuffer, 0, digestSize); + if (fsVerityHashPageBuffer != nullptr) { + rootHash = std::vector(digestSize); + fsVerityHashPageBuffer->GetByte(rootHash.data(), digestSize); + delete fsVerityHashPageBuffer; + fsVerityHashPageBuffer = nullptr; + } + } else { + tree = std::vector(dataBuffer->GetBufferPtr(), dataBuffer->GetBufferPtr() + dataBuffer->GetCapacity()); + ByteBuffer* fsVerityHashPageBuffer = Slice(dataBuffer, 0, FSVERITY_HASH_PAGE_SIZE); + if (fsVerityHashPageBuffer != nullptr) { + std::vector fsVerityHashPage(FSVERITY_HASH_PAGE_SIZE); + fsVerityHashPageBuffer->GetData(0, fsVerityHashPage.data(), FSVERITY_HASH_PAGE_SIZE); + DigestUtils digestUtils(HASH_SHA256); + std::string fsVerityHashPageStr(fsVerityHashPage.begin(), fsVerityHashPage.end()); + digestUtils.AddData(fsVerityHashPageStr); + std::string result = digestUtils.Result(DigestUtils::Type::BINARY); + for (int i = 0; i < static_cast(result.size()); i++) { + rootHash.push_back(result[i]); + } + delete fsVerityHashPageBuffer; + fsVerityHashPageBuffer = nullptr; + } + } + + return new MerkleTree(rootHash, tree, fsVerityHashAlgorithm); +} + +void MerkleTreeBuilder::DataRoundupChunkSize(ByteBuffer* data, long originalDataSize, int digestSize) +{ + long fullChunkSize = GetFullChunkSize(originalDataSize, CHUNK_SIZE, digestSize); + int diffValue = (int)(fullChunkSize % CHUNK_SIZE); + if (diffValue > 0) { + data->SetPosition(data->GetPosition() + (CHUNK_SIZE - diffValue)); + } +} + +long MerkleTreeBuilder::GetChunkCount(long dataSize, long divisor) +{ + return (long)std::ceil((double)dataSize / (double)divisor); +} + +long MerkleTreeBuilder::GetFullChunkSize(long dataSize, long divisor, long multiplier) +{ + return GetChunkCount(dataSize, divisor) * multiplier; +} +} // namespace SignatureTools +} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/cmd/include/params_trust_list.h b/binary_sign_tool/codesigning/sign/include/code_signing.h similarity index 48% rename from binary_sign_tool/cmd/include/params_trust_list.h rename to binary_sign_tool/codesigning/sign/include/code_signing.h index f06416da1644eb969c4f7720f32d8d0b2190a74e..3543c5730f4822207fb6e5616f2a6a648371c870 100644 --- a/binary_sign_tool/cmd/include/params_trust_list.h +++ b/binary_sign_tool/codesigning/sign/include/code_signing.h @@ -12,30 +12,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef SIGNATURETOOLS_CODE_SIGNING_H +#define SIGNATURETOOLS_CODE_SIGNING_H -#ifndef SIGNATRUETOOLS_PARAMSTRUSTLIST_H -#define SIGNATRUETOOLS_PARAMSTRUSTLIST_H - -#include #include -#include +#include #include -#include + +#include "securec.h" +#include "thread_pool.h" +#include "file_utils.h" +#include "local_signer.h" +#include "signer_config.h" #include "signature_tools_log.h" +#include "fs_verity_generator.h" +#include "bc_signeddata_generator.h" namespace OHOS { namespace SignatureTools { -class ParamsTrustList final { +class CodeSigning { public: - static ParamsTrustList GetInstance(); - std::vector GetTrustList(const std::string& command); -private: - void ReadHelpParam(std::istringstream& fd); - void PutTrustMap(const std::string& cmd_stand_by, const std::string& param); - void GenerateTrustList(); + CodeSigning(SignerConfig* signConfig, bool adHoc); + CodeSigning(); + + bool GetElfCodeSignBlock(const std::string &input, uint64_t& csOffset, std::vector &codesignData); + +public: + bool GenerateSignature(const std::vector& signedData, const std::string& ownerID, + std::vector& ret); + bool GetOwnerIdFromCert(std::string& ownerID); + SignerConfig* m_signConfig; + bool m_adHoc; + private: - std::unordered_map> trustMap; + static constexpr int MIN_CERT_CHAIN_SIZE = 2; + static constexpr int MAX_CERT_CHAIN_SIZE = 3; }; } // namespace SignatureTools } // namespace OHOS -#endif +#endif // SIGNATURETOOLS_CODE_SIGNING_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/sign/src/code_signing.cpp b/binary_sign_tool/codesigning/sign/src/code_signing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2662db7fa3d5a0f04de41fa7e4e15a69a1de586f --- /dev/null +++ b/binary_sign_tool/codesigning/sign/src/code_signing.cpp @@ -0,0 +1,144 @@ +/* + * 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. + */ + +#include + +#include "fs_verity_descriptor.h" +#include "fs_verity_descriptor_with_sign.h" +#include "code_signing.h" + +namespace OHOS { +namespace SignatureTools { + +const FsVerityHashAlgorithm FS_SHA256(1, "SHA-256", 256 / 8); +const FsVerityHashAlgorithm FS_SHA512(2, "SHA-512", 512 / 8); +const int8_t LOG_2_OF_FSVERITY_HASH_PAGE_SIZE = 12; +const int FLAG_AD_HOC = 1 << 4; +const uint8_t ELF_CODE_SIGN_VERSION = 0x3; + +CodeSigning::CodeSigning(SignerConfig* signConfig, bool adHoc) +{ + m_signConfig = signConfig; + m_adHoc = adHoc; +} + +CodeSigning::CodeSigning() +{ +} + +bool CodeSigning::GetElfCodeSignBlock(const std::string &input, uint64_t& csOffset, std::vector& codesignData) +{ + SIGNATURE_TOOLS_LOGI("Start to sign elf code."); + std::ifstream inputstream(input, std::ios::binary | std::ios::ate); + if (!inputstream.is_open()) { + PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open file: " + input + "failed"); + return false; + } + int flags = 0; + if (m_adHoc) { + flags = flags | FLAG_AD_HOC; + } + std::streamsize fileSize = inputstream.tellg(); + inputstream.seekg(0, std::ios::beg); + std::unique_ptr fsVerityGenerator = std::make_unique(); + fsVerityGenerator->SetCsOffset(csOffset); + fsVerityGenerator->GenerateFsVerityDigest(inputstream, fileSize, flags); + std::vector signature; + + if (!m_adHoc) { + std::string ownerID; + GetOwnerIdFromCert(ownerID); + std::vector fsVerityDigest = fsVerityGenerator->GetFsVerityDigest(); + bool generateSignatureFlag = GenerateSignature(fsVerityDigest, ownerID, signature); + if (!generateSignatureFlag) { + SIGNATURE_TOOLS_LOGE("[SignElf] generate elf signature failed"); + return false; + } + } else { + signature = fsVerityGenerator->GetDescriptorDigest(); + } + + FsVerityDescriptor::Builder fsdbuilder; + fsdbuilder.SetFileSize(fileSize) + .SetHashAlgorithm(FS_SHA256.GetId()) + .SetLog2BlockSize(LOG_2_OF_FSVERITY_HASH_PAGE_SIZE) + .SetSaltSize(fsVerityGenerator->GetSaltSize()) + .SetSignSize(signature.size()) + .SetSalt(fsVerityGenerator->GetSalt()) + .SetRawRootHash(fsVerityGenerator->GetRootHash()) + .SetFlags(flags) + .SetCsVersion(ELF_CODE_SIGN_VERSION); + + FsVerityDescriptorWithSign fsVerityDescriptorWithSign = + FsVerityDescriptorWithSign(FsVerityDescriptor(fsdbuilder), signature); + std::vector treeBytes = fsVerityGenerator->GetTreeBytes(); + fsVerityDescriptorWithSign.ToByteArray(codesignData); + return true; +} + +bool CodeSigning::GenerateSignature(const std::vector& signedData, const std::string& ownerID, + std::vector& ret) +{ + if (m_signConfig->GetSigner() != nullptr) { + STACK_OF(X509)* certs = NULL; + certs = m_signConfig->GetSigner()->GetCertificates(); + if (certs == nullptr) { + PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "No certificates configured for sign."); + return false; + } + sk_X509_pop_free(certs, X509_free); + } else { + return false; + } + std::unique_ptr bcSignedDataGenerator = + std::make_unique(); + if (!ownerID.empty()) { + SIGNATURE_TOOLS_LOGW("generate signature get owner id not null."); + bcSignedDataGenerator->SetOwnerId(ownerID); + } + std::string signed_data(signedData.begin(), signedData.end()); + std::string ret_str; + if (signedData.empty()) { + PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Generate verity digest is null"); + return false; + } + bool generateSignedDataFlag = bcSignedDataGenerator->GenerateSignedData(signed_data, m_signConfig, ret_str); + if (generateSignedDataFlag) { + SIGNATURE_TOOLS_LOGE("Generate signedData failed"); + return false; + } + ret = std::vector(ret_str.begin(), ret_str.end()); + return true; +} + +bool CodeSigning::GetOwnerIdFromCert(std::string& ownerID) +{ + if (m_signConfig == nullptr) { + ownerID = ""; + return true; + } + STACK_OF(X509)* certs = m_signConfig->GetSigner()->GetCertificates(); + if (sk_X509_num(certs) < MIN_CERT_CHAIN_SIZE) { + SIGNATURE_TOOLS_LOGE("sign certs not a cert chain"); + return false; + } + X509* cert = sk_X509_value(certs, 0); + X509_NAME* subject = X509_get_subject_name(cert); + VerifyCertOpensslUtils::GetTextFromX509Name(subject, NID_organizationalUnitName, ownerID); + SIGNATURE_TOOLS_LOGI("organizationalUnitName = %s.", ownerID.c_str()); + return true; +} +} // namespace SignatureTools +} // namespace OHOS diff --git a/binary_sign_tool/codesigning/signature_tools_codesigning.gni b/binary_sign_tool/codesigning/signature_tools_codesigning.gni new file mode 100644 index 0000000000000000000000000000000000000000..7fd882afda516b673c4140098092d8307bfb94f4 --- /dev/null +++ b/binary_sign_tool/codesigning/signature_tools_codesigning.gni @@ -0,0 +1,35 @@ +# 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. + +import("../signature_tools.gni") +signature_tools_codesigning_include = [ + "${signature_tools_codesigning}/fsverity/include", + #"${signature_tools_codesigning}/utils/include", + "${signature_tools_codesigning}/sign/include", + "${hapsigntool_cpp_codesigning}/sign/include", + "${hapsigntool_cpp_codesigning}/utils/include", + "${hapsigntool_cpp_codesigning}/fsverity/include", +] + +signature_tools_codesigning_src = [ + "${signature_tools_codesigning}/fsverity/src/fs_verity_descriptor.cpp", + "${hapsigntool_cpp_codesigning}/fsverity/src/fs_verity_digest.cpp", + "${signature_tools_codesigning}/fsverity/src/fs_verity_generator.cpp", + "${hapsigntool_cpp_codesigning}/fsverity/src/fs_verity_hash_algorithm.cpp", + "${signature_tools_codesigning}/fsverity/src/merkle_tree_builder.cpp", + "${hapsigntool_cpp_codesigning}/fsverity/src/fs_verity_descriptor_with_sign.cpp", + "${hapsigntool_cpp_codesigning}/utils/src/fs_digest_utils.cpp", + "${hapsigntool_cpp_codesigning}/utils/src/cms_utils.cpp", + "${hapsigntool_cpp_codesigning}/sign/src/bc_signeddata_generator.cpp", + "${signature_tools_codesigning}/sign/src/code_signing.cpp", +] diff --git a/binary_sign_tool/common/include/localization_adapter.h b/binary_sign_tool/common/include/localization_adapter.h deleted file mode 100644 index 980e726affda54cef8b10db560d97c84abe7788b..0000000000000000000000000000000000000000 --- a/binary_sign_tool/common/include/localization_adapter.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 SIGNATRUETOOLS_LOCALIIZATION_ADAPTER_H -#define SIGNATRUETOOLS_LOCALIIZATION_ADAPTER_H - -#include -#include - -#include "openssl/ssl.h" -#include "openssl/pem.h" -#include "openssl/err.h" -#include "options.h" -#include "key_store_helper.h" -#include "signature_tools_log.h" -#include "digest_common.h" -namespace OHOS { -namespace SignatureTools { -class LocalizationAdapter { -public: - LocalizationAdapter() = default; - LocalizationAdapter(Options* options); - ~LocalizationAdapter() = default; - - int IsAliasExist(const std::string& alias); - int GetKeyPair(bool autoCreate, EVP_PKEY** keyPair); - int IssuerKeyStoreFile(EVP_PKEY** keyPair, bool autoCreate); - int KeyStoreFile(EVP_PKEY** keyPair, bool autoCreate); - - void ResetPwd(); - void SetIssuerKeyStoreFile(bool issuerKeyStoreFile); - void AppAndProfileAssetsRealse(std::initializer_list keys, - std::initializer_list reqs, - std::initializer_list certs); - - bool IsOutFormChain(); - bool IsRemoteSigner(); - - const std::string GetSignAlg() const; - const std::string GetOutFile(); - const std::string GetInFile(); - - Options* GetOptions(); - EVP_PKEY* GetAliasKey(bool autoCreate); - EVP_PKEY* GetIssuerKeyByAlias(); - X509* GetSubCaCertFile(); - X509* GetCaCertFile(); - STACK_OF(X509*) GetSignCertChain(); - std::vector GetCertsFromFile(std::string& certPath, const std::string& logTitle); - -private: - void ResetChars(char* chars); - -public: - Options* options; - std::unique_ptr keyStoreHelper; - -private: - static constexpr int MIN_CERT_CHAIN_SIZE = 2; - static constexpr int MAX_CERT_CHAIN_SIZE = 3; - bool isIssuerKeyStoreFile; -}; -} // namespace SignatureTools -} // namespace OHOS -#endif // SIGNATRUETOOLS_LOCALIIZATION_ADAPTER_H diff --git a/binary_sign_tool/hap/config/include/signer_config.h b/binary_sign_tool/hap/config/include/signer_config.h deleted file mode 100644 index df939ae577dc5ec52659efb2f2b184a1a9300e17..0000000000000000000000000000000000000000 --- a/binary_sign_tool/hap/config/include/signer_config.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 SIGNATRUETOOLS_SIGNER_CONFIG_H -#define SIGNATRUETOOLS_SIGNER_CONFIG_H -#include -#include -#include -#include - -#include "options.h" -#include "openssl/x509.h" -#include "signature_algorithm_helper.h" -#include "signer.h" - -namespace OHOS { -namespace SignatureTools { -class SignerConfig { -public: - SignerConfig(); - ~SignerConfig(); - Options* GetOptions() const; - void SetOptions(Options* optionsParam); - STACK_OF(X509)* GetCertificates() const; - void SetCertificates(STACK_OF(X509)* certificatesParam); - STACK_OF(X509_CRL)* GetX509CRLs() const; - void SetX509CRLs(STACK_OF(X509_CRL)* crls); - std::vector GetSignatureAlgorithms() const; - void SetSignatureAlgorithms(const std::vector& signatureAlgorithmsParam); - const std::map& GetSignParamMap() const; - void FillParameters(const std::map& params); - std::shared_ptr GetSigner(); - int GetCompatibleVersion() const; - void SetCompatibleVersion(int compatibleVersionParam); - -private: - bool IsInputCertChainNotEmpty() const; - bool IsInputCrlNotEmpty() const; - Options* options; - STACK_OF(X509)* certificates; - STACK_OF(X509_CRL)* x509CRLs; - std::vector signatureAlgorithms; - std::map signParamMap; - std::shared_ptr signer; - int compatibleVersion; -}; -} // namespace SignatureTools -} // namespace OHOS -#endif // SIGNATRUETOOLS_SIGNER_CONFIG_H diff --git a/binary_sign_tool/hap/config/src/signer_config.cpp b/binary_sign_tool/hap/config/src/signer_config.cpp deleted file mode 100644 index 382e94b224a0c7f92cb0a60c7cc388e3d3b0b727..0000000000000000000000000000000000000000 --- a/binary_sign_tool/hap/config/src/signer_config.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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. - */ -#include -#include - -#include "signer_factory.h" -#include "localization_adapter.h" -#include "signer_config.h" - -namespace OHOS { -namespace SignatureTools { -SignerConfig::SignerConfig() : options(nullptr), - certificates(nullptr), - x509CRLs(nullptr), - signer(nullptr), - compatibleVersion(0) -{ -} - -SignerConfig::~SignerConfig() -{ - if (certificates) { - sk_X509_pop_free(certificates, X509_free); - } - certificates = NULL; - - if (x509CRLs) { - sk_X509_CRL_pop_free(x509CRLs, X509_CRL_free); - } - x509CRLs = NULL; -} - -Options* SignerConfig::GetOptions() const -{ - return options; -} - -void SignerConfig::SetOptions(Options* optionsParam) -{ - options = optionsParam; -} - -STACK_OF(X509)* SignerConfig::GetCertificates() const -{ - if (IsInputCertChainNotEmpty() || signer == nullptr) { - return certificates; - } - return signer->GetCertificates(); -} - -void SignerConfig::SetCertificates(STACK_OF(X509)* certificatesParam) -{ - certificates = certificatesParam; -} - -STACK_OF(X509_CRL)* SignerConfig::GetX509CRLs() const -{ - if (IsInputCertChainNotEmpty() || IsInputCrlNotEmpty() || signer == nullptr) { - return x509CRLs; - } - return signer->GetCrls(); -} - -void SignerConfig::SetX509CRLs(STACK_OF(X509_CRL)* crls) -{ - x509CRLs = crls; -} - -std::vector SignerConfig::GetSignatureAlgorithms() const -{ - return signatureAlgorithms; -} - -void SignerConfig::SetSignatureAlgorithms(const std::vector& signatureAlgorithmsParam) -{ - signatureAlgorithms = signatureAlgorithmsParam; -} - -const std::map& SignerConfig::GetSignParamMap() const -{ - return signParamMap; -} - -void SignerConfig::FillParameters(const std::map& params) -{ - signParamMap = params; -} - -std::shared_ptr SignerConfig::GetSigner() -{ - if (signer == nullptr) { - SignerFactory factory; - LocalizationAdapter adapter(options); - signer = factory.GetSigner(adapter); - } - return signer; -} - -int SignerConfig::GetCompatibleVersion() const -{ - return compatibleVersion; -} - -void SignerConfig::SetCompatibleVersion(int compatibleVersionParam) -{ - compatibleVersion = compatibleVersionParam; -} - -bool SignerConfig::IsInputCertChainNotEmpty() const -{ - return certificates != nullptr; -} - -bool SignerConfig::IsInputCrlNotEmpty() const -{ - return x509CRLs != nullptr; -} -} // namespace SignatureTools -} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/hap/entity/src/content_digest_algorithm.cpp b/binary_sign_tool/hap/entity/src/content_digest_algorithm.cpp deleted file mode 100644 index 2a70b365586f35b8598322b87622d930018fb6a6..0000000000000000000000000000000000000000 --- a/binary_sign_tool/hap/entity/src/content_digest_algorithm.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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. - */ -#include "content_digest_algorithm.h" -namespace OHOS { -namespace SignatureTools { -const ContentDigestAlgorithm ContentDigestAlgorithm::SHA256("SHA-256", 256 / 8); -const ContentDigestAlgorithm ContentDigestAlgorithm::SHA384("SHA-384", 384 / 8); -const ContentDigestAlgorithm ContentDigestAlgorithm::SHA512("SHA-512", 512 / 8); - -ContentDigestAlgorithm::ContentDigestAlgorithm() - : m_digestAlgorithm(""), - m_digestOutputByteSize(0) -{ -} - -ContentDigestAlgorithm::ContentDigestAlgorithm(const std::string& digestAlgorithm, - const int digestOutputByteSize) - : m_digestAlgorithm(digestAlgorithm), m_digestOutputByteSize(digestOutputByteSize) -{ -} - -ContentDigestAlgorithm::ContentDigestAlgorithm(const ContentDigestAlgorithm& other) - : m_digestAlgorithm(other.m_digestAlgorithm), - m_digestOutputByteSize(other.m_digestOutputByteSize) -{ -} - -ContentDigestAlgorithm& ContentDigestAlgorithm::operator=(const ContentDigestAlgorithm& other) -{ - if (this != &other) { - m_digestAlgorithm = other.m_digestAlgorithm; - m_digestOutputByteSize = other.m_digestOutputByteSize; - } - return *this; -} - -std::string ContentDigestAlgorithm::GetDigestAlgorithm() -{ - return m_digestAlgorithm; -} - -int ContentDigestAlgorithm::GetDigestOutputByteSize() -{ - return m_digestOutputByteSize; -} -} // namespace SignatureTools -} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/hap/entity/src/signature_algorithm_helper.cpp b/binary_sign_tool/hap/entity/src/signature_algorithm_helper.cpp deleted file mode 100644 index 62f9abe78401e010992e7851318f7de8ed9dc6da..0000000000000000000000000000000000000000 --- a/binary_sign_tool/hap/entity/src/signature_algorithm_helper.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ -#include "signature_algorithm_helper.h" - -namespace OHOS { -namespace SignatureTools { -const SignatureAlgorithmHelper SignatureAlgorithmHelper::ECDSA_WITH_SHA256_INSTANCE{ - SignatureAlgorithmId::ECDSA_WITH_SHA256, "EC", ContentDigestAlgorithm::SHA256, - {"SHA256withECDSA", nullptr} }; - -const SignatureAlgorithmHelper SignatureAlgorithmHelper::ECDSA_WITH_SHA384_INSTANCE{ - SignatureAlgorithmId::ECDSA_WITH_SHA384, "EC", ContentDigestAlgorithm::SHA384, - {"SHA384withECDSA", nullptr} }; - -SignatureAlgorithmHelper::SignatureAlgorithmHelper() : m_id(SignatureAlgorithmId::ECDSA_WITH_SHA256), - m_keyAlgorithm(""), - m_contentDigestAlgorithm(ContentDigestAlgorithm::SHA256), - m_signatureAlgAndParams("", nullptr) -{ -} - -SignatureAlgorithmHelper::SignatureAlgorithmHelper(const SignatureAlgorithmHelper& other) : m_id(other.m_id), - m_keyAlgorithm(other.m_keyAlgorithm), - m_contentDigestAlgorithm(other.m_contentDigestAlgorithm), - m_signatureAlgAndParams(other.m_signatureAlgAndParams.first, nullptr) -{ -} - -SignatureAlgorithmHelper::SignatureAlgorithmHelper(const SignatureAlgorithmId& id_, const std::string& keyAlg_, - const ContentDigestAlgorithm& digestAlg_, - const std::pair& sigParams_) - : m_id(id_), m_keyAlgorithm(keyAlg_), m_contentDigestAlgorithm(digestAlg_), m_signatureAlgAndParams(sigParams_) -{ -} - -SignatureAlgorithmHelper& SignatureAlgorithmHelper::operator=(const SignatureAlgorithmHelper& other) -{ - if (this != &other) { - m_id = other.m_id; - m_keyAlgorithm = other.m_keyAlgorithm; - m_contentDigestAlgorithm = other.m_contentDigestAlgorithm; - m_signatureAlgAndParams.first = other.m_signatureAlgAndParams.first; - m_signatureAlgAndParams.second = other.m_signatureAlgAndParams.second; - } - return *this; -} - -SignatureAlgorithmHelper::~SignatureAlgorithmHelper() -{ -} - -const SignatureAlgorithmHelper* SignatureAlgorithmHelper::FindById(const SignatureAlgorithmId id) -{ - if (id == SignatureAlgorithmId::ECDSA_WITH_SHA256) return &ECDSA_WITH_SHA256_INSTANCE; - if (id == SignatureAlgorithmId::ECDSA_WITH_SHA384) return &ECDSA_WITH_SHA384_INSTANCE; - return nullptr; -} -} // namespace SignatureTools -} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/hap/utils/src/dynamic_lib_handle.cpp b/binary_sign_tool/hap/provider/include/ad_hoc_sign_provider.h similarity index 66% rename from binary_sign_tool/hap/utils/src/dynamic_lib_handle.cpp rename to binary_sign_tool/hap/provider/include/ad_hoc_sign_provider.h index 5088eeafbbaf7ef519aa142c9030c5ed9639f775..03b6c1ca025d1492216941e6c47f60f1dd1f4a68 100644 --- a/binary_sign_tool/hap/utils/src/dynamic_lib_handle.cpp +++ b/binary_sign_tool/hap/provider/include/ad_hoc_sign_provider.h @@ -12,19 +12,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef SIGNATRUETOOLS_AD_HOC_SIGN_PROVIDER_H +#define SIGNATRUETOOLS_AD_HOC_SIGN_PROVIDER_H -#include "dynamic_lib_handle.h" +#include "sign_provider.h" namespace OHOS { namespace SignatureTools { -void* DynamicLibHandle::handle = nullptr; -DynamicLibHandle::~DynamicLibHandle() -{ - if (handle != nullptr) { - if (dlclose(handle) != 0) { - SIGNATURE_TOOLS_LOGE("dlclose() %s", dlerror()); - } - } -} +class AdHocSignProvider : public SignProvider { +public: + AdHocSignProvider() = default; + ~AdHocSignProvider() = default; + bool SignElf(Options* options); +}; } // namespace SignatureTools -} // namespace OHOS \ No newline at end of file +} // namespace OHOS +#endif // SIGNATRUETOOLS_AD_HOC_SIGN_PROVIDER_H \ No newline at end of file diff --git a/binary_sign_tool/hap/provider/include/sign_provider.h b/binary_sign_tool/hap/provider/include/sign_provider.h index 3f3e08b27bb577e83837ec05588145cd8832e738..7a3a76b80abb970a369ee86a9d332f86b1846269 100644 --- a/binary_sign_tool/hap/provider/include/sign_provider.h +++ b/binary_sign_tool/hap/provider/include/sign_provider.h @@ -35,10 +35,8 @@ #include "signer_config.h" #include "param_constants.h" #include "byte_buffer.h" -#include "hap_utils.h" #include "pkcs7_data.h" #include "profile_verify.h" -#include "signature_info.h" typedef std::tuple, std::shared_ptr, std::string> fileIOTuple; namespace OHOS { @@ -47,8 +45,7 @@ class SignProvider { public: SignProvider() = default; virtual ~SignProvider() = default; - bool Sign(Options* options); - bool SignElf(Options* options); + virtual bool SignElf(Options* options); bool SetSignParams(Options* options, std::unordered_set& paramSet); virtual std::optional GetCrl(); virtual bool CheckParams(Options* options); @@ -58,23 +55,15 @@ protected: void CheckSignAlignment(); X509* GetCertificate(const std::string& certificate)const; std::string GetCertificateCN(X509* cert)const; - std::string FindProfileFromOptionalBlocks()const; - int CheckProfileValid(STACK_OF(X509)* inputCerts); + int CheckProfileValid(STACK_OF(X509)* inputCerts, const std::string& file); int CheckProfileInfo(const ProfileInfo& info, STACK_OF(X509)* inputCerts)const; - int LoadOptionalBlocks(); - std::vector optionalBlocks; std::map signParams = std::map(); private: bool InitSigerConfig(SignerConfig& signerConfig, STACK_OF(X509)* publicCerts, Options* options); - bool CreateSignerConfigs(STACK_OF(X509)* certificates, const std::optional& crl, Options* options, SignerConfig&); - bool CheckSignatureAlg(); - int LoadOptionalBlock(const std::string& file, int type); - bool CheckFile(const std::string& filePath); - int GetX509Certificates(Options* options, STACK_OF(X509)** ret); int GetPublicCerts(Options* options, STACK_OF(X509)** ret); int GetCertificateChainFromFile(const std::string& certChianFile, STACK_OF(X509)** ret); @@ -82,7 +71,6 @@ private: private: static std::vector VALID_SIGN_ALG_NAME; - static constexpr int FOUR_BYTE = 4; std::string profileContent; }; } // namespace SignatureTools diff --git a/binary_sign_tool/hap/verify/include/matching_result.h b/binary_sign_tool/hap/provider/src/ad_hoc_sign_provider.cpp similarity index 58% rename from binary_sign_tool/hap/verify/include/matching_result.h rename to binary_sign_tool/hap/provider/src/ad_hoc_sign_provider.cpp index 8bfbc19671ffe925c918498340a0e51945eb45fd..918b53713ebafcfd003069166d57b5ce5d4b7d32 100644 --- a/binary_sign_tool/hap/verify/include/matching_result.h +++ b/binary_sign_tool/hap/provider/src/ad_hoc_sign_provider.cpp @@ -12,27 +12,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef SIGNATRUETOOLS_MATCHING_RESULT_H -#define SIGNATRUETOOLS_MATCHING_RESULT_H +#include "ad_hoc_sign_provider.h" +#include "params.h" +#include "sign_elf.h" + namespace OHOS { namespace SignatureTools { -enum SourcesTrusted { - OTHER_TRUSTED_SOURCE = 0, - APP_GALLARY, - APP_SYSTEM, - APP_THIRD_PARTY_PRELOAD, -}; -enum StatesMatching { - DO_NOT_MATCH = 0, - MATCH_WITH_SIGN, - MATCH_WITH_PROFILE, - MATCH_WITH_PROFILE_DEBUG, - MATCH_WITH_TICKET, -}; -struct MatchingResult { - StatesMatching matchState; - SourcesTrusted source; -}; +bool AdHocSignProvider::SignElf(Options* options) +{ + if (!SignProvider::CheckParams(options)) { + SIGNATURE_TOOLS_LOGE("Parameter check failed !"); + return false; + } + SignerConfig signerConfig; + if (!SignElf::Sign(signerConfig, signParams)) { + SIGNATURE_TOOLS_LOGE("[SignElf] sign elf failed"); + return false; + } + return true; +} } // namespace SignatureTools -} // namespace OHOS -#endif // HAP_MATCHING_RESULT_H +} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/hap/provider/src/remote_sign_provider.cpp b/binary_sign_tool/hap/provider/src/remote_sign_provider.cpp deleted file mode 100644 index 640c5d266c5b9009824ad4951e8679b426399eb6..0000000000000000000000000000000000000000 --- a/binary_sign_tool/hap/provider/src/remote_sign_provider.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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. - */ -#include "remote_sign_provider.h" - -namespace OHOS { -namespace SignatureTools { -bool RemoteSignProvider::CheckParams(Options* options) -{ - if (!SignProvider::CheckParams(options)) { - SIGNATURE_TOOLS_LOGE("SignProvider::Parameter check failed !"); - return false; - } - // The following code is for reference only. - std::vector paramFileds; - paramFileds.emplace_back(ParamConstants::PARAM_REMOTE_SERVER); - paramFileds.emplace_back(ParamConstants::PARAM_REMOTE_USERNAME); - paramFileds.emplace_back(ParamConstants::PARAM_REMOTE_USERPWD); - paramFileds.emplace_back(ParamConstants::PARAM_REMOTE_ONLINEAUTHMODE); - paramFileds.emplace_back(ParamConstants::PARAM_REMOTE_SIGNERPLUGIN); - std::unordered_set paramSet = Params::InitParamField(paramFileds); - for (auto it = options->begin(); it != options->end(); it++) { - if (paramSet.find(it->first) != paramSet.end()) { - size_t size = it->first.size(); - std::string str = it->first.substr(size - 3); - if (str == "Pwd") { - signParams.insert(std::make_pair(it->first, "")); - } else { - signParams.insert(std::make_pair(it->first, options->GetString(it->first))); - } - } - } - for (const auto& param : paramFileds) { - if (signParams.find(param) == signParams.end()) { - PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, - "Missing parameter:" + param); - return false; - } - } - return true; -} - -bool RemoteSignProvider::CheckInputCertMatchWithProfile(X509* inputCert, X509* certInProfile) const -{ - bool ret = true; - if (inputCert == nullptr || certInProfile == nullptr) { - PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, - "The certificate is empty"); - return false; - } - X509_NAME* subject1 = X509_get_subject_name(inputCert); - X509_NAME* subject2 = X509_get_subject_name(certInProfile); - if (X509_NAME_cmp(subject1, subject2) != 0) { - PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, - "The subject does not match!"); - return false; - } - X509_NAME* issuer1 = X509_get_issuer_name(inputCert); - X509_NAME* issuer2 = X509_get_issuer_name(certInProfile); - if (X509_NAME_cmp(issuer1, issuer2) != 0) { - PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, - "The issuer name does not match!"); - return false; - } - ASN1_INTEGER* serial1 = X509_get_serialNumber(inputCert); - ASN1_INTEGER* serial2 = X509_get_serialNumber(certInProfile); - if (ASN1_INTEGER_cmp(serial1, serial2) != 0) { - PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, - "serial number does not match!"); - return false; - } - EVP_PKEY* pkey1 = X509_get_pubkey(inputCert); - EVP_PKEY* pkey2 = X509_get_pubkey(certInProfile); - if (pkey1 && pkey2 && EVP_PKEY_cmp(pkey1, pkey2) != 1) { - EVP_PKEY_free(pkey1); - EVP_PKEY_free(pkey2); - PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, - "The public key does not match!"); - return false; - } - if (!pkey1 || !pkey2) { - PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, - "The public key is null!"); - ret = false; - } - if (pkey1) EVP_PKEY_free(pkey1); - if (pkey2) EVP_PKEY_free(pkey2); - return ret; -} -} // namespace SignatureTools -} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/hap/provider/src/sign_provider.cpp b/binary_sign_tool/hap/provider/src/sign_provider.cpp index 35ff929ac76402a56051a1c3cc1d3ea086cc97e7..c0ccd18404d72f46db23e87e9df97688a93624ce 100644 --- a/binary_sign_tool/hap/provider/src/sign_provider.cpp +++ b/binary_sign_tool/hap/provider/src/sign_provider.cpp @@ -48,6 +48,15 @@ bool SignProvider::InitSigerConfig(SignerConfig& signerConfig, STACK_OF(X509)* p bool SignProvider::SignElf(Options* options) { + // 1.check the parameters + if (!CheckParams(options)) { + SIGNATURE_TOOLS_LOGE("Check Params failed please check"); + return false; + } + if (!CheckSignatureAlg()) { + SIGNATURE_TOOLS_LOGE("signAlg Parameter is not support"); + return false; + } STACK_OF(X509)* publicCerts = nullptr; int ret = GetX509Certificates(options, &publicCerts); if (ret != RET_OK) { @@ -64,7 +73,6 @@ bool SignProvider::SignElf(Options* options) if (!profileContent.empty()) { signParams.insert(std::make_pair(ParamConstants::PARAM_PROFILE_JSON_CONTENT, profileContent)); } - if (!SignElf::Sign(signerConfig, signParams)) { SIGNATURE_TOOLS_LOGE("[SignElf] sign elf failed"); return false; @@ -82,8 +90,7 @@ bool SignProvider::CreateSignerConfigs(STACK_OF(X509)* certificates, const std:: std::vector signatureAlgorithms; SignatureAlgorithmHelper alg; // Since CheckParmaAndInitConfig has already validated all parameters, it is possible to directly use at - if (!Params::GetSignatureAlgorithm(signParams.at(ParamConstants::PARAM_BASIC_SIGANTURE_ALG), - alg)) { + if (!Params::GetSignatureAlgorithm(signParams.at(ParamConstants::PARAM_BASIC_SIGANTURE_ALG), alg)) { SIGNATURE_TOOLS_LOGE("[Sign] get Signature Algorithm failed"); return false; } @@ -96,90 +103,26 @@ bool SignProvider::CreateSignerConfigs(STACK_OF(X509)* certificates, const std:: return true; } -int SignProvider::LoadOptionalBlocks() -{ - int ret = RET_OK; - if (auto property = signParams.find(ParamConstants::PARAM_BASIC_PROPERTY); - property != signParams.end()) { - if ((ret = LoadOptionalBlock(property->second, HapUtils::HAP_PROPERTY_BLOCK_ID)) != RET_OK) - return ret; - } - if (auto profile = signParams.find(ParamConstants::PARAM_BASIC_PROFILE); profile != signParams.end()) { - if ((ret = LoadOptionalBlock(profile->second, HapUtils::HAP_PROFILE_BLOCK_ID)) != RET_OK) - return ret; - } - if (auto proofOfRotation = signParams.find(ParamConstants::PARAM_BASIC_PROOF); - proofOfRotation != signParams.end()) { - if ((LoadOptionalBlock(proofOfRotation->second, HapUtils::HAP_PROOF_OF_ROTATION_BLOCK_ID)) != RET_OK) - return ret; - } - return ret; -} - -int SignProvider::LoadOptionalBlock(const std::string& file, int type) -{ - if (file.empty()) - return RET_OK; - if (!CheckFile(file)) { - SIGNATURE_TOOLS_LOGE("check file failed. Invalid file: %s, file type: %d", - file.c_str(), type); - return FILE_NOT_FOUND; - } - ByteBuffer optionalBlockBuffer; - if (!FileUtils::ReadFileToByteBuffer(file, optionalBlockBuffer)) - return IO_ERROR; - if (optionalBlockBuffer.GetCapacity() == 0) { - PrintErrorNumberMsg("IO_ERROR", IO_ERROR, file + " is empty!"); - return IO_ERROR; - } - optionalBlocks.push_back({type, optionalBlockBuffer}); - return RET_OK; -} - std::optional SignProvider::GetCrl() { return std::nullopt; } -bool SignProvider::CheckFile(const std::string& filePath) -{ - if (filePath.empty()) { - PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "file name is null."); - return false; - } - if (!std::filesystem::exists(filePath) || !std::filesystem::is_regular_file(filePath)) { - PrintErrorNumberMsg("IO_ERROR", IO_ERROR, filePath + " not exist or can not read!"); - return false; - } - return true; -} - int SignProvider::GetX509Certificates(Options* options, STACK_OF(X509)** X509Vec) { int ret = RET_OK; - // 1.check the parameters - if (!CheckParams(options)) { - SIGNATURE_TOOLS_LOGE("Check Params failed please check"); - return COMMAND_ERROR; - } // 2.get x509 verify certificate ret = GetPublicCerts(options, X509Vec); if (ret != RET_OK) { SIGNATURE_TOOLS_LOGE("Get Public Certs please check"); return ret; } - // 3. load optionalBlocks - ret = LoadOptionalBlocks(); - if (ret != RET_OK) { - SIGNATURE_TOOLS_LOGE("Load Optional Blocks please check"); - return ret; - } std::string profileFile = options->GetString(Options::PROFILE_FILE); if (FileUtils::IsEmpty(profileFile)) { return ret; } - // 4. check Profile Valid - if ((ret = CheckProfileValid(*X509Vec)) < 0) { + // 3. check Profile Valid + if ((ret = CheckProfileValid(*X509Vec, profileFile)) < 0) { SIGNATURE_TOOLS_LOGE("profile check error"); sk_X509_pop_free(*X509Vec, X509_free); *X509Vec = nullptr; @@ -251,8 +194,6 @@ bool SignProvider::CheckParams(Options* options) paramFileds.emplace_back(ParamConstants::PARAM_BASIC_OUTPUT_FILE); paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PRIVATE_KEY); paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PROFILE); - paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PROOF); - paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PROPERTY); paramFileds.emplace_back(ParamConstants::PARAM_REMOTE_SERVER); paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PROFILE_SIGNED); paramFileds.emplace_back(ParamConstants::PARAM_LOCAL_PUBLIC_CERT); @@ -275,11 +216,6 @@ bool SignProvider::CheckParams(Options* options) || signParams.at(ParamConstants::PARAM_AD_HOC).empty()) { signParams[ParamConstants::PARAM_AD_HOC] = ParamConstants::AD_HOC_TYPE_0; } - if (!CheckSignatureAlg()) { - SIGNATURE_TOOLS_LOGE("signAlg Parameter is not support"); - return false; - } - CheckSignAlignment(); return true; } @@ -356,21 +292,13 @@ std::string SignProvider::GetCertificateCN(X509* cert)const return ret; } -std::string SignProvider::FindProfileFromOptionalBlocks()const +int SignProvider::CheckProfileValid(STACK_OF(X509)* inputCerts, const std::string& file) { std::string profile; - for (const OptionalBlock& optionalBlock : optionalBlocks) { - if (optionalBlock.optionalType == HapUtils::HAP_PROFILE_BLOCK_ID) { - profile = std::string(optionalBlock.optionalBlockValue.GetBufferPtr(), - optionalBlock.optionalBlockValue.GetCapacity()); - } + if (FileUtils::ReadFile(file, profile) < 0) { + SIGNATURE_TOOLS_LOGE("profile read faild!"); + return IO_ERROR; } - return profile; -} - -int SignProvider::CheckProfileValid(STACK_OF(X509)* inputCerts) -{ - std::string profile = FindProfileFromOptionalBlocks(); std::map::const_iterator ite = signParams.find(ParamConstants::PARAM_BASIC_PROFILE_SIGNED); if (ite == signParams.end()) { diff --git a/binary_sign_tool/hap/sign/include/sign_elf.h b/binary_sign_tool/hap/sign/include/sign_elf.h index 6840d35d8b9bbc1e3bbde34a4bf7ba5d666d966e..4a929a350b40625e6659b9d0594b62a380c01a14 100644 --- a/binary_sign_tool/hap/sign/include/sign_elf.h +++ b/binary_sign_tool/hap/sign/include/sign_elf.h @@ -28,26 +28,25 @@ namespace OHOS { namespace SignatureTools { class SignElf { public: - static const char CODESIGN_BLOCK_TYPE = 3; static bool Sign(SignerConfig& signerConfig, std::map &signParams); private: - static int blockNum; - static constexpr int FILE_PATH_LENGTH = 256; static constexpr int PAGE_SIZE = 4096; - static constexpr int FILE_BUFFER_BLOCK = 16384; static const std::string profileSec; static const std::string permissionSec; + static const std::string codesignSec; static bool loadModule(std::map& signParams, std::string& moduleContent); static bool loadProfileAndSign(SignerConfig& signerConfig, std::map& signParams, std::string& p7b); static bool isExecElf(ELFIO::elfio& reader); - static bool WriteCodeSignBlock(SignerConfig& signerConfig, const std::map& signParams, - long secOffset); + static bool WriteCodeSignBlock(ELFIO::elfio& reader, std::string& tmpOutputFilePath, uint64_t& csOffset); static bool WriteSection(ELFIO::elfio& reader, const std::string& content, const std::string& secName); static bool WriteSecDataToFile(ELFIO::elfio& reader, SignerConfig& signerConfig, std::map& signParams); + static bool GenerateCodeSignByte(SignerConfig& signerConfig, const std::string& inputFile, uint64_t& csOffset, + const std::string& adHoc); + static bool ReplaceDataOffset(const std::string& filePath, uint64_t& csOffset, const std::vector& csData); }; } // namespace SignatureTools } // namespace OHOS diff --git a/binary_sign_tool/hap/sign/src/sign_elf.cpp b/binary_sign_tool/hap/sign/src/sign_elf.cpp index 3563f5cbba3e7be11b1b7c959a3059fa49a15f50..bc54e3aa4b39cff950c2ca88df259e3f8f700924 100644 --- a/binary_sign_tool/hap/sign/src/sign_elf.cpp +++ b/binary_sign_tool/hap/sign/src/sign_elf.cpp @@ -20,13 +20,14 @@ #include "file_utils.h" #include "string_utils.h" #include "constant.h" +#include "code_signing.h" #include "param_constants.h" #include "profile_sign_tool.h" namespace OHOS { namespace SignatureTools { -int SignElf::blockNum = 0; +const std::string SignElf::codesignSec = ".codesign"; const std::string SignElf::profileSec = ".profile"; const std::string SignElf::permissionSec = ".permission"; constexpr size_t MAX_SECTION_SIZE = static_cast(0xFFFFFFFF); @@ -45,15 +46,27 @@ bool SignElf::Sign(SignerConfig& signerConfig, std::map 0 and 4K alignment + if (csOffset == 0 || (csOffset % PAGE_SIZE) != 0) { + SIGNATURE_TOOLS_LOGE("[SignElf] csOffset is not 4K alignment"); + return false; + } + std::string adHoc = signParams.at(ParamConstants::PARAM_AD_HOC); + bool generateCodeSignFlag = GenerateCodeSignByte(signerConfig, tmpOutputFile, csOffset, adHoc); + if (!generateCodeSignFlag) { + return false; + } + return FileUtils::CopyTmpFileAndDel(tmpOutputFile, outputFile); } bool SignElf::loadModule(std::map& signParams, std::string& moduleContent) @@ -65,11 +78,10 @@ bool SignElf::loadModule(std::map& signParams, std::st return false; } } else { - SIGNATURE_TOOLS_LOGE("[SignElf] Failed to find module file"); - return false; + SIGNATURE_TOOLS_LOGI("[SignElf] No module file"); } if (moduleContent.size() > MAX_SECTION_SIZE) { - SIGNATURE_TOOLS_LOGE("[SignElf] moduleContent size exceeds maximum allowed section size"); + SIGNATURE_TOOLS_LOGE("[SignElf] moduleContent size exceeds maximum allowed section size (4GB)"); return false; } return true; @@ -86,8 +98,7 @@ bool SignElf::loadProfileAndSign(SignerConfig& signerConfig, std::map MAX_SECTION_SIZE) { - SIGNATURE_TOOLS_LOGE("[SignElf] profileContent size exceeds maximum allowed section size"); + SIGNATURE_TOOLS_LOGE("[SignElf] profileContent size exceeds maximum allowed section size (4GB)"); return false; } return true; @@ -118,45 +129,32 @@ bool SignElf::isExecElf(ELFIO::elfio& reader) return false; } -bool SignElf::WriteCodeSignBlock(SignerConfig& signerConfig, const std::map& signParams, - long secOffset) +bool SignElf::WriteCodeSignBlock(ELFIO::elfio& reader, std::string& outputFile, uint64_t& csOffset) { - std::string inputFile = signParams.at(ParamConstants::PARAM_BASIC_INPUT_FILE); - std::string outputFile = signParams.at(ParamConstants::PARAM_BASIC_OUTPUT_FILE); - - ELFIO::elfio reader; - if (!reader.load(inputFile)) { - SIGNATURE_TOOLS_LOGE("[SignElf] Failed to load input ELF file"); + ELFIO::section* sec = reader.sections[codesignSec]; + if (sec) { + SIGNATURE_TOOLS_LOGE("[SignElf] .codesign section already exists"); return false; } - - // Create .codesign section with 4K size - ELFIO::section* codesignSec = reader.sections.add(".codesign"); - if (!codesignSec) { + sec = reader.sections.add(codesignSec); + if (!sec) { SIGNATURE_TOOLS_LOGE("[SignElf] Failed to create .codesign section"); return false; } + sec->set_type(ELFIO::SHT_PROGBITS); + sec->set_flags(ELFIO::SHF_ALLOC); + sec->set_addr_align(PAGE_SIZE); + char codesignData[PAGE_SIZE]; + sec->set_data(codesignData, PAGE_SIZE); - codesignSec->set_type(ELFIO::SHT_PROGBITS); - codesignSec->set_flags(ELFIO::SHF_ALLOC); - codesignSec->set_addr_align(1); - - // Allocate 4K of data - const size_t codesignSize = 4096; - std::vector codesignData(codesignSize, 0); - - codesignSec->set_data(codesignData.data(), codesignData.size()); - - // Save the modified ELF file if (!reader.save(outputFile)) { - SIGNATURE_TOOLS_LOGE("[SignElf] Failed to save output ELF file"); + SIGNATURE_TOOLS_LOGE("[SignElf] Failed to save 4K data to .codesign section"); return false; } - - // Get the offset of the .codesign section - ELFIO::Elf64_Off sectionOffset = codesignSec->get_offset(); - SIGNATURE_TOOLS_LOGI("[SignElf] .codesign section offset: %ld", sectionOffset); - secOffset = sectionOffset; + ELFIO::Elf64_Off secOff = sec->get_offset(); + csOffset = secOff; + PrintMsg("add codesign section success"); + SIGNATURE_TOOLS_LOGD("[SignElf] .codesign section offset: %lu, size: %lu", secOff, sec->get_size()); return true; } @@ -182,6 +180,9 @@ bool SignElf::WriteSection(ELFIO::elfio& reader, const std::string& content, con bool SignElf::WriteSecDataToFile(ELFIO::elfio& reader, SignerConfig& signerConfig, std::map& signParams) { + if (signParams.at(ParamConstants::PARAM_AD_HOC) == ParamConstants::AD_HOC_TYPE_1) { + return true; + } // check elf bin or so if (!isExecElf(reader)) { return true; @@ -190,18 +191,74 @@ bool SignElf::WriteSecDataToFile(ELFIO::elfio& reader, SignerConfig& signerConfi if (!loadProfileAndSign(signerConfig, signParams, p7b)) { return false; } - if (!WriteSection(reader, p7b, profileSec)) { - return false; + if (!p7b.empty()) { + if (WriteSection(reader, p7b, profileSec)) { + PrintMsg("add profile section success"); + } else { + return false; + } } - PrintMsg("add profile to ELF file success"); std::string moduleContent; if (!loadModule(signParams, moduleContent)) { return false; } - if (!WriteSection(reader, moduleContent, permissionSec)) { + + if (!moduleContent.empty()) { + if (WriteSection(reader, moduleContent, permissionSec)) { + PrintMsg("add permission section success"); + } else { + return false; + } + } + return true; +} + +bool SignElf::GenerateCodeSignByte(SignerConfig& signerConfig, const std::string& inputFile, uint64_t& csOffset, + const std::string& adHoc) +{ + CodeSigning codeSigning(&signerConfig, (adHoc == ParamConstants::AD_HOC_TYPE_1)); + std::vector codesignData; + bool getElfCodeSignBlockFlag = codeSigning.GetElfCodeSignBlock(inputFile, csOffset, codesignData); + if (!getElfCodeSignBlockFlag) { + SIGNATURE_TOOLS_LOGE("[SignElf] get elf code sign block error."); + return false; + } + SIGNATURE_TOOLS_LOGD("[SignElf] elf code sign block off %lu: ,len: %lu .", csOffset, codesignData.size()); + + if (codesignData.size() > PAGE_SIZE) { + SIGNATURE_TOOLS_LOGE("[SignElf] signature size is too large."); + return false; + } + + if (!ReplaceDataOffset(inputFile, csOffset, codesignData)) { + SIGNATURE_TOOLS_LOGE("[SignElf] Failed to replace code sign data in file."); + return false; + } + PrintMsg("write code sign data success"); + return true; +} + +bool SignElf::ReplaceDataOffset(const std::string& filePath, uint64_t& csOffset, const std::vector& csData) +{ + std::fstream fileStream(filePath, std::ios::in | std::ios::out | std::ios::binary); + if (!fileStream) { + SIGNATURE_TOOLS_LOGE("[SignElf] Failed to open file: %s", filePath.c_str()); + return false; + } + + fileStream.seekp(csOffset, std::ios::beg); + if (!fileStream) { + SIGNATURE_TOOLS_LOGE("[SignElf] Failed to seek to offset: %lu", csOffset); + return false; + } + + fileStream.write(reinterpret_cast(csData.data()), csData.size()); + if (!fileStream) { + SIGNATURE_TOOLS_LOGE("[SignElf] Failed to write data at offset: %lu", csOffset); return false; } - PrintMsg("add permission to ELF file success"); + fileStream.flush(); + fileStream.close(); return true; } } // namespace SignatureTools diff --git a/binary_sign_tool/hap/signature_tools_hap.gni b/binary_sign_tool/hap/signature_tools_hap.gni index 6069ded5b1eed0f42b4a490af5055d6d4e5dd443..a8ea3a9b0b58a6810e18e0548e1c5dfce039072e 100644 --- a/binary_sign_tool/hap/signature_tools_hap.gni +++ b/binary_sign_tool/hap/signature_tools_hap.gni @@ -13,8 +13,8 @@ import("../signature_tools.gni") signature_tools_hap_include = [ - "${signature_tools_hap}/verify/include", - "${signature_tools_hap}/config/include", + "${hapsigntool_cpp_hap}/verify/include", + "${hapsigntool_cpp_hap}/config/include", "${signature_tools_hap}/entity/include", "${signature_tools_hap}/provider/include", "${signature_tools_hap}/sign/include", @@ -22,14 +22,15 @@ signature_tools_hap_include = [ ] signature_tools_hap_src = [ - "${signature_tools_hap}/config/src/signer_config.cpp", - "${signature_tools_hap}/entity/src/content_digest_algorithm.cpp", + "${hapsigntool_cpp_hap}/config/src/signer_config.cpp", + "${hapsigntool_cpp_hap}/entity/src/content_digest_algorithm.cpp", "${signature_tools_hap}/entity/src/param_constants.cpp", - "${signature_tools_hap}/entity/src/signature_algorithm_helper.cpp", + "${hapsigntool_cpp_hap}/entity/src/signature_algorithm_helper.cpp", + "${signature_tools_hap}/provider/src/ad_hoc_sign_provider.cpp", "${signature_tools_hap}/provider/src/local_sign_provider.cpp", - "${signature_tools_hap}/provider/src/remote_sign_provider.cpp", + "${hapsigntool_cpp_hap}/provider/src/remote_sign_provider.cpp", "${signature_tools_hap}/provider/src/sign_provider.cpp", "${signature_tools_hap}/sign/src/sign_elf.cpp", - "${signature_tools_hap}/utils/src/dynamic_lib_handle.cpp", + "${hapsigntool_cpp_hap}/utils/src/dynamic_lib_handle.cpp", "${signature_tools_hap}/sign/src/bc_pkcs7_generator.cpp", ] diff --git a/binary_sign_tool/hap/utils/include/hap_utils.h b/binary_sign_tool/hap/utils/include/hap_utils.h deleted file mode 100644 index e0d0cd9e488b21ea46bfea87263a524d7facf367..0000000000000000000000000000000000000000 --- a/binary_sign_tool/hap/utils/include/hap_utils.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 SIGNATRUETOOLS_HAP_UTILS_H -#define SIGNATRUETOOLS_HAP_UTILS_H - -#include -#include -#include -#include -#include -#include - -#include "content_digest_algorithm.h" -#include "signature_tools_log.h" - -namespace OHOS { -namespace SignatureTools { -class HapUtils { -public: - static constexpr int HAP_SIGNATURE_SCHEME_V1_BLOCK_ID = 0x20000000; - static constexpr int HAP_PROOF_OF_ROTATION_BLOCK_ID = 0x20000001; - static constexpr int HAP_PROFILE_BLOCK_ID = 0x20000002; - static constexpr int HAP_PROPERTY_BLOCK_ID = 0x20000003; - static constexpr int HAP_CODE_SIGN_BLOCK_ID = 0x30000001; - static constexpr int CONTENT_DIGESTED_CHUNK_MAX_SIZE_BYTES = 1024 * 1024; - static constexpr int CONTENT_VERSION = 2; - static constexpr int BIT_SIZE = 8; - static constexpr int HALF_BIT_SIZE = 4; - static constexpr int INT_SIZE = 4; - static constexpr int BLOCK_NUMBER = 1; - static constexpr int HAP_SIGN_SCHEME_V2_BLOCK_VERSION = 2; - static constexpr int HAP_SIGN_SCHEME_V3_BLOCK_VERSION = 3; - static constexpr int64_t HAP_SIG_BLOCK_MAGIC_LO_V2 = 0x2067695320504148LL; - static constexpr int64_t HAP_SIG_BLOCK_MAGIC_HI_V2 = 0x3234206b636f6c42LL; - static constexpr int64_t HAP_SIG_BLOCK_MAGIC_LO_V3 = 0x676973207061683cLL; - static constexpr int64_t HAP_SIG_BLOCK_MAGIC_HI_V3 = 0x3e6b636f6c62206eLL; - static constexpr int HAP_SIG_BLOCK_HEADER_SIZE = 32; - static constexpr int HAP_SIG_BLOCK_MIN_SIZE = HAP_SIG_BLOCK_HEADER_SIZE; - static constexpr int BLOCK_SIZE = 8; -}; -} // namespace SignatureTools -} // namespace OHOS -#endif diff --git a/binary_sign_tool/signature_tools.gni b/binary_sign_tool/signature_tools.gni index f2a67bd884b056fbb5f767a4b36d99926cacecef..56b002a52104c17dfda7bba7a41ed230899cf132 100644 --- a/binary_sign_tool/signature_tools.gni +++ b/binary_sign_tool/signature_tools.gni @@ -15,18 +15,18 @@ signature_tools_root_path = "//developtools/hapsigner/binary_sign_tool" signature_tools_utils = "${signature_tools_root_path}/utils" signature_tools_cmd = "${signature_tools_root_path}/cmd" signature_tools_error = "${signature_tools_root_path}/error" - -# signature_tools_codesigning = "${signature_tools_root_path}/codesigning" +signature_tools_codesigning = "${signature_tools_root_path}/codesigning" signature_tools_common = "${signature_tools_root_path}/common" signature_tools_hap = "${signature_tools_root_path}/hap" signature_tools_profile = "${signature_tools_root_path}/profile" signature_tools_signer = "${signature_tools_root_path}/signer" signature_tools_api = "${signature_tools_root_path}/api" -# signature_tools_test = "//developtools/hapsigner/hapsigntool_cpp_test" - hapsigntool_cpp_root_path = "//developtools/hapsigner/hapsigntool_cpp" hapsigntool_cpp_signer = "${hapsigntool_cpp_root_path}/signer" hapsigntool_cpp_common = "${hapsigntool_cpp_root_path}/common" hapsigntool_cpp_profile = "${hapsigntool_cpp_root_path}/profile" hapsigntool_cpp_utils = "${hapsigntool_cpp_root_path}/utils" +hapsigntool_cpp_codesigning = "${hapsigntool_cpp_root_path}/codesigning" +hapsigntool_cpp_cmd = "${hapsigntool_cpp_root_path}/cmd" +hapsigntool_cpp_hap = "${hapsigntool_cpp_root_path}/hap"