154aa6d63Sopenharmony_ci/* 254aa6d63Sopenharmony_ci * Copyright (c) 2024-2024 Huawei Device Co., Ltd. 354aa6d63Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 454aa6d63Sopenharmony_ci * you may not use this file except in compliance with the License. 554aa6d63Sopenharmony_ci * You may obtain a copy of the License at 654aa6d63Sopenharmony_ci * 754aa6d63Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 854aa6d63Sopenharmony_ci * 954aa6d63Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1054aa6d63Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1154aa6d63Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1254aa6d63Sopenharmony_ci * See the License for the specific language governing permissions and 1354aa6d63Sopenharmony_ci * limitations under the License. 1454aa6d63Sopenharmony_ci */ 1554aa6d63Sopenharmony_ci 1654aa6d63Sopenharmony_ci#include "sign_bin.h" 1754aa6d63Sopenharmony_ci#include "param_constants.h" 1854aa6d63Sopenharmony_ci#include "file_utils.h" 1954aa6d63Sopenharmony_ci#include "block_head.h" 2054aa6d63Sopenharmony_ci#include "signature_block_types.h" 2154aa6d63Sopenharmony_ci#include "signature_block_tags.h" 2254aa6d63Sopenharmony_ci#include "hash_utils.h" 2354aa6d63Sopenharmony_ci#include "sign_content_info.h" 2454aa6d63Sopenharmony_ci#include "sign_head.h" 2554aa6d63Sopenharmony_ci#include "bc_pkcs7_generator.h" 2654aa6d63Sopenharmony_ci#include "params.h" 2754aa6d63Sopenharmony_ci 2854aa6d63Sopenharmony_cinamespace OHOS { 2954aa6d63Sopenharmony_cinamespace SignatureTools { 3054aa6d63Sopenharmony_ci 3154aa6d63Sopenharmony_cibool SignBin::Sign(SignerConfig& signerConfig, const std::map<std::string, std::string>& signParams) 3254aa6d63Sopenharmony_ci{ 3354aa6d63Sopenharmony_ci /* 1. Make block head, write to output file. */ 3454aa6d63Sopenharmony_ci std::string signCode = signParams.at(ParamConstants::PARAM_SIGN_CODE); 3554aa6d63Sopenharmony_ci if (ParamConstants::ENABLE_SIGN_CODE == signCode) { 3654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGW("can not sign bin with codesign.\n"); 3754aa6d63Sopenharmony_ci } 3854aa6d63Sopenharmony_ci std::string inputFile = signParams.at(ParamConstants::PARAM_BASIC_INPUT_FILE); 3954aa6d63Sopenharmony_ci std::string outputFile = signParams.at(ParamConstants::PARAM_BASIC_OUTPUT_FILE); 4054aa6d63Sopenharmony_ci std::string profileFile = signParams.at(ParamConstants::PARAM_BASIC_PROFILE); 4154aa6d63Sopenharmony_ci std::string profileSigned = signParams.at(ParamConstants::PARAM_BASIC_PROFILE_SIGNED); 4254aa6d63Sopenharmony_ci bool writeBlockOk = WriteBlockDataToFile(inputFile, outputFile, profileFile, profileSigned); 4354aa6d63Sopenharmony_ci if (!writeBlockOk) { 4454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("The block head data made failed."); 4554aa6d63Sopenharmony_ci FileUtils::DelDir(outputFile); 4654aa6d63Sopenharmony_ci return false; 4754aa6d63Sopenharmony_ci } 4854aa6d63Sopenharmony_ci /* 2. Make sign data, and append write to output file */ 4954aa6d63Sopenharmony_ci std::string signAlg = signParams.at(ParamConstants::PARAM_BASIC_SIGANTURE_ALG); 5054aa6d63Sopenharmony_ci bool writeSignDataOk = WriteSignDataToOutputFile(signerConfig, outputFile, signAlg); 5154aa6d63Sopenharmony_ci if (!writeSignDataOk) { 5254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("The sign data made failed."); 5354aa6d63Sopenharmony_ci FileUtils::DelDir(outputFile); 5454aa6d63Sopenharmony_ci return false; 5554aa6d63Sopenharmony_ci } 5654aa6d63Sopenharmony_ci /* 3. Make sign head data, and write to output file */ 5754aa6d63Sopenharmony_ci bool writeSignHeadDataOk = WriteSignHeadDataToOutputFile(inputFile, outputFile); 5854aa6d63Sopenharmony_ci if (!writeSignHeadDataOk) { 5954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("The sign head data made failed."); 6054aa6d63Sopenharmony_ci FileUtils::DelDir(outputFile); 6154aa6d63Sopenharmony_ci return false; 6254aa6d63Sopenharmony_ci } 6354aa6d63Sopenharmony_ci return true; 6454aa6d63Sopenharmony_ci} 6554aa6d63Sopenharmony_ci 6654aa6d63Sopenharmony_cibool SignBin::WriteBlockDataToFile(const std::string& inputFile, const std::string& outputFile, 6754aa6d63Sopenharmony_ci const std::string& profileFile, const std::string& profileSigned) 6854aa6d63Sopenharmony_ci{ 6954aa6d63Sopenharmony_ci int64_t binFileLen = FileUtils::GetFileLen(inputFile); 7054aa6d63Sopenharmony_ci int64_t profileDataLen = FileUtils::GetFileLen(profileFile); 7154aa6d63Sopenharmony_ci bool isValid = CheckBinAndProfileLengthIsValid(binFileLen, profileDataLen); 7254aa6d63Sopenharmony_ci if (!isValid) { 7354aa6d63Sopenharmony_ci PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, 7454aa6d63Sopenharmony_ci "file length is invalid, binFileLen: " + std::to_string(binFileLen) + 7554aa6d63Sopenharmony_ci "lld, profileDataLen: " + std::to_string(profileDataLen) + "lld"); 7654aa6d63Sopenharmony_ci return false; 7754aa6d63Sopenharmony_ci } 7854aa6d63Sopenharmony_ci int64_t offset = binFileLen + BlockHead::GetBlockLen() + BlockHead::GetBlockLen(); 7954aa6d63Sopenharmony_ci bool isOver = IsLongOverflowInteger(offset); 8054aa6d63Sopenharmony_ci if (isOver) { 8154aa6d63Sopenharmony_ci PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, 8254aa6d63Sopenharmony_ci "The profile block head offset is overflow interger range in sign bin, offset: " 8354aa6d63Sopenharmony_ci + std::to_string(offset)); 8454aa6d63Sopenharmony_ci return false; 8554aa6d63Sopenharmony_ci } 8654aa6d63Sopenharmony_ci char isSigned = SignatureBlockTypes::GetProfileBlockTypes(profileSigned); 8754aa6d63Sopenharmony_ci std::string proBlockByte = 8854aa6d63Sopenharmony_ci BlockHead::GetBlockHead(isSigned, SignatureBlockTags::DEFAULT, (short)profileDataLen, (int)offset); 8954aa6d63Sopenharmony_ci offset += profileDataLen; 9054aa6d63Sopenharmony_ci isOver = IsLongOverflowInteger(offset); 9154aa6d63Sopenharmony_ci if (isOver) { 9254aa6d63Sopenharmony_ci PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, 9354aa6d63Sopenharmony_ci "The profile block head offset is overflow interger range in sign bin, offset: " 9454aa6d63Sopenharmony_ci + std::to_string(offset)); 9554aa6d63Sopenharmony_ci return false; 9654aa6d63Sopenharmony_ci } 9754aa6d63Sopenharmony_ci std::string signBlockByte = BlockHead::GetBlockHead( 9854aa6d63Sopenharmony_ci SignatureBlockTypes::SIGNATURE_BLOCK, SignatureBlockTags::DEFAULT, (short)0, (int)offset); 9954aa6d63Sopenharmony_ci return WriteSignedBin(inputFile, proBlockByte, signBlockByte, profileFile, outputFile); 10054aa6d63Sopenharmony_ci} 10154aa6d63Sopenharmony_ci 10254aa6d63Sopenharmony_cistd::vector<int8_t> SignBin::GenerateFileDigest(const std::string& outputFile, 10354aa6d63Sopenharmony_ci const std::string& signAlg) 10454aa6d63Sopenharmony_ci{ 10554aa6d63Sopenharmony_ci SignatureAlgorithmHelper signatureAlgorithmClass; 10654aa6d63Sopenharmony_ci bool getAlgOk = Params::GetSignatureAlgorithm(signAlg, signatureAlgorithmClass); 10754aa6d63Sopenharmony_ci if (!getAlgOk) { 10854aa6d63Sopenharmony_ci PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "[SignHap] get Signature Algorithm failed."); 10954aa6d63Sopenharmony_ci return std::vector<int8_t>(); 11054aa6d63Sopenharmony_ci } 11154aa6d63Sopenharmony_ci std::string alg = signatureAlgorithmClass.m_contentDigestAlgorithm.GetDigestAlgorithm(); 11254aa6d63Sopenharmony_ci std::vector<int8_t> data = HashUtils::GetFileDigest(outputFile, alg); 11354aa6d63Sopenharmony_ci if (data.empty()) { 11454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("GetFileDigest failed."); 11554aa6d63Sopenharmony_ci return std::vector<int8_t>(); 11654aa6d63Sopenharmony_ci } 11754aa6d63Sopenharmony_ci std::vector<int8_t> outputChunk; 11854aa6d63Sopenharmony_ci SignContentInfo contentInfo; 11954aa6d63Sopenharmony_ci contentInfo.AddContentHashData(0, SignatureBlockTags::HASH_ROOT_4K, HashUtils::GetHashAlgsId(alg), 12054aa6d63Sopenharmony_ci data.size(), data); 12154aa6d63Sopenharmony_ci return contentInfo.GetByteContent(); 12254aa6d63Sopenharmony_ci} 12354aa6d63Sopenharmony_ci 12454aa6d63Sopenharmony_cibool SignBin::WriteSignDataToOutputFile(SignerConfig& SignerConfig, const std::string& outputFile, 12554aa6d63Sopenharmony_ci const std::string& signAlg) 12654aa6d63Sopenharmony_ci{ 12754aa6d63Sopenharmony_ci std::vector<int8_t> dig = GenerateFileDigest(outputFile, signAlg); 12854aa6d63Sopenharmony_ci if (dig.empty()) { 12954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("generateSignature verity digest is null."); 13054aa6d63Sopenharmony_ci return false; 13154aa6d63Sopenharmony_ci } 13254aa6d63Sopenharmony_ci std::string retStr; 13354aa6d63Sopenharmony_ci std::string signedData(dig.begin(), dig.end()); 13454aa6d63Sopenharmony_ci std::unique_ptr<Pkcs7Generator> generator = std::make_unique<BCPkcs7Generator>(); 13554aa6d63Sopenharmony_ci if (generator->GenerateSignedData(signedData, &SignerConfig, retStr)) { 13654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("failed to GenerateSignedData!"); 13754aa6d63Sopenharmony_ci return false; 13854aa6d63Sopenharmony_ci } 13954aa6d63Sopenharmony_ci bool writeByteToOutFile = FileUtils::AppendWriteByteToFile(retStr, outputFile); 14054aa6d63Sopenharmony_ci if (!writeByteToOutFile) { 14154aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("write signedData to outputFile failed!"); 14254aa6d63Sopenharmony_ci return false; 14354aa6d63Sopenharmony_ci } 14454aa6d63Sopenharmony_ci return true; 14554aa6d63Sopenharmony_ci} 14654aa6d63Sopenharmony_ci 14754aa6d63Sopenharmony_cibool SignBin::WriteSignHeadDataToOutputFile(const std::string& inputFile, const std::string& outputFile) 14854aa6d63Sopenharmony_ci{ 14954aa6d63Sopenharmony_ci int64_t size = FileUtils::GetFileLen(outputFile) - FileUtils::GetFileLen(inputFile) + SignHead::SIGN_HEAD_LEN; 15054aa6d63Sopenharmony_ci bool isOver = IsLongOverflowInteger(size); 15154aa6d63Sopenharmony_ci if (isOver) { 15254aa6d63Sopenharmony_ci PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, 15354aa6d63Sopenharmony_ci "File size is Overflow integer range, size: " + std::to_string(size)); 15454aa6d63Sopenharmony_ci return false; 15554aa6d63Sopenharmony_ci } 15654aa6d63Sopenharmony_ci SignHead signHeadData; 15754aa6d63Sopenharmony_ci std::vector<int8_t> signHeadByte = signHeadData.GetSignHead(size); 15854aa6d63Sopenharmony_ci if (signHeadByte.empty()) { 15954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Failed to get sign head data!"); 16054aa6d63Sopenharmony_ci return false; 16154aa6d63Sopenharmony_ci } 16254aa6d63Sopenharmony_ci bool writeByteToOutFile = 16354aa6d63Sopenharmony_ci FileUtils::AppendWriteByteToFile(std::string(signHeadByte.begin(), signHeadByte.end()), outputFile); 16454aa6d63Sopenharmony_ci if (!writeByteToOutFile) { 16554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Failed to WriteByteToOutFile!"); 16654aa6d63Sopenharmony_ci return false; 16754aa6d63Sopenharmony_ci } 16854aa6d63Sopenharmony_ci return true; 16954aa6d63Sopenharmony_ci} 17054aa6d63Sopenharmony_ci 17154aa6d63Sopenharmony_cibool SignBin::CheckBinAndProfileLengthIsValid(int64_t binFileLen, int64_t profileDataLen) 17254aa6d63Sopenharmony_ci{ 17354aa6d63Sopenharmony_ci return binFileLen != -1 && profileDataLen != -1 && !IsLongOverflowShort(profileDataLen); 17454aa6d63Sopenharmony_ci} 17554aa6d63Sopenharmony_ci 17654aa6d63Sopenharmony_cibool SignBin::IsLongOverflowInteger(int64_t num) 17754aa6d63Sopenharmony_ci{ 17854aa6d63Sopenharmony_ci return (num - (num & 0xffffffffL)) != 0; 17954aa6d63Sopenharmony_ci} 18054aa6d63Sopenharmony_ci 18154aa6d63Sopenharmony_cibool SignBin::IsLongOverflowShort(int64_t num) 18254aa6d63Sopenharmony_ci{ 18354aa6d63Sopenharmony_ci return (num - (num & 0xffff)) != 0; 18454aa6d63Sopenharmony_ci} 18554aa6d63Sopenharmony_ci 18654aa6d63Sopenharmony_cibool SignBin::WriteSignedBin(const std::string& inputFile, const std::string& proBlockByte, 18754aa6d63Sopenharmony_ci const std::string& signBlockByte, const std::string& profileFile, 18854aa6d63Sopenharmony_ci const std::string& outputFile) 18954aa6d63Sopenharmony_ci{ 19054aa6d63Sopenharmony_ci // 1. write the input file to the output file. 19154aa6d63Sopenharmony_ci bool writeInputOk = FileUtils::WriteInputToOutPut(inputFile, outputFile); 19254aa6d63Sopenharmony_ci // 2. append write profile block head to the output file. 19354aa6d63Sopenharmony_ci bool appendProfileHeadOk = FileUtils::AppendWriteByteToFile(proBlockByte, outputFile); 19454aa6d63Sopenharmony_ci // 3. append write sign block head to the output file. 19554aa6d63Sopenharmony_ci bool appendBlockHeadOk = FileUtils::AppendWriteByteToFile(signBlockByte, outputFile); 19654aa6d63Sopenharmony_ci // 4. write profile src file to the output file. 19754aa6d63Sopenharmony_ci bool appendProfileSrcOk = FileUtils::AppendWriteFileToFile(profileFile, outputFile); 19854aa6d63Sopenharmony_ci if (!writeInputOk || !appendProfileHeadOk || !appendBlockHeadOk || !appendProfileSrcOk) { 19954aa6d63Sopenharmony_ci PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "Failed to write signed bin"); 20054aa6d63Sopenharmony_ci return false; 20154aa6d63Sopenharmony_ci } 20254aa6d63Sopenharmony_ci return true; 20354aa6d63Sopenharmony_ci} 20454aa6d63Sopenharmony_ci 20554aa6d63Sopenharmony_ci} // namespace SignatureTools 20654aa6d63Sopenharmony_ci} // namespace OHOS