diff --git a/binary_sign_tool/BUILD.gn b/binary_sign_tool/BUILD.gn index 04d734d493e8a9c6f3cb05fc979680ec2bb8eb32..c7e94bbd986778926199645ba34dd552dba78c2a 100644 --- a/binary_sign_tool/BUILD.gn +++ b/binary_sign_tool/BUILD.gn @@ -12,7 +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") @@ -56,7 +56,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 @@ -64,7 +64,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 @@ -94,6 +94,8 @@ ohos_executable("binary-sign-tool") { "-Wno-c++20-extensions", ] + defines = [ "SIGNATURE_LOG_DEBUG" ] + install_images = [ "system" ] install_enable = false part_name = "hapsigner" 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/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_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/codesigning/fsverity/include/fs_verity_descriptor.h b/binary_sign_tool/codesigning/fsverity/include/fs_verity_descriptor.h new file mode 100644 index 0000000000000000000000000000000000000000..fc3e0fd5e71be0376412e8029df609e2d06fe9af --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/include/fs_verity_descriptor.h @@ -0,0 +1,182 @@ +/* + * 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_FSVERITY_DESCRIPTOR_H +#define SIGNATURETOOLS_FSVERITY_DESCRIPTOR_H + +#include +#include +#include + +#include "byte_buffer.h" +#include "signature_tools_log.h" + +namespace OHOS { +namespace SignatureTools { +class FsVerityDescriptor { +public: + static const uint8_t VERSION = 1; + static const int PAGE_SIZE_4K = 4096; + static const int FLAG_STORE_MERKLE_TREE_OFFSET = 0x1; + static const int FS_VERITY_DESCRIPTOR_TYPE = 0x1; + static const uint8_t CODE_SIGN_VERSION = 0x1; + static const int DESCRIPTOR_SIZE = 256; + static const int ROOT_HASH_FILED_SIZE = 64; + static const int SALT_SIZE = 32; + static const int RESERVED_SIZE_AFTER_FLAGS = 4; + static const int RESERVED_SIZE_AFTER_TREE_OFFSET = 127; + + class Builder; + FsVerityDescriptor(); + long GetFileSize() + { + return fileSize; + } + + long GetMerkleTreeOffset() + { + return merkleTreeOffset; + } + + int GetSignSize() + { + return signSize; + } + + static FsVerityDescriptor FromByteArray(std::vector& bytes); + void ToByteArray(std::vector &ret); + void GetByteForGenerateDigest(std::vector& ret); + + FsVerityDescriptor(Builder& builder) + { + this->version = builder.version; + this->fileSize = builder.fileSize; + this->hashAlgorithm = builder.hashAlgorithm; + this->log2BlockSize = builder.log2BlockSize; + this->saltSize = builder.saltSize; + this->signSize = builder.signSize; + this->salt = builder.salt; + this->rawRootHash = builder.rawRootHash; + this->flags = builder.flags; + this->merkleTreeOffset = builder.merkleTreeOffset; + this->csVersion = builder.csVersion; + } + + void WriteBytesWithSize(ByteBuffer* buffer, std::vector& src, int size); + +public: +class Builder { + friend class FsVerityDescriptor; +public: + Builder& SetVersion(uint8_t version) + { + this->version = version; + return *this; + } + + Builder& SetFileSize(long fileSize) + { + this->fileSize = fileSize; + return *this; + } + + Builder& SetHashAlgorithm(uint8_t hashAlgorithm) + { + this->hashAlgorithm = hashAlgorithm; + return *this; + } + + Builder& SetLog2BlockSize(uint8_t log2BlockSize) + { + this->log2BlockSize = log2BlockSize; + return *this; + } + + Builder& SetSignSize(int signSize) + { + this->signSize = signSize; + return *this; + } + + Builder& SetSaltSize(uint8_t saltSize) + { + this->saltSize = saltSize; + return *this; + } + + Builder& SetSalt(const std::vector& salt) + { + this->salt = salt; + return *this; + } + + Builder& SetRawRootHash(const std::vector& rawRootHash) + { + this->rawRootHash = rawRootHash; + return *this; + } + + Builder& SetFlags(int flags) + { + this->flags = flags; + return *this; + } + + Builder& SetMerkleTreeOffset(long merkleTreeOffset) + { + this->merkleTreeOffset = merkleTreeOffset; + return *this; + } + + Builder& SetCsVersion(uint8_t csVersion) + { + this->csVersion = csVersion; + return *this; + } + + FsVerityDescriptor Build() + { + return FsVerityDescriptor(*this); + } + +private: + uint8_t version = VERSION; + long fileSize; + uint8_t hashAlgorithm; + uint8_t log2BlockSize; + uint8_t saltSize; + int signSize; + std::vector salt; + std::vector rawRootHash; + std::int32_t flags; + std::int64_t merkleTreeOffset; + uint8_t csVersion; +}; + +private: + uint8_t version; + long fileSize; + uint8_t hashAlgorithm; + uint8_t log2BlockSize; + uint8_t saltSize; + int signSize; + std::vector salt; + std::vector rawRootHash; + int flags; + long merkleTreeOffset; + uint8_t csVersion; +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATURETOOLS_FSVERITY_DESCRIPTOR_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/include/fs_verity_descriptor_with_sign.h b/binary_sign_tool/codesigning/fsverity/include/fs_verity_descriptor_with_sign.h new file mode 100644 index 0000000000000000000000000000000000000000..c5cf6f07475c2c5902d3d3b818e25c758ffb138a --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/include/fs_verity_descriptor_with_sign.h @@ -0,0 +1,47 @@ +/* + * 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_FSVERITY_DESCRIPTOR_WITH_SIGN_H +#define SIGNATURETOOLS_FSVERITY_DESCRIPTOR_WITH_SIGN_H + +#include +#include + +#include "fs_verity_descriptor.h" + +namespace OHOS { +namespace SignatureTools { +class FsVerityDescriptorWithSign { +public: + static constexpr int32_t INTEGER_BYTES = 4; + +public: + FsVerityDescriptorWithSign(); + FsVerityDescriptorWithSign(FsVerityDescriptor fsVerityDescriptor, const std::vector &signature); + FsVerityDescriptorWithSign(int32_t type, int32_t length, FsVerityDescriptor fsVerityDescriptor, + const std::vector &signature); + int32_t Size(); + void ToByteArray(std::vector &ret); + FsVerityDescriptor GetFsVerityDescriptor(); + std::vector& GetSignature(); + +private: + int32_t type = FsVerityDescriptor::FS_VERITY_DESCRIPTOR_TYPE;; + int32_t length; + FsVerityDescriptor fsVerityDescriptor; + std::vector signature; +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATURETOOLS_FSVERITY_DIGEST_H \ No newline at end of file diff --git a/binary_sign_tool/utils/include/signature_info.h b/binary_sign_tool/codesigning/fsverity/include/fs_verity_digest.h similarity index 65% rename from binary_sign_tool/utils/include/signature_info.h rename to binary_sign_tool/codesigning/fsverity/include/fs_verity_digest.h index 6df6a0926299aa354e8e2cb724a5200557b550fc..e4f7cd369c6a45c7d1b496850ce583a1e47473f1 100644 --- a/binary_sign_tool/utils/include/signature_info.h +++ b/binary_sign_tool/codesigning/fsverity/include/fs_verity_digest.h @@ -12,18 +12,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef SIGNERTOOLS_SIGNATURE_INFO_H -#define SIGNERTOOLS_SIGNATURE_INFO_H +#ifndef SIGNATURETOOLS_FSVERITY_DIGEST_H +#define SIGNATURETOOLS_FSVERITY_DIGEST_H +#include #include +#include + #include "byte_buffer.h" namespace OHOS { namespace SignatureTools { -struct OptionalBlock { - int32_t optionalType = 0; - ByteBuffer optionalBlockValue; +class FsVerityDigest { +public: + static void GetFsVerityDigest(int8_t algoID, std::vector& digest, std::vector& ret); + +private: + static const std::string FSVERITY_DIGEST_MAGIC; + static const int DIGEST_HEADER_SIZE; }; } // namespace SignatureTools } // namespace OHOS -#endif // HAP_SIGNATURE_INFO_H +#endif // SIGNATURETOOLS_FSVERITY_DIGEST_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/include/fs_verity_generator.h b/binary_sign_tool/codesigning/fsverity/include/fs_verity_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..da43ce8c835ba0d59303adaba59e03fb2a883e1e --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/include/fs_verity_generator.h @@ -0,0 +1,86 @@ +/* + * 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_FSVERITY_GENERATOR_H +#define SIGNATURETOOLS_FSVERITY_GENERATOR_H + +#include +#include +#include + +#include "merkle_tree.h" +#include "merkle_tree_builder.h" +#include "fs_verity_descriptor.h" +#include "fs_verity_digest.h" + +namespace OHOS { +namespace SignatureTools { +class FsVerityGenerator { +public: + MerkleTree* GenerateMerkleTree(std::istream& inputStream, long size, + const FsVerityHashAlgorithm& fsVerityHashAlgorithm); + bool GenerateFsVerityDigest(std::istream& inputStream, long size, long fsvTreeOffset); + std::vector GetFsVerityDigest() + { + return fsVerityDigest; + } + + std::vector Getsalt() + { + return salt; + } + + std::vector GetTreeBytes() + { + return treeBytes; + } + + std::vector GetRootHash() + { + return rootHash; + } + + std::vector GetSalt() + { + return salt; + } + + int GetSaltSize() + { + return salt.empty() ? 0 : salt.size(); + } + + 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 fsVerityDigest; + std::vector treeBytes; + std::vector rootHash; +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATURETOOLS_FSVERITY_GENERATOR_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/include/fs_verity_hash_algorithm.h b/binary_sign_tool/codesigning/fsverity/include/fs_verity_hash_algorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..3c8ae8c3399bedd99738d806038ef567b5edff2f --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/include/fs_verity_hash_algorithm.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SIGNATURETOOLS_FSVERITY_HASH_ALGORITHM_H +#define SIGNATURETOOLS_FSVERITY_HASH_ALGORITHM_H + +#include + +namespace OHOS { +namespace SignatureTools { +class FsVerityHashAlgorithm { +public: + static const FsVerityHashAlgorithm SHA256; + static const FsVerityHashAlgorithm SHA512; + FsVerityHashAlgorithm(const uint8_t id, const std::string& hashAlgorithm, const int outputByteSize) + : id(id), hashAlgorithm(hashAlgorithm), outputByteSize(outputByteSize) + { + } + char GetId() const; + const std::string& GetHashAlgorithm() const; + int GetOutputByteSize() const; + +private: + const uint8_t id; + const std::string hashAlgorithm; + const int outputByteSize; +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATURETOOLS_FSVERITY_HASH_ALGORITHM_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/include/merkle_tree.h b/binary_sign_tool/codesigning/fsverity/include/merkle_tree.h new file mode 100644 index 0000000000000000000000000000000000000000..c82d1ae19eec8ace521468b6712c2380f0e0e0e7 --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/include/merkle_tree.h @@ -0,0 +1,39 @@ +/* + * 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_H +#define SIGNATURETOOLS_MERKLE_TREE_H + +#include + +#include "fs_verity_hash_algorithm.h" + +namespace OHOS { +namespace SignatureTools { +class MerkleTree { +public: + MerkleTree(const std::vector& rootHash, const std::vector& tree, + const SignatureTools::FsVerityHashAlgorithm& fsVerityHashAlgorithm) + : rootHash(rootHash), + tree(tree), + fsVerityHashAlgorithm(fsVerityHashAlgorithm) + { + } + std::vector rootHash; + std::vector tree; + SignatureTools::FsVerityHashAlgorithm fsVerityHashAlgorithm; +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATURETOOLS_MERKLE_TREE_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..629a9847427bc4fa4b1542fa22b43d231825934c --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/include/merkle_tree_builder.h @@ -0,0 +1,73 @@ +/* + * 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); + +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; +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATURETOOLS_MERKLE_TREE_BUILDER_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/include/thread_pool.h b/binary_sign_tool/codesigning/fsverity/include/thread_pool.h new file mode 100644 index 0000000000000000000000000000000000000000..18e1de6e9df1dd8fd19a78809bc0cc0340c12081 --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/include/thread_pool.h @@ -0,0 +1,105 @@ +/* + * 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_THREAD_POOL_H +#define SIGNATRUETOOLS_THREAD_POOL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TASK_NUM (std::thread::hardware_concurrency()) + +namespace OHOS { +namespace SignatureTools { +namespace Uscript { +class ThreadPool { +public: + ThreadPool(size_t threads = TASK_NUM) + : m_stop(false) + { + for (size_t i = 0; i < threads; ++i) + m_workers.emplace_back([this] { + std::function task; + std::unique_lock lock(m_queueMutex); + while (!(m_stop && m_tasks.empty())) { + m_condition.wait(lock, [this] { return m_stop || !m_tasks.empty(); }); + if (m_stop && m_tasks.empty()) { + return; + } + task = std::move(m_tasks.front()); + m_tasks.pop(); + lock.unlock(); + task(); + lock.lock(); + m_conditionMax.notify_one(); + } + }); + } + + template + auto Enqueue(F&& f, Args&& ... args) + -> std::future::type> + { + using returnType = typename std::result_of::type; + auto task = std::make_shared< std::packaged_task >( + std::bind(std::forward(f), std::forward(args)...) + ); + std::future res = task->get_future(); + { + std::unique_lock lock(m_queueMutex); + while (m_stop == false && m_tasks.size() >= TASK_NUM) { + m_conditionMax.wait(lock, [this] { return m_stop || m_tasks.size() < TASK_NUM; }); + } + m_tasks.emplace([task] () { (*task)(); }); + m_condition.notify_one(); + } + return res; + } + + ~ThreadPool() + { + if (m_stop == false) { + { + std::unique_lock lock(m_queueMutex); + m_stop = true; + } + m_condition.notify_all(); + for (std::thread& worker : m_workers) { + worker.join(); + } + } + } + +private: + // need to keep track of threads so we can join them + std::vector m_workers; + // the task queue + std::queue> m_tasks; + // synchronization + std::mutex m_queueMutex; + std::condition_variable m_condition; + std::condition_variable m_conditionMax; + bool m_stop; +}; +} // namespace Uscript +} // namespace SignatureTools +} // namespace OHOS +#endif \ 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..b219dd1c220e534db3b5de8acc523ed1a5efa95e --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/src/fs_verity_descriptor.cpp @@ -0,0 +1,142 @@ +/* + * 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() +{} + +FsVerityDescriptor FsVerityDescriptor::FromByteArray(std::vector& bytes) +{ + std::unique_ptr bf = std::make_unique(ByteBuffer(bytes.size())); + bf->PutData(bytes.data(), bytes.size()); + // after put, rewind is mandatory before get + bf->Flip(); + std::unique_ptr builder = + std::make_unique(FsVerityDescriptor::Builder()); + int8_t inFsVersion; + bf->GetInt8(inFsVersion); + if (FsVerityDescriptor::VERSION != inFsVersion) { + PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, + "The FS descriptor version of FsVerityDescriptor is incorrect"); + return builder->Build(); + } + int8_t inFsHashAlgorithm; + bf->GetInt8(inFsHashAlgorithm); + int8_t inLog2BlockSize; + bf->GetInt8(inLog2BlockSize); + builder->SetVersion(inFsVersion).SetHashAlgorithm(inFsHashAlgorithm).SetLog2BlockSize(inLog2BlockSize); + int8_t inSaltSize; + bf->GetInt8(inSaltSize); + int32_t inSignSize; + bf->GetInt32(inSignSize); + int64_t inDataSize; + bf->GetInt64(inDataSize); + char inRootHashArr[FsVerityDescriptor::ROOT_HASH_FILED_SIZE]; + bf->GetData(inRootHashArr, FsVerityDescriptor::ROOT_HASH_FILED_SIZE); + std::vector inRootHash(inRootHashArr, inRootHashArr + FsVerityDescriptor::ROOT_HASH_FILED_SIZE); + builder->SetSaltSize(inSaltSize).SetSignSize(inSignSize).SetFileSize(inDataSize).SetRawRootHash(inRootHash); + char inSaltArr[FsVerityDescriptor::SALT_SIZE]; + bf->GetData(inSaltArr, FsVerityDescriptor::SALT_SIZE); + std::vector inSalt(inSaltArr, inSaltArr + FsVerityDescriptor::SALT_SIZE); + int32_t inFlags; + bf->GetInt32(inFlags); + bf->SetPosition(bf->GetPosition() + RESERVED_SIZE_AFTER_FLAGS); + int64_t inTreeOffset; + bf->GetInt64(inTreeOffset); + if (inTreeOffset % PAGE_SIZE_4K != 0) { + PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, + "The offset of merkle tree of FsVerityDescriptor is incorrect"); + return builder->Build(); + } + int8_t reserve[FsVerityDescriptor::RESERVED_SIZE_AFTER_TREE_OFFSET]; + bf->GetByte(reserve, sizeof(reserve)); + int8_t inCsVersion; + bf->GetInt8(inCsVersion); + builder->SetSalt(inSalt).SetFlags(inFlags).SetMerkleTreeOffset(inTreeOffset).SetCsVersion(inCsVersion); + return builder->Build(); +} + +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(CODE_SIGN_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); + 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_descriptor_with_sign.cpp b/binary_sign_tool/codesigning/fsverity/src/fs_verity_descriptor_with_sign.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3032baf98e8b06b3ef857aca02e0aa4ad0de75f4 --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/src/fs_verity_descriptor_with_sign.cpp @@ -0,0 +1,74 @@ +/* + * 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_with_sign.h" + +namespace OHOS { +namespace SignatureTools { + +FsVerityDescriptorWithSign::FsVerityDescriptorWithSign() +{ +} + +FsVerityDescriptorWithSign::FsVerityDescriptorWithSign(FsVerityDescriptor fsVerityDescriptor, + const std::vector &signature) +{ + this->fsVerityDescriptor = fsVerityDescriptor; + if (!signature.empty()) { + this->signature = signature; + } + length = FsVerityDescriptor::DESCRIPTOR_SIZE + this->signature.size(); +} + +FsVerityDescriptorWithSign::FsVerityDescriptorWithSign(int32_t type, int32_t length, + FsVerityDescriptor fsVerityDescriptor, const std::vector &signature) +{ + this->type = type; + this->length = length; + this->fsVerityDescriptor = fsVerityDescriptor; + this->signature = signature; +} + +int32_t FsVerityDescriptorWithSign::Size() +{ + int tmpVariable = 2; + return INTEGER_BYTES * tmpVariable + FsVerityDescriptor::DESCRIPTOR_SIZE + signature.size(); +} + +void FsVerityDescriptorWithSign::ToByteArray(std::vector& ret) +{ + std::unique_ptr buffer = std::make_unique(Size()); + buffer->PutInt32(type); + buffer->PutInt32(length); + std::vector fsArr; + fsVerityDescriptor.ToByteArray(fsArr); + buffer->PutData(fsArr.data(), fsArr.size()); + buffer->PutData(signature.data(), signature.size()); + buffer->Flip(); + ret = std::vector(buffer->GetBufferPtr(), buffer->GetBufferPtr() + buffer->GetLimit()); + return; +} + +FsVerityDescriptor FsVerityDescriptorWithSign::GetFsVerityDescriptor() +{ + return fsVerityDescriptor; +} + +std::vector& FsVerityDescriptorWithSign::GetSignature() +{ + return signature; +} +} // namespace SignatureTools +} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/codesigning/fsverity/src/fs_verity_digest.cpp b/binary_sign_tool/codesigning/fsverity/src/fs_verity_digest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7494a081972743c92bdca90b32fd455a78f7643d --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/src/fs_verity_digest.cpp @@ -0,0 +1,49 @@ +/* + * 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 "securec.h" +#include "fs_verity_digest.h" +#include "signature_tools_log.h" + +namespace OHOS { +namespace SignatureTools { +const std::string FsVerityDigest::FSVERITY_DIGEST_MAGIC = "FSVerity"; +const int FsVerityDigest::DIGEST_HEADER_SIZE = 12; + +void FsVerityDigest::GetFsVerityDigest(int8_t algoID, std::vector& digest, + std::vector &ret) +{ + const int size = DIGEST_HEADER_SIZE + digest.size(); + if (size <= 0) { + ret = std::vector(); + return; + } + std::unique_ptr buffer = std::make_unique(ByteBuffer(size)); + buffer->PutData(FSVERITY_DIGEST_MAGIC.c_str(), (int32_t)FSVERITY_DIGEST_MAGIC.length()); + buffer->PutInt16(algoID); + buffer->PutInt16((int16_t)digest.size()); + buffer->PutData(digest.data(), digest.size()); + buffer->Flip(); + char dataArr[size]; + if (memset_s(dataArr, sizeof(dataArr), 0, sizeof(dataArr)) != RET_OK) { + SIGNATURE_TOOLS_LOGE("memcpy_s failed"); + ret = std::vector(); + return; + } + buffer->GetData(dataArr, size); + ret = std::vector(dataArr, dataArr + size); + return; +} +} // namespace SignatureTools +} // namespace OHOS 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..8090b0fe92a6dafea2c645f1dfaa50fa63ff6084 --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/src/fs_verity_generator.cpp @@ -0,0 +1,67 @@ +/* + * 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 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()); + return builder->GenerateMerkleTree(inputStream, size, fsVerityHashAlgorithm); +} + +bool FsVerityGenerator::GenerateFsVerityDigest(std::istream& inputStream, long size, long fsvTreeOffset) +{ + MerkleTree* merkleTree = GenerateMerkleTree(inputStream, size, FS_SHA256); + if (merkleTree == nullptr) { + return false; + } + int flags = 0; + std::shared_ptr merkleTree_ptr(merkleTree); + // sign size is 0, cs version 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); + std::vector fsVerityDescriptor; + builder->Build().GetByteForGenerateDigest(fsVerityDescriptor); + std::vector digest; + 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++) { + digest.push_back(result[i]); + } + FsVerityDigest::GetFsVerityDigest(FS_SHA256.GetId(), digest, 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/fs_verity_hash_algorithm.cpp b/binary_sign_tool/codesigning/fsverity/src/fs_verity_hash_algorithm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe0ec10d5af564c6712fddfb1ffdf0c73d52b895 --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/src/fs_verity_hash_algorithm.cpp @@ -0,0 +1,37 @@ +/* + * 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_hash_algorithm.h" + +namespace OHOS { +namespace SignatureTools { +const FsVerityHashAlgorithm FsVerityHashAlgorithm::SHA256((char)1, "SHA-256", 256 / 8); +const FsVerityHashAlgorithm FsVerityHashAlgorithm::SHA512((char)2, "SHA-512", 512 / 8); + +char FsVerityHashAlgorithm::GetId() const +{ + return id; +} + +const std::string& FsVerityHashAlgorithm::GetHashAlgorithm() const +{ + return hashAlgorithm; +} + +int FsVerityHashAlgorithm::GetOutputByteSize() const +{ + return outputByteSize; +} +} // 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..d39a97deeabc702fe59a849fbc56d85c000e3fee --- /dev/null +++ b/binary_sign_tool/codesigning/fsverity/src/merkle_tree_builder.cpp @@ -0,0 +1,296 @@ +/* + * 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 (int 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); + 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 (int i = 0; i < result.size(); i++) { + 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/codesigning/sign/include/bc_signeddata_generator.h b/binary_sign_tool/codesigning/sign/include/bc_signeddata_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..3619b4e90efc38410268b03cef9e49c4cb76dd1d --- /dev/null +++ b/binary_sign_tool/codesigning/sign/include/bc_signeddata_generator.h @@ -0,0 +1,59 @@ +/* + * 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_BC_SIGNEDDATA_GENERATOR_H +#define SIGNATRUETOOLS_BC_SIGNEDDATA_GENERATOR_H + +#include +#include +#include + +#include "openssl/x509.h" +#include "signeddata_generator.h" +#include "pkcs7_data.h" +#include "signer_config.h" +#include "signer.h" + +namespace OHOS { +namespace SignatureTools { + +class BCSignedDataGenerator : public SignedDataGenerator { +public: + /** + * Generate signature data with specific content and sign configuration. + * + * @param content unsigned file digest content. + * @param signerConfig sign configurations. + * @ret signed data. + * @return 0:success <0:error + */ + static int GetSigAlg(SignerConfig* signerConfig, std::string& sigAlg); + int GenerateSignedData(const std::string& content, SignerConfig* signerConfig, std::string& ret)override; + void SetOwnerId(const std::string& ownerID); + +private: + // @return 0(NID_undef) >0: success(new NID) + static int CreateNIDFromOID(const std::string& oid, const std::string& shortName, + const std::string& longName); + int PackageSignedData(const std::string& content, const std::shared_ptr& signer, + const std::string& sigAlg, std::string& ret); + // @return 0:success <0 :error + int AddOwnerID(std::vector& attrs, const std::string& ownerID); + +private: + std::string m_ownerID; +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATRUETOOLS_BC_SIGNEDDATA_GENERATOR_H \ No newline at end of file diff --git a/binary_sign_tool/hap/utils/include/hap_utils.h b/binary_sign_tool/codesigning/sign/include/code_signing.h similarity index 35% rename from binary_sign_tool/hap/utils/include/hap_utils.h rename to binary_sign_tool/codesigning/sign/include/code_signing.h index e0d0cd9e488b21ea46bfea87263a524d7facf367..9c1ec69f0a9b86fe7e8918954e61b3673310b209 100644 --- a/binary_sign_tool/hap/utils/include/hap_utils.h +++ b/binary_sign_tool/codesigning/sign/include/code_signing.h @@ -1,4 +1,4 @@ -/* +/* * 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. @@ -12,45 +12,50 @@ * 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_HAP_UTILS_H -#define SIGNATRUETOOLS_HAP_UTILS_H - -#include #include #include -#include -#include -#include +#include -#include "content_digest_algorithm.h" +#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 HapUtils { +class CodeSigning { 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; + CodeSigning(SignerConfig* signConfig); + CodeSigning(); + + bool SignFile(std::istream& inputStream, + int64_t fileSize, bool storeTree, + int64_t fsvTreeOffset, const std::string &ownerID); + bool GetElfCodeSignBlock(const std::string &input, int64_t offset, + const std::string &inForm, + std::vector &codesignData); + +public: + int64_t GetTimestamp(); + bool GenerateSignature(const std::vector& signedData, const std::string&, + std::vector&); + int64_t m_timestamp = 0; + std::vector m_extractedNativeLibSuffixs; + SignerConfig* m_signConfig; + std::mutex m_mutex; + +private: + static constexpr int MAX_PROCESSORS = 32; + const int POOL_SIZE = std::min(MAX_PROCESSORS, static_cast(std::thread::hardware_concurrency())); + std::shared_ptr mPools; }; } // namespace SignatureTools } // namespace OHOS -#endif +#endif // SIGNATURETOOLS_CODE_SIGNING_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/sign/include/signeddata_generator.h b/binary_sign_tool/codesigning/sign/include/signeddata_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..dd2b390eca0c97a443e3a99746971f9875e84a4d --- /dev/null +++ b/binary_sign_tool/codesigning/sign/include/signeddata_generator.h @@ -0,0 +1,40 @@ +/* + * 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_SIGNEDDATA_GENERATOR_H +#define SIGNATRUETOOLS_SIGNEDDATA_GENERATOR_H + +#include + +#include "signer_config.h" + +namespace OHOS { +namespace SignatureTools { + +class SignedDataGenerator { +public: + virtual ~SignedDataGenerator() = default; + /** + * Generate signature data with specific content and sign configuration. + * + * @param content unsigned file digest content. + * @param signerConfig sign configurations. + * @param ret signed data. + * @return 0:success <0:error + */ + virtual int GenerateSignedData(const std::string& content, SignerConfig* signerConfig, std::string& ret) = 0; +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATRUETOOLS_SIGNEDDATA_GENERATOR_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/sign/src/bc_signeddata_generator.cpp b/binary_sign_tool/codesigning/sign/src/bc_signeddata_generator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44c2fe98c729585a0fd5be96c7816db3fe267318 --- /dev/null +++ b/binary_sign_tool/codesigning/sign/src/bc_signeddata_generator.cpp @@ -0,0 +1,151 @@ +/* + * 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 "constant.h" +#include "pkcs7_data.h" +#include "local_signer.h" +#include "signer_config.h" +#include "signature_tools_log.h" +#include "signature_algorithm_helper.h" +#include "signature_tools_errno.h" +#include "bc_signeddata_generator.h" + +namespace OHOS { +namespace SignatureTools { + +int BCSignedDataGenerator::GenerateSignedData(const std::string& content, + SignerConfig* signerConfig, std::string& ret) +{ + std::string sigAlg; + int result = RET_OK; + if (content.empty()) { + PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, + "digest content is empty, generate signed data failed"); + return INVALIDPARAM_ERROR; + } + if (signerConfig == NULL) { + PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, + "signerConfig is NULL"); + return INVALIDPARAM_ERROR; + } + std::shared_ptr signer = signerConfig->GetSigner(); + if (signer == NULL) { + PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, + "signer is NULL"); + return INVALIDPARAM_ERROR; + } + result = GetSigAlg(signerConfig, sigAlg); + if (result < 0) { + SIGNATURE_TOOLS_LOGE("get sign algorithm from signerConfig failed"); + return INVALIDPARAM_ERROR; + } + result = PackageSignedData(content, signer, sigAlg, ret); + if (result < 0) { + SIGNATURE_TOOLS_LOGE("package signed data failed"); + return result; + } + return result; +} + +void BCSignedDataGenerator::SetOwnerId(const std::string& ownerID) +{ + m_ownerID = ownerID; +} + +int BCSignedDataGenerator::PackageSignedData(const std::string& content, const std::shared_ptr& signer, + const std::string& sigAlg, std::string& ret) +{ + int result = RET_OK; + PKCS7Data p7Data(PKCS7_DETACHED_FLAGS); + std::vector attrs; + if (m_ownerID.empty() == false) { + if (AddOwnerID(attrs, m_ownerID) < 0) { + PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, + "create ownerIDOid failed"); + return INVALIDPARAM_ERROR; + } + } + // Generate PKCS#7 + result = p7Data.Sign(content, signer, sigAlg, ret, attrs); + if (result < 0) { + SIGNATURE_TOOLS_LOGE("generate pkcs7 signed data block failed"); + return SIGN_ERROR; + } + // Verify after parsing + result = p7Data.Parse(ret); + if (result < 0) { + SIGNATURE_TOOLS_LOGE("verify pkcs7 signed data block bytes failed"); + return PARSE_ERROR; + } + result = p7Data.Verify(content); + if (result < 0) { + SIGNATURE_TOOLS_LOGE("verify pkcs7 signed data block failed"); + return VERIFY_ERROR; + } + return result; +} + +int BCSignedDataGenerator::GetSigAlg(SignerConfig* signerConfig, std::string& sigAlg) +{ + std::vector sigs = signerConfig->GetSignatureAlgorithms(); + if (sigs.size() != 1) { + PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "sigAlg count not equal to 1"); + return INVALIDPARAM_ERROR; + } + SignatureAlgorithmHelper signatureAlg = sigs[0]; + if (signatureAlg.m_id == SignatureAlgorithmId::ECDSA_WITH_SHA256) { + sigAlg = SIGN_ALG_SHA256; + } else if (signatureAlg.m_id == SignatureAlgorithmId::ECDSA_WITH_SHA384) { + sigAlg = SIGN_ALG_SHA384; + } else { + PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, + sigAlg + "is invalid sigAlg, please use SHA256withECDSA/SHA384withECDSA, sign failed"); + return NOT_SUPPORT_ERROR; + } + return RET_OK; +} + +int BCSignedDataGenerator::CreateNIDFromOID(const std::string& oid, const std::string& shortName, + const std::string& longName) +{ + int nid = OBJ_txt2nid(oid.c_str()); + if (nid == NID_undef) { + nid = OBJ_create(oid.c_str(), shortName.c_str(), longName.c_str()); + } + return nid; +} + +int BCSignedDataGenerator::AddOwnerID(std::vector& attrs, const std::string& ownerID) +{ + PKCS7Attr attr; + int nid = CreateNIDFromOID(OWNERID_OID, OWNERID_OID_SHORT_NAME, OWNERID_OID_LONG_NAME); + if (nid == NID_undef) { + return RET_FAILED; + } + ASN1_STRING* ownerIDAsn1 = ASN1_STRING_new(); + if (ownerIDAsn1 == NULL) { + SIGNATURE_TOOLS_LOGE("asn1 string create error!\n"); + return RET_FAILED; + } + ASN1_STRING_set(ownerIDAsn1, ownerID.c_str(), ownerID.length()); + attr.nid = nid; + attr.atrtype = V_ASN1_UTF8STRING; + attr.value = ownerIDAsn1; + attrs.push_back(attr); + return RET_OK; +} +} // namespace SignatureTools +} // namespace OHOS \ 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..c783f0f804f95d52a6b6ec5902f02607339caf89 --- /dev/null +++ b/binary_sign_tool/codesigning/sign/src/code_signing.cpp @@ -0,0 +1,145 @@ +/* + * 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; + +CodeSigning::CodeSigning(SignerConfig* signConfig) : mPools(new Uscript::ThreadPool(POOL_SIZE)) +{ + m_signConfig = signConfig; +} + +CodeSigning::CodeSigning() : mPools(new Uscript::ThreadPool(POOL_SIZE)) +{ +} + +int64_t CodeSigning::GetTimestamp() +{ + auto now = std::chrono::system_clock::now(); + auto nowSeconds = std::chrono::time_point_cast(now); + return nowSeconds.time_since_epoch().count(); +} + +bool CodeSigning::SignFile(std::istream& inputStream, int64_t fileSize, bool storeTree, + int64_t fsvTreeOffset, const std::string &ownerID) +{ + std::unique_ptr fsVerityGenerator = + std::make_unique(); + if (!fsVerityGenerator->GenerateFsVerityDigest(inputStream, fileSize, fsvTreeOffset)) { + SIGNATURE_TOOLS_LOGE("SignFile GenerateFsVerityDigest Fail"); + return false; + } + std::vector fsVerityDigest = fsVerityGenerator->GetFsVerityDigest(); + std::vector signature; + bool generateSignatureFlag = GenerateSignature(fsVerityDigest, ownerID, signature); + if (!generateSignatureFlag) { + SIGNATURE_TOOLS_LOGE("SignFile GenerateSignature Fail"); + return false; + } + + // int saltSize = fsVerityGenerator->GetSaltSize(); + // std::vector salt = fsVerityGenerator->GetSalt(); + // SignInfo signInfo(saltSize, flags, fileSize, salt, signature); + + return true; +} + +bool CodeSigning::GetElfCodeSignBlock(const std::string &input, int64_t offset, + const std::string &inForm, + 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; + } + std::streamsize fileSize = inputstream.tellg(); + inputstream.seekg(0, std::ios::beg); + std::unique_ptr fsVerityGenerator = std::make_unique(); + fsVerityGenerator->GenerateFsVerityDigest(inputstream, fileSize, 0); + std::vector fsVerityDigest = fsVerityGenerator->GetFsVerityDigest(); + std::vector signature; + bool generateSignatureFlag = GenerateSignature(fsVerityDigest, "ownerID", signature); + if (!generateSignatureFlag) { + SIGNATURE_TOOLS_LOGE("[SignElf] generate elf signature failed"); + return false; + } + + FsVerityDescriptor::Builder fsdbuilder; + fsdbuilder.SetFileSize(fileSize) + .SetHashAlgorithm(FS_SHA256.GetId()) + .SetLog2BlockSize(LOG_2_OF_FSVERITY_HASH_PAGE_SIZE) + .SetSaltSize(fsVerityGenerator->GetSaltSize()) + .SetSignSize(signature.size()) + .SetFileSize(fileSize) + .SetSalt(fsVerityGenerator->Getsalt()) + .SetRawRootHash(fsVerityGenerator->GetRootHash()) + .SetFlags(FsVerityDescriptor::FLAG_STORE_MERKLE_TREE_OFFSET) + .SetCsVersion(FsVerityDescriptor::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; +} +} // 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..0f4a6696245e50ad0260ca7032207603a7795fde --- /dev/null +++ b/binary_sign_tool/codesigning/signature_tools_codesigning.gni @@ -0,0 +1,32 @@ +# 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", +] + +signature_tools_codesigning_src = [ + "${signature_tools_codesigning}/fsverity/src/fs_verity_descriptor.cpp", + "${signature_tools_codesigning}/fsverity/src/fs_verity_digest.cpp", + "${signature_tools_codesigning}/fsverity/src/fs_verity_generator.cpp", + "${signature_tools_codesigning}/fsverity/src/fs_verity_hash_algorithm.cpp", + "${signature_tools_codesigning}/fsverity/src/merkle_tree_builder.cpp", + "${signature_tools_codesigning}/fsverity/src/fs_verity_descriptor_with_sign.cpp", + "${signature_tools_codesigning}/utils/src/fs_digest_utils.cpp", + "${signature_tools_codesigning}/utils/src/cms_utils.cpp", + "${signature_tools_codesigning}/sign/src/bc_signeddata_generator.cpp", + "${signature_tools_codesigning}/sign/src/code_signing.cpp", +] diff --git a/binary_sign_tool/codesigning/utils/include/cms_utils.h b/binary_sign_tool/codesigning/utils/include/cms_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..82d34abd95be18d0b3637f107b1eb2e08ff100e8 --- /dev/null +++ b/binary_sign_tool/codesigning/utils/include/cms_utils.h @@ -0,0 +1,40 @@ +/* + * 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_CMS_UTILS_H +#define SIGNATURETOOLS_CMS_UTILS_H + +#include +#include +#include + +#include "signature_tools_log.h" +#include "pkcs7_data.h" + +namespace OHOS { +namespace SignatureTools { +class CmsUtils { +public: + static bool VerifySignDataWithUnsignedDataDigest(const std::vector& unsignedDataDigest, + const std::vector& signedData); + static bool CheckOwnerID(const std::string& signature, const std::string& profileOwnerID, + const std::string& profileType); + static int CreateNIDFromOID(const std::string& oid, const std::string& shortName, + const std::string& longName); +private: + CmsUtils(); +}; +} // namespace SignatureTools +} // namespace OHOS +#endif // SIGNATURETOOLS_CMS_UTILS_H \ No newline at end of file diff --git a/binary_sign_tool/codesigning/utils/include/fs_digest_utils.h b/binary_sign_tool/codesigning/utils/include/fs_digest_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..4fd1a0384850a2953c4b63f2b63a69bf5407c5f5 --- /dev/null +++ b/binary_sign_tool/codesigning/utils/include/fs_digest_utils.h @@ -0,0 +1,55 @@ +/* + * 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_FS_DIGEST_UTILS_H +#define SIGNATURETOOLS_FS_DIGEST_UTILS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "signature_tools_log.h" + +using hashFunc = const EVP_MD* (*)(void); + +enum HashType { + HASH_SHA256, + HASH_SHA384 +}; + +class DigestUtils { +public: + enum class Type :char { + BINARY, HEX + }; + explicit DigestUtils(HashType type); + ~DigestUtils(); + void AddData(const std::string &data); + void AddData(const char* data, int length); + std::string Result(Type type = Type::HEX); + +private: + EVP_MD_CTX* m_ctx = NULL; + HashType m_type; +}; +#endif // SIGNATURETOOLS_FS_DIGEST_UTILS_H diff --git a/binary_sign_tool/codesigning/utils/src/cms_utils.cpp b/binary_sign_tool/codesigning/utils/src/cms_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3fd77745a60a80004898b418baed815a60d5a115 --- /dev/null +++ b/binary_sign_tool/codesigning/utils/src/cms_utils.cpp @@ -0,0 +1,105 @@ +/* + * 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 "cms_utils.h" +#include "bc_signeddata_generator.h" +#include "constant.h" + +namespace OHOS { +namespace SignatureTools { + +bool CmsUtils::VerifySignDataWithUnsignedDataDigest(const std::vector& unsignedDataDigest, + const std::vector& signedData) +{ + int ret = 0; + std::string unsignedDataDigest_(unsignedDataDigest.begin(), unsignedDataDigest.end()); + PKCS7Data p7Data(PKCS7_DETACHED_FLAGS); + ret = p7Data.Parse(signedData); + if (ret < 0) { + SIGNATURE_TOOLS_LOGE("verify pkcs7 signed data block bytes failed"); + return false; + } + ret = p7Data.Verify(unsignedDataDigest_); + if (ret < 0) { + SIGNATURE_TOOLS_LOGE("verify pkcs7 signed datablock failed"); + return false; + } + return true; +} + +bool CmsUtils::CheckOwnerID(const std::string& signature, const std::string& profileOwnerID, + const std::string& profileType) +{ + std::string ownerID = profileOwnerID; + if (DEBUG_STR == profileType) ownerID = DEBUG_LIB_ID; + int nid = CreateNIDFromOID(OWNERID_OID, OWNERID_OID_SHORT_NAME, OWNERID_OID_LONG_NAME); + const unsigned char* data = reinterpret_cast(signature.c_str()); + PKCS7* p7 = d2i_PKCS7(NULL, &data, static_cast(signature.size())); + if (p7 == nullptr) { + PrintErrorNumberMsg("PARSE_ERROR", PARSE_ERROR, "invalid data, parse pkcs7 failed"); + return false; + } + STACK_OF(PKCS7_SIGNER_INFO)* signerInfosk = PKCS7_get_signer_info(p7); + if (signerInfosk == nullptr) { + PKCS7_free(p7); + PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "can't get signerinfo from pkcs7"); + return true; + } + for (int i = 0; i < sk_PKCS7_SIGNER_INFO_num(signerInfosk); i++) { + PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(signerInfosk, i); + ASN1_TYPE* asn1Type = PKCS7_get_signed_attribute(signerInfo, nid); + if (asn1Type == nullptr) { + if (DEBUG_STR == profileType) + continue; + if (ownerID.empty()) { + continue; + } else { + PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "app-identifier is not in the signature"); + PKCS7_free(p7); + return false; + } + } + if (ownerID.empty()) { + PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "app-identifier in profile is null,in signature exist"); + PKCS7_free(p7); + return false; + } + if (asn1Type->type == V_ASN1_UTF8STRING) { + ASN1_STRING* result = asn1Type->value.asn1_string; + std::string result_ownerID; + result_ownerID.assign(reinterpret_cast(ASN1_STRING_get0_data(result)), + ASN1_STRING_length(result)); + if (ownerID != result_ownerID) { + PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "app-identifier in signature is invalid"); + PKCS7_free(p7); + return false; + } + } + } + PKCS7_free(p7); + return true; +} + +int CmsUtils::CreateNIDFromOID(const std::string& oid, const std::string& shortName, + const std::string& longName) +{ + int nid = OBJ_txt2nid(oid.c_str()); + if (nid == NID_undef) { + nid = OBJ_create(oid.c_str(), shortName.c_str(), longName.c_str()); + } + return nid; +} +} // namespace SignatureTools +} // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/codesigning/utils/src/fs_digest_utils.cpp b/binary_sign_tool/codesigning/utils/src/fs_digest_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea4e589338b77626e6364a276c24571166e0cfca --- /dev/null +++ b/binary_sign_tool/codesigning/utils/src/fs_digest_utils.cpp @@ -0,0 +1,84 @@ +/* + * 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_digest_utils.h" +#include "securec.h" + +void DigestUtils::AddData(const std::string &data) +{ + AddData(data.data(), (int)data.size()); +} + +void DigestUtils::AddData(const char* data, int length) +{ + int ret = EVP_DigestUpdate(m_ctx, data, length); + if (ret < 1) { + printf("Update DigestFunc failed!\n"); + } +} + +std::string DigestUtils::Result(DigestUtils::Type type) +{ + unsigned int len = 0; + + const std::map hashLength = { + {HASH_SHA256, SHA256_DIGEST_LENGTH}, + {HASH_SHA384, SHA384_DIGEST_LENGTH}, + }; + + unsigned char* md = reinterpret_cast(new char[hashLength.at(m_type)]); + int ret = EVP_DigestFinal_ex(m_ctx, md, &len); + if (ret < 1) { + printf("Failed to Calculate Hash Relsult\n"); + } + int temporaryVariableFirst = 2; + if (type == Type::HEX) { + int temporaryVariableSecond = 3; + char* res = new char[len * temporaryVariableFirst + 1]; + for (unsigned int i = 0; i < len; i++) { + snprintf_s(&res[i * temporaryVariableFirst], temporaryVariableSecond, + temporaryVariableFirst, "%02x", md[i]); + } + std::string st{res, len * temporaryVariableFirst}; + delete[]md; + delete[]res; + return st; + } + std::string st{reinterpret_cast(md), len}; + delete[]md; + return st; +} + +DigestUtils::DigestUtils(HashType type) +{ + m_type = type; + m_ctx = EVP_MD_CTX_new(); + + const std::map hashMethods = { + {HASH_SHA256, EVP_sha256}, + {HASH_SHA384, EVP_sha384} + }; + + int ret = EVP_DigestInit_ex(m_ctx, hashMethods.at(type)(), nullptr); + if (ret < 1) { + printf("Init DigestFunc failed!\n"); + } +} + +DigestUtils::~DigestUtils() +{ + if (m_ctx != nullptr) { + EVP_MD_CTX_free(m_ctx); + } +} \ No newline at end of file diff --git a/binary_sign_tool/common/include/constant.h b/binary_sign_tool/common/include/constant.h index e7154c0d2a519503d9c87cb2865f920e35b51a1f..7f178b24e564f7dd2690be2e258a157bd776ca48 100644 --- a/binary_sign_tool/common/include/constant.h +++ b/binary_sign_tool/common/include/constant.h @@ -21,8 +21,6 @@ namespace OHOS { namespace SignatureTools { -const char APP_SIGNING_CAPABILITY[] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x0A, 0x01, 0x00}; -const char PROFILE_SIGNING_CAPABILITY[] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x0A, 0x01, 0x01}; constexpr long DEFAULT_START_VALIDITY = 0; constexpr long ONE_DAY_TIME = 86400; @@ -32,22 +30,16 @@ constexpr int NIST_P_256 = 256; constexpr int NIST_P_384 = 384; constexpr int DEFAULT_VALIDITY_DAYS = 3650; constexpr int INVALIDCHAR = 3; -constexpr int DEFAULT_BASIC_CONSTRAINTS_PATH_LEN = 0; constexpr int RANDOM_SERIAL_NUMBER_LENGTH = 32; constexpr int DEFAULT_CUSTOM_VALIDITY_DAYS = 1095; const bool DEFAULT_KEY_USAGE_CRITICAL = true; const bool DEFAULT_EXT_KEY_USAGE_CRITICAL = false; -const bool DEFAULT_BASIC_CONSTRAINTS = false; -const bool DEFAULT_BASIC_CONSTRAINTS_CRITICAL = false; -const bool DEFAULT_BASIC_CONSTRAINTS_CA = false; - const std::string SIGN_ALG_SHA256 = "SHA256withECDSA"; const std::string SIGN_ALG_SHA384 = "SHA384withECDSA"; const std::string DEFAULT_BASIC_EXTENSION = "critical,CA:FALSE"; const std::string DEFAULT_KEYUSAGE_EXTENSION = "digitalSignature"; const std::string DEFAULT_EXTEND_KEYUSAGE = "codeSigning"; -const std::string NID_BASIC_CONST = "basicConstraints"; const std::string NID_KEYUSAGE_CONST = "keyUsage"; const std::string NID_EXT_KEYUSAGE_CONST = "extendedKeyUsage"; const std::string PKCS7_EXT_SIGNATURE_OID = "1.2.840.113549.1.1.10"; @@ -57,7 +49,6 @@ const std::string OWNERID_OID_SHORT_NAME = "ownerID"; const std::string OWNERID_OID_LONG_NAME = "Code Signature Owner ID"; const std::string DEFAULT_PROFILE_SIGNED_1 = "1"; const std::string DEFAULT_PROFILE_SIGNED_0 = "0"; -const std::string ZIP = "zip"; const std::string ELF = "elf"; const std::string BIN = "bin"; const std::string OUT_FORM_CERT = "cert"; @@ -75,9 +66,6 @@ const std::string GENERATE_CERT = "generate-cert"; const std::string GENERATE_APP_CERT = "generate-app-cert"; const std::string GENERATE_PROFILE_CERT = "generate-profile-cert"; const std::string SIGN_ELF = "sign"; -const std::string SIGN_PROFILE = "sign-profile"; -const std::string VERIFY_APP = "verify-app"; -const std::string VERIFY_PROFILE = "verify-profile"; constexpr int32_t ONE_DAY_HOUR = 24; constexpr int32_t ONE_DAY_MINUTE = 60; diff --git a/binary_sign_tool/common/include/digest_common.h b/binary_sign_tool/common/include/digest_common.h index 20f7645c7c14bcb344c84f1615c2c783954f7021..d11ea9d94bb04513ad34fc80a4ac9f781dacd864 100644 --- a/binary_sign_tool/common/include/digest_common.h +++ b/binary_sign_tool/common/include/digest_common.h @@ -22,7 +22,6 @@ #include "openssl/ossl_typ.h" #include "digest_parameter.h" #include "pkcs7_context.h" -#include "signature_info.h" #include "export_define.h" #include "openssl/pkcs7.h" #include "openssl/safestack.h" @@ -43,12 +42,9 @@ class DigestCommon { public: DigestCommon() = delete; - static int32_t GetDigest(const ByteBuffer& chunk, const std::vector& optionalBlocks, - const DigestParameter& digestParameter, unsigned char(&out)[EVP_MAX_MD_SIZE]); static bool DigestInit(const DigestParameter& digestParameter); static bool DigestUpdate(const DigestParameter& digestParameter, const unsigned char content[], int32_t len); - static int32_t GetDigest(const DigestParameter& digestParameter, unsigned char(&out)[EVP_MAX_MD_SIZE]); static int32_t GetDigestAlgorithmOutputSizeBytes(int32_t nId); DLL_EXPORT static int32_t GetDigestAlgorithmId(int32_t signAlgorithm); static std::string GetDigestAlgorithmString(int32_t signAlgorithm); diff --git a/binary_sign_tool/common/include/options.h b/binary_sign_tool/common/include/options.h index 625fd8f775321125a4b8acdcfe9f88030653deda..c8dad6ee2d98c9b319e8c83669d53ce335ce5ca5 100644 --- a/binary_sign_tool/common/include/options.h +++ b/binary_sign_tool/common/include/options.h @@ -84,9 +84,6 @@ public: /* signature algorithm. */ static const std::string SIGN_ALG; - /* length of path. */ - static const std::string BASIC_CONSTRAINTS_PATH_LEN; - /* outfile. */ static const std::string OUT_FILE; @@ -107,16 +104,12 @@ public: static const std::string EXT_KEY_USAGE; static const std::string KEY_USAGE_CRITICAL; static const std::string EXT_KEY_USAGE_CRITICAL; - static const std::string BASIC_CONSTRAINTS; - static const std::string BASIC_CONSTRAINTS_CRITICAL; - static const std::string BASIC_CONSTRAINTS_CA; /* Out form includes all forms. */ static const std::string OUT_FORM_SCOPE; static const std::string MODE; static const std::string OUT_CERT_CHAIN; static const std::string OUT_PROFILE; - static const std::string PROOF_FILE; static const std::string PROFILE_FILE; static const std::string PROFILE_SIGNED; static const std::string MODULE_FILE; diff --git a/binary_sign_tool/common/include/signature_tools_errno.h b/binary_sign_tool/common/include/signature_tools_errno.h index cabcc5eb0c9af38e6e09fc4d01bf1a9bfc08bb28..9d0be88c30e25621d64da0facc21a0ae14ea6003 100644 --- a/binary_sign_tool/common/include/signature_tools_errno.h +++ b/binary_sign_tool/common/include/signature_tools_errno.h @@ -58,10 +58,6 @@ const int KEY_ALIAS_ERROR = -109; * Enum constant INVALID_ERROR. */ const int INVALIDPARAM_ERROR = -110; -/** - * Enum constant ZIP_ERROR. - */ -const int ZIP_ERROR = -111; /** * Enum constant FORMAT_ERROR. */ diff --git a/binary_sign_tool/common/src/digest_common.cpp b/binary_sign_tool/common/src/digest_common.cpp index 36a694b9ba09e3abd0b173e4af03b83f26636a53..74504d767551a7deef1284c01b7bd54aee9af265 100644 --- a/binary_sign_tool/common/src/digest_common.cpp +++ b/binary_sign_tool/common/src/digest_common.cpp @@ -70,63 +70,6 @@ bool DigestCommon::DigestUpdate(const DigestParameter& digestParameter, return true; } -int32_t DigestCommon::GetDigest(const DigestParameter& digestParameter, - unsigned char(&out)[EVP_MAX_MD_SIZE]) -{ - uint32_t outLen = 0; - if (!CheckDigestParameter(digestParameter)) { - return outLen; - } - if (EVP_DigestFinal(digestParameter.ctxPtr, out, &outLen) <= 0) { - GetOpensslErrorMessage(); - SIGNATURE_TOOLS_LOGE("EVP_DigestFinal failed"); - outLen = 0; - } - return outLen; -} - -int32_t DigestCommon::GetDigest(const ByteBuffer& chunk, - const std::vector& optionalBlocks, - const DigestParameter& digestParameter, - unsigned char(&out)[EVP_MAX_MD_SIZE]) -{ - int32_t chunkLen = chunk.Remaining(); - uint32_t outLen = 0; - if (digestParameter.md == nullptr) { - SIGNATURE_TOOLS_LOGE("md is nullprt"); - return outLen; - } - if (digestParameter.ctxPtr == nullptr) { - SIGNATURE_TOOLS_LOGE("ctxPtr is nullprt"); - return outLen; - } - if (EVP_DigestInit(digestParameter.ctxPtr, digestParameter.md) <= 0) { - GetOpensslErrorMessage(); - SIGNATURE_TOOLS_LOGE("EVP_DigestInit failed"); - return outLen; - } - if (EVP_DigestUpdate(digestParameter.ctxPtr, chunk.GetBufferPtr(), chunkLen) <= 0) { - GetOpensslErrorMessage(); - SIGNATURE_TOOLS_LOGE("EVP_DigestUpdate chunk failed"); - return outLen; - } - for (int32_t i = 0; i < static_cast(optionalBlocks.size()); i++) { - chunkLen = optionalBlocks[i].optionalBlockValue.GetCapacity(); - if (EVP_DigestUpdate(digestParameter.ctxPtr, optionalBlocks[i].optionalBlockValue.GetBufferPtr(), - chunkLen) <= 0) { - GetOpensslErrorMessage(); - SIGNATURE_TOOLS_LOGE("EVP_DigestUpdate %dst optional block failed", i); - return outLen; - } - } - if (EVP_DigestFinal(digestParameter.ctxPtr, out, &outLen) <= 0) { - GetOpensslErrorMessage(); - SIGNATURE_TOOLS_LOGE("EVP_DigestFinal failed"); - outLen = 0; - } - return outLen; -} - void DigestCommon::GetOpensslErrorMessage() { unsigned long retOpenssl; diff --git a/binary_sign_tool/common/src/localization_adapter.cpp b/binary_sign_tool/common/src/localization_adapter.cpp index edb38cdc733ab6e2bc1c3befa578fa4faa3c85b8..c1f8718a13cc8cf6a7e0c53cb6cb77cb817b71fa 100644 --- a/binary_sign_tool/common/src/localization_adapter.cpp +++ b/binary_sign_tool/common/src/localization_adapter.cpp @@ -257,7 +257,7 @@ const std::string LocalizationAdapter::GetOutFile() std::vector LocalizationAdapter::GetCertsFromFile(std::string& certPath, const std::string& logTitle) { - SIGNATURE_TOOLS_LOGD("outPutPath = %s , logTitle = %s", certPath.c_str(), logTitle.c_str()); + SIGNATURE_TOOLS_LOGD("certPath = %s , logTitle = %s", certPath.c_str(), logTitle.c_str()); std::vector certs; if (certPath.empty()) { SIGNATURE_TOOLS_LOGE("cert path not exist!"); diff --git a/binary_sign_tool/common/src/options.cpp b/binary_sign_tool/common/src/options.cpp index a3f7d7dd57d6b93cf9cb7223c292aa2fe7bb69d2..92df7fe43f9437ec455cc346a1add5f192c45f06 100644 --- a/binary_sign_tool/common/src/options.cpp +++ b/binary_sign_tool/common/src/options.cpp @@ -33,7 +33,6 @@ const std::string Options::ISSUER = "issuer"; const std::string Options::SUBJECT = "subject"; const std::string Options::VALIDITY = "validity"; const std::string Options::SIGN_ALG = "signAlg"; -const std::string Options::BASIC_CONSTRAINTS_PATH_LEN = "basicConstraintsPathLen"; const std::string Options::OUT_FILE = "outFile"; const std::string Options::OUT_FORM = "outForm"; const std::string Options::SUB_CA_CERT_FILE = "subCaCertFile"; @@ -45,15 +44,11 @@ const std::string Options::KEY_USAGE = "keyUsage"; const std::string Options::EXT_KEY_USAGE = "extKeyUsage"; const std::string Options::KEY_USAGE_CRITICAL = "keyUsageCritical"; const std::string Options::EXT_KEY_USAGE_CRITICAL = "extKeyUsageCritical"; -const std::string Options::BASIC_CONSTRAINTS_CA = "basicConstraintsCa"; -const std::string Options::BASIC_CONSTRAINTS_CRITICAL = "basicConstraintsCritical"; -const std::string Options::BASIC_CONSTRAINTS = "basicConstraints"; const std::string Options::OUT_FORM_SCOPE = "cert,certChain"; const std::string Options::MODE = "mode"; const std::string Options::INFORM = "inForm"; const std::string Options::OUT_CERT_CHAIN = "outCertChain"; const std::string Options::OUT_PROFILE = "outProfile"; -const std::string Options::PROOF_FILE = "outproof"; const std::string Options::PROFILE_FILE = "profileFile"; const std::string Options::PROFILE_SIGNED = "profileSigned"; const std::string Options::MODULE_FILE = "moduleFile"; diff --git a/binary_sign_tool/hap/entity/include/param_constants.h b/binary_sign_tool/hap/entity/include/param_constants.h index 2afcc11332215a30540cecbdd4b7ab4786786b03..20b86094d9b3833efdd957df97e975ecd89ecdb6 100644 --- a/binary_sign_tool/hap/entity/include/param_constants.h +++ b/binary_sign_tool/hap/entity/include/param_constants.h @@ -33,10 +33,8 @@ public: static const std::string ALIGNMENT; static const std::string PARAM_SIGN_MODE; static const std::string PARAM_BASIC_CRL; - static const std::string PARAM_BASIC_PROPERTY; static const std::string PARAM_BASIC_PROFILE; static const std::string PARAM_PROFILE_JSON_CONTENT; - static const std::string PARAM_BASIC_PROOF; static const std::string PARAM_BASIC_ALIGNMENT; static const std::string PARAM_BASIC_PRIVATE_KEY; static const std::string PARAM_BASIC_INPUT_FILE; @@ -56,8 +54,6 @@ public: static const std::string PARAM_LOCAL_PUBLIC_CERT; static const std::string PARAM_VERIFY_CERTCHAIN_FILE; static const std::string PARAM_VERIFY_PROFILE_FILE; - static const std::string PARAM_VERIFY_PROOF_FILE; - static const std::string PARAM_VERIFY_PROPERTY_FILE; static const std::string PARAM_RESIGN_CONFIG_FILE; static const std::string PARAM_IN_FORM; static const std::string PARAM_SIGN_CODE; diff --git a/binary_sign_tool/hap/entity/src/param_constants.cpp b/binary_sign_tool/hap/entity/src/param_constants.cpp index fe48cf053dc094b83bd11549995a98abf1dda71d..6bf63154e9b9dff06bf49f38ef85aa01cece1bf4 100644 --- a/binary_sign_tool/hap/entity/src/param_constants.cpp +++ b/binary_sign_tool/hap/entity/src/param_constants.cpp @@ -25,10 +25,8 @@ const std::string ParamConstants::HAP_SIG_ALGORITHM_SHA512_ECDSA = "SHA512withEC const std::string ParamConstants::ALIGNMENT = "4"; const std::string ParamConstants::PARAM_SIGN_MODE = "mode"; const std::string ParamConstants::PARAM_BASIC_CRL = "crl"; -const std::string ParamConstants::PARAM_BASIC_PROPERTY = "property"; const std::string ParamConstants::PARAM_BASIC_PROFILE = "profileFile"; const std::string ParamConstants::PARAM_PROFILE_JSON_CONTENT = "profileContent"; -const std::string ParamConstants::PARAM_BASIC_PROOF = "proof"; const std::string ParamConstants::PARAM_BASIC_ALIGNMENT = "a"; const std::string ParamConstants::PARAM_BASIC_PRIVATE_KEY = "keyAlias"; const std::string ParamConstants::PARAM_BASIC_INPUT_FILE = "inFile"; @@ -48,8 +46,6 @@ const std::string ParamConstants::PARAM_LOCAL_JKS_KEYALIAS_CODE = "keyPwd"; const std::string ParamConstants::PARAM_LOCAL_PUBLIC_CERT = "appCertFile"; const std::string ParamConstants::PARAM_VERIFY_CERTCHAIN_FILE = "outCertChain"; const std::string ParamConstants::PARAM_VERIFY_PROFILE_FILE = "outProfile"; -const std::string ParamConstants::PARAM_VERIFY_PROOF_FILE = "outproof"; -const std::string ParamConstants::PARAM_VERIFY_PROPERTY_FILE = "outproperty"; const std::string ParamConstants::PARAM_RESIGN_CONFIG_FILE = "resignconfig"; const std::string ParamConstants::PARAM_IN_FORM = "inForm"; const std::string ParamConstants::PARAM_SIGN_CODE = "signCode"; diff --git a/binary_sign_tool/hap/provider/include/sign_provider.h b/binary_sign_tool/hap/provider/include/sign_provider.h index 3f3e08b27bb577e83837ec05588145cd8832e738..2a5d0d06f3de6daed36a77c06e3b6e14e83e134d 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 { @@ -58,23 +56,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 +72,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/provider/src/sign_provider.cpp b/binary_sign_tool/hap/provider/src/sign_provider.cpp index 35ff929ac76402a56051a1c3cc1d3ea086cc97e7..4c5606ec62de012c14589ea93ff27bd93886c870 100644 --- a/binary_sign_tool/hap/provider/src/sign_provider.cpp +++ b/binary_sign_tool/hap/provider/src/sign_provider.cpp @@ -57,6 +57,7 @@ bool SignProvider::SignElf(Options* options) } SignerConfig signerConfig; if (!InitSigerConfig(signerConfig, publicCerts, options)) { + sk_X509_pop_free(publicCerts, X509_free); SIGNATURE_TOOLS_LOGE("SignElf] create Signer Configs failed"); return false; } @@ -96,64 +97,11 @@ 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; @@ -168,18 +116,12 @@ int SignProvider::GetX509Certificates(Options* options, STACK_OF(X509)** X509Vec 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 +193,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); @@ -356,21 +296,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..2e89c42bd00fe482dab1088aaa2f7b488a4b9d12 100644 --- a/binary_sign_tool/hap/sign/include/sign_elf.h +++ b/binary_sign_tool/hap/sign/include/sign_elf.h @@ -28,26 +28,24 @@ 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); + 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 c93feaecf1f2c0713e9e5be5e521f27519fa31fc..2a198b671b58d727c89223698f8b04a7ea8ddb51 100644 --- a/binary_sign_tool/hap/sign/src/sign_elf.cpp +++ b/binary_sign_tool/hap/sign/src/sign_elf.cpp @@ -20,15 +20,16 @@ #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::profileSec = ".profile"; const std::string SignElf::permissionSec = ".permission"; +const std::string SignElf::codesignSec = ".codesign"; bool SignElf::Sign(SignerConfig& signerConfig, std::map& signParams) { @@ -44,15 +45,16 @@ bool SignElf::Sign(SignerConfig& signerConfig, std::map 0 and 4K alignment + GenerateCodeSignByte(signerConfig, tmpOutputFile, csOffset); + + return FileUtils::CopyTmpFileAndDel(tmpOutputFile, outputFile); } bool SignElf::loadModule(std::map& signParams, std::string& moduleContent) @@ -109,45 +111,44 @@ 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; } - - 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 + sec->set_type(ELFIO::SHT_PROGBITS); + sec->set_flags(ELFIO::SHF_ALLOC); + sec->set_addr_align(1); + char codesignData[PAGE_SIZE]; + sec->set_data(codesignData, PAGE_SIZE); + 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; + // Allocate 4K of sec + ELFIO::Elf64_Off secOff = sec->get_offset(); + csOffset = secOff; + int64_t addLen = PAGE_SIZE - (secOff % PAGE_SIZE); + if (addLen != PAGE_SIZE) { + csOffset += addLen; + char addData[addLen]; + sec->append_data(addData, addLen); + if (!reader.save(outputFile)) { + SIGNATURE_TOOLS_LOGE("[SignElf] Failed to add %ld data to .codesign section", addLen); + return false; + } + } + PrintMsg("add codesign to ELF file success"); + SIGNATURE_TOOLS_LOGD("[SignElf] .codesign section offset: %ld, size: %ld", secOff, sec->get_size()); return true; } @@ -195,5 +196,48 @@ bool SignElf::WriteSecDataToFile(ELFIO::elfio& reader, SignerConfig& signerConfi PrintMsg("add permission to ELF file success"); return true; } + +bool SignElf::GenerateCodeSignByte(SignerConfig& signerConfig, const std::string &inputFile, uint64_t& csOffset) +{ + CodeSigning codeSigning(&signerConfig); + std::vector codesignData; + bool getElfCodeSignBlockFlag = codeSigning.GetElfCodeSignBlock(inputFile, 0, "elf", codesignData); + if (!getElfCodeSignBlockFlag) { + SIGNATURE_TOOLS_LOGE("[SignElf] get elf code sign block error."); + return false; + } + SIGNATURE_TOOLS_LOGD("[SignElf] elf code sign block off %ld: ,len: %ld .", csOffset, codesignData.size()); + + if (!ReplaceDataOffset(inputFile, csOffset, codesignData)) { + SIGNATURE_TOOLS_LOGE("[SignElf] Failed to replace code sign data in file."); + return false; + } + PrintMsg("write code sign data to ELF file 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: %ld", csOffset); + return false; + } + + fileStream.write(reinterpret_cast(csData.data()), csData.size()); + if (!fileStream) { + SIGNATURE_TOOLS_LOGE("[SignElf] Failed to write data at offset: %ld", csOffset); + return false; + } + + fileStream.close(); + return true; +} } // namespace SignatureTools } // namespace OHOS \ No newline at end of file diff --git a/binary_sign_tool/signature_tools.gni b/binary_sign_tool/signature_tools.gni index b43efcc1b98fdad21667249eb63d2fe7002dd1d2..cc8f2d3729b462213528f25ba9c42777d68835fe 100644 --- a/binary_sign_tool/signature_tools.gni +++ b/binary_sign_tool/signature_tools.gni @@ -15,7 +15,7 @@ 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" diff --git a/binary_sign_tool/utils/include/file_utils.h b/binary_sign_tool/utils/include/file_utils.h index 28b4a8bd90f427de5422abbeea771b85d7f7f6dc..421ea1cb4402df68c6b75dbf9b9731d9b69cf7e6 100644 --- a/binary_sign_tool/utils/include/file_utils.h +++ b/binary_sign_tool/utils/include/file_utils.h @@ -33,7 +33,6 @@ public: static const int NUM_TWO; static const int NUM_THREE; static const int NUM_FOUR; - static const std::string LIBS_PATH_PREFIX; static constexpr int FILE_BUFFER_BLOCK = 1024 * 1024; FileUtils() = delete; // judge is or not empty @@ -115,7 +114,6 @@ public: * @param name filename * @return boolean */ - static bool IsRunnableFile(const std::string& name); static int64_t GetFileLen(const std::string& file); static void DelDir(const std::string& file); static bool CopyTmpFileAndDel(const std::string& tmpFile, const std::string& output); diff --git a/binary_sign_tool/utils/src/file_utils.cpp b/binary_sign_tool/utils/src/file_utils.cpp index 24ed0f972039846dd2a32cf88071939f97f8306a..bb1a1fa5a4b5acae970915b6b288c9dd579160a0 100644 --- a/binary_sign_tool/utils/src/file_utils.cpp +++ b/binary_sign_tool/utils/src/file_utils.cpp @@ -28,7 +28,6 @@ namespace SignatureTools { const int FileUtils::NUM_TWO = 2; const int FileUtils::NUM_THREE = 3; const int FileUtils::NUM_FOUR = 4; -const std::string FileUtils::LIBS_PATH_PREFIX = "libs/"; const char ELF_MAGIC[] = { '\x7f', 'E', 'L', 'F' }; bool FileUtils::IsEmpty(std::string cs) { @@ -280,26 +279,6 @@ bool FileUtils::WriteInputToOutPut(const std::string& input, const std::string& return true; } -bool FileUtils::IsRunnableFile(const std::string& name) -{ - if (name.empty()) { - return false; - } - size_t dotPos = name.rfind('.'); - if (dotPos == std::string::npos) { - return false; - } - std::string suffix = name.substr(dotPos + 1); - if (suffix == "an" || suffix == "abc") { - return true; - } - std::string libDir = name.substr(0, LIBS_PATH_PREFIX.size()); - if (LIBS_PATH_PREFIX.compare(libDir) == 0) { - return true; - } - return false; -} - bool FileUtils::IsValidFile(std::string file) { std::filesystem::path filePath = file;