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#include "sign_provider.h" 1654aa6d63Sopenharmony_ci 1754aa6d63Sopenharmony_ci#include <openssl/pem.h> 1854aa6d63Sopenharmony_ci#include <openssl/bio.h> 1954aa6d63Sopenharmony_ci#include <openssl/x509.h> 2054aa6d63Sopenharmony_ci#include <cstdio> 2154aa6d63Sopenharmony_ci#include <cinttypes> 2254aa6d63Sopenharmony_ci#include <filesystem> 2354aa6d63Sopenharmony_ci#include <algorithm> 2454aa6d63Sopenharmony_ci 2554aa6d63Sopenharmony_ci#include "nlohmann/json.hpp" 2654aa6d63Sopenharmony_ci#include "string_utils.h" 2754aa6d63Sopenharmony_ci#include "file_utils.h" 2854aa6d63Sopenharmony_ci#include "sign_elf.h" 2954aa6d63Sopenharmony_ci#include "sign_bin.h" 3054aa6d63Sopenharmony_ci#include "params.h" 3154aa6d63Sopenharmony_ci#include "constant.h" 3254aa6d63Sopenharmony_ci 3354aa6d63Sopenharmony_ciusing namespace nlohmann; 3454aa6d63Sopenharmony_cinamespace OHOS { 3554aa6d63Sopenharmony_cinamespace SignatureTools { 3654aa6d63Sopenharmony_cistd::vector<std::string> SignProvider::VALID_SIGN_ALG_NAME = { 3754aa6d63Sopenharmony_ci ParamConstants::HAP_SIG_ALGORITHM_SHA256_ECDSA, 3854aa6d63Sopenharmony_ci ParamConstants::HAP_SIG_ALGORITHM_SHA384_ECDSA, 3954aa6d63Sopenharmony_ci ParamConstants::HAP_SIG_ALGORITHM_SHA512_ECDSA 4054aa6d63Sopenharmony_ci}; 4154aa6d63Sopenharmony_ci 4254aa6d63Sopenharmony_cibool SignProvider::PrintErrorLog(const std::string& log, const int& errorCode, std::string path) 4354aa6d63Sopenharmony_ci{ 4454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("%s", std::string("(Error Code: " + std::to_string(errorCode) + ")" + log).c_str()); 4554aa6d63Sopenharmony_ci if (path != "") { 4654aa6d63Sopenharmony_ci remove(path.c_str()); 4754aa6d63Sopenharmony_ci } 4854aa6d63Sopenharmony_ci return false; 4954aa6d63Sopenharmony_ci} 5054aa6d63Sopenharmony_ci 5154aa6d63Sopenharmony_cibool SignProvider::InitSigerConfig(SignerConfig& signerConfig, STACK_OF(X509)* publicCerts, Options* options) 5254aa6d63Sopenharmony_ci{ 5354aa6d63Sopenharmony_ci std::optional<X509_CRL*> crl = GetCrl(); 5454aa6d63Sopenharmony_ci if (!CreateSignerConfigs(publicCerts, crl, options, signerConfig)) { 5554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[SignHap] create Signer Configs failed"); 5654aa6d63Sopenharmony_ci return false; 5754aa6d63Sopenharmony_ci } 5854aa6d63Sopenharmony_ci int CompatibleVersion; 5954aa6d63Sopenharmony_ci if (!StringUtils::CheckStringToint(signParams.at(ParamConstants::PARAM_BASIC_COMPATIBLE_VERSION), 6054aa6d63Sopenharmony_ci CompatibleVersion)) { 6154aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[SignHap] CompatibleVersion String To int failed"); 6254aa6d63Sopenharmony_ci return false; 6354aa6d63Sopenharmony_ci } 6454aa6d63Sopenharmony_ci signerConfig.SetCompatibleVersion(CompatibleVersion); 6554aa6d63Sopenharmony_ci return true; 6654aa6d63Sopenharmony_ci} 6754aa6d63Sopenharmony_ci 6854aa6d63Sopenharmony_ciint SignProvider::CheckParmaAndInitConfig(SignerConfig& signerConfig, Options* options, std::string& suffix) 6954aa6d63Sopenharmony_ci{ 7054aa6d63Sopenharmony_ci STACK_OF(X509)* publicCerts = nullptr; 7154aa6d63Sopenharmony_ci int ret = GetX509Certificates(options, &publicCerts); 7254aa6d63Sopenharmony_ci if (ret != RET_OK) { 7354aa6d63Sopenharmony_ci sk_X509_pop_free(publicCerts, X509_free); 7454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("SIGNHAP_ERROR get X509 Certificates failed"); 7554aa6d63Sopenharmony_ci return ret; 7654aa6d63Sopenharmony_ci } 7754aa6d63Sopenharmony_ci if (!CheckCompatibleVersion()) { 7854aa6d63Sopenharmony_ci sk_X509_pop_free(publicCerts, X509_free); 7954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("check Compatible Version failed!!"); 8054aa6d63Sopenharmony_ci return COMMAND_PARAM_ERROR; 8154aa6d63Sopenharmony_ci } 8254aa6d63Sopenharmony_ci if (!InitSigerConfig(signerConfig, publicCerts, options)) { 8354aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("create Signer Configs failed"); 8454aa6d63Sopenharmony_ci return COMMAND_PARAM_ERROR; 8554aa6d63Sopenharmony_ci } 8654aa6d63Sopenharmony_ci std::string inputFilePath = signParams.at(ParamConstants::PARAM_BASIC_INPUT_FILE); 8754aa6d63Sopenharmony_ci suffix = FileUtils::GetSuffix(inputFilePath); 8854aa6d63Sopenharmony_ci if (suffix == "") { 8954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("hap format error pleass check!!"); 9054aa6d63Sopenharmony_ci return COMMAND_PARAM_ERROR; 9154aa6d63Sopenharmony_ci } 9254aa6d63Sopenharmony_ci return RET_OK; 9354aa6d63Sopenharmony_ci} 9454aa6d63Sopenharmony_ci 9554aa6d63Sopenharmony_cifileIOTuple SignProvider::PrepareIOStreams(const std::string& inputPath, 9654aa6d63Sopenharmony_ci const std::string& outputPath, bool& ret) 9754aa6d63Sopenharmony_ci{ 9854aa6d63Sopenharmony_ci std::shared_ptr<std::ifstream> inputFile = nullptr; 9954aa6d63Sopenharmony_ci std::shared_ptr<std::ofstream> outputFile = nullptr; 10054aa6d63Sopenharmony_ci std::string tmpOutputFilePath; 10154aa6d63Sopenharmony_ci ret = false; 10254aa6d63Sopenharmony_ci inputFile = std::make_shared<std::ifstream>(inputPath, std::ios::binary); 10354aa6d63Sopenharmony_ci if (!inputFile->good()) { 10454aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, 10554aa6d63Sopenharmony_ci inputPath + " open failed"); 10654aa6d63Sopenharmony_ci return {nullptr, nullptr, ""}; 10754aa6d63Sopenharmony_ci } 10854aa6d63Sopenharmony_ci if (inputPath == outputPath) { 10954aa6d63Sopenharmony_ci std::filesystem::path filePath = outputPath; 11054aa6d63Sopenharmony_ci std::filesystem::path directory = filePath.parent_path(); 11154aa6d63Sopenharmony_ci std::string strDirectory = directory; 11254aa6d63Sopenharmony_ci tmpOutputFilePath = strDirectory + '/' + std::string("signedHap") + "." + "hap"; 11354aa6d63Sopenharmony_ci outputFile = std::make_shared<std::ofstream>(tmpOutputFilePath, std::ios::binary | std::ios::trunc); 11454aa6d63Sopenharmony_ci if (!outputFile->good()) { 11554aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, 11654aa6d63Sopenharmony_ci tmpOutputFilePath + " open failed"); 11754aa6d63Sopenharmony_ci return {nullptr, nullptr, ""}; 11854aa6d63Sopenharmony_ci } 11954aa6d63Sopenharmony_ci ret = true; 12054aa6d63Sopenharmony_ci } else { 12154aa6d63Sopenharmony_ci outputFile = std::make_shared<std::ofstream>(outputPath, std::ios::binary | std::ios::trunc); 12254aa6d63Sopenharmony_ci if (!outputFile->good()) { 12354aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, 12454aa6d63Sopenharmony_ci outputPath + " open failed"); 12554aa6d63Sopenharmony_ci return {nullptr, nullptr, ""}; 12654aa6d63Sopenharmony_ci } 12754aa6d63Sopenharmony_ci tmpOutputFilePath = outputPath; 12854aa6d63Sopenharmony_ci } 12954aa6d63Sopenharmony_ci return {inputFile, outputFile, tmpOutputFilePath}; 13054aa6d63Sopenharmony_ci} 13154aa6d63Sopenharmony_ci 13254aa6d63Sopenharmony_cibool SignProvider::InitZipOutput(std::shared_ptr<RandomAccessFile> outputHap, 13354aa6d63Sopenharmony_ci std::shared_ptr<ZipSigner> zip, 13454aa6d63Sopenharmony_ci std::shared_ptr<std::ifstream> inputStream, 13554aa6d63Sopenharmony_ci std::shared_ptr<std::ofstream>tmpOutput, 13654aa6d63Sopenharmony_ci const std::string& Path) 13754aa6d63Sopenharmony_ci{ 13854aa6d63Sopenharmony_ci int alignment; 13954aa6d63Sopenharmony_ci if (!StringUtils::CheckStringToint(signParams.at(ParamConstants::PARAM_BASIC_ALIGNMENT), alignment)) { 14054aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[signHap] alignment String To int failed"); 14154aa6d63Sopenharmony_ci inputStream->close(); 14254aa6d63Sopenharmony_ci tmpOutput->close(); 14354aa6d63Sopenharmony_ci remove(Path.c_str()); 14454aa6d63Sopenharmony_ci return false; 14554aa6d63Sopenharmony_ci } 14654aa6d63Sopenharmony_ci 14754aa6d63Sopenharmony_ci if (!CopyFileAndAlignment(*inputStream, *tmpOutput, alignment, *zip)) { 14854aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[signHap] copy File And Alignment failed"); 14954aa6d63Sopenharmony_ci inputStream->close(); 15054aa6d63Sopenharmony_ci tmpOutput->close(); 15154aa6d63Sopenharmony_ci remove(Path.c_str()); 15254aa6d63Sopenharmony_ci return false; 15354aa6d63Sopenharmony_ci } 15454aa6d63Sopenharmony_ci 15554aa6d63Sopenharmony_ci inputStream->close(); 15654aa6d63Sopenharmony_ci tmpOutput->flush(); 15754aa6d63Sopenharmony_ci tmpOutput->close(); 15854aa6d63Sopenharmony_ci if (!outputHap->Init(Path)) { 15954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[signHap] init outputFile failed %s", Path.c_str()); 16054aa6d63Sopenharmony_ci remove(Path.c_str()); 16154aa6d63Sopenharmony_ci return false; 16254aa6d63Sopenharmony_ci } 16354aa6d63Sopenharmony_ci return true; 16454aa6d63Sopenharmony_ci} 16554aa6d63Sopenharmony_ci 16654aa6d63Sopenharmony_cibool SignProvider::InitDataSourceContents(RandomAccessFile& outputHap, DataSourceContents& dataSrcContents) 16754aa6d63Sopenharmony_ci{ 16854aa6d63Sopenharmony_ci std::shared_ptr<ZipDataInput> outputHapIn = std::make_shared<RandomAccessFileInput>(outputHap); 16954aa6d63Sopenharmony_ci // get eocd bytebuffer and eocd offset 17054aa6d63Sopenharmony_ci if (!HapSignerBlockUtils::FindEocdInHap(outputHap, dataSrcContents.eocdPair)) { 17154aa6d63Sopenharmony_ci PrintErrorNumberMsg("ZIP_ERROR", ZIP_ERROR, "eocd is not found in hap"); 17254aa6d63Sopenharmony_ci return false; 17354aa6d63Sopenharmony_ci } 17454aa6d63Sopenharmony_ci dataSrcContents.endOfCentralDir = new ByteBufferDataSource(dataSrcContents.eocdPair.first); 17554aa6d63Sopenharmony_ci if (!dataSrcContents.endOfCentralDir) { 17654aa6d63Sopenharmony_ci return false; 17754aa6d63Sopenharmony_ci } 17854aa6d63Sopenharmony_ci 17954aa6d63Sopenharmony_ci // get cd offset 18054aa6d63Sopenharmony_ci if (!HapSignerBlockUtils::GetCentralDirectoryOffset(dataSrcContents.eocdPair.first, 18154aa6d63Sopenharmony_ci dataSrcContents.eocdPair.second, dataSrcContents.cDOffset)) { 18254aa6d63Sopenharmony_ci PrintErrorNumberMsg("ZIP_ERROR", ZIP_ERROR, "get central directory offset failed"); 18354aa6d63Sopenharmony_ci return false; 18454aa6d63Sopenharmony_ci } 18554aa6d63Sopenharmony_ci 18654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("Central Directory Offset is %" PRId64, dataSrcContents.cDOffset); 18754aa6d63Sopenharmony_ci 18854aa6d63Sopenharmony_ci // get beforeCentralDir 18954aa6d63Sopenharmony_ci dataSrcContents.beforeCentralDir = outputHapIn->Slice(0, dataSrcContents.cDOffset); 19054aa6d63Sopenharmony_ci if (!dataSrcContents.beforeCentralDir) { 19154aa6d63Sopenharmony_ci return false; 19254aa6d63Sopenharmony_ci } 19354aa6d63Sopenharmony_ci 19454aa6d63Sopenharmony_ci // get cd size 19554aa6d63Sopenharmony_ci long cDSize; 19654aa6d63Sopenharmony_ci if (!HapSignerBlockUtils::GetCentralDirectorySize(dataSrcContents.eocdPair.first, cDSize)) { 19754aa6d63Sopenharmony_ci PrintErrorNumberMsg("ZIP_ERROR", ZIP_ERROR, "get central directory size failed"); 19854aa6d63Sopenharmony_ci return false; 19954aa6d63Sopenharmony_ci } 20054aa6d63Sopenharmony_ci 20154aa6d63Sopenharmony_ci // get cd buffer 20254aa6d63Sopenharmony_ci dataSrcContents.cDByteBuffer = outputHapIn->CreateByteBuffer(dataSrcContents.cDOffset, cDSize); 20354aa6d63Sopenharmony_ci if (dataSrcContents.cDByteBuffer.GetCapacity() == 0) { 20454aa6d63Sopenharmony_ci return false; 20554aa6d63Sopenharmony_ci } 20654aa6d63Sopenharmony_ci dataSrcContents.centralDir = new ByteBufferDataSource(dataSrcContents.cDByteBuffer); 20754aa6d63Sopenharmony_ci if (!dataSrcContents.centralDir) { 20854aa6d63Sopenharmony_ci return false; 20954aa6d63Sopenharmony_ci } 21054aa6d63Sopenharmony_ci return true; 21154aa6d63Sopenharmony_ci} 21254aa6d63Sopenharmony_ci 21354aa6d63Sopenharmony_cibool SignProvider::Sign(Options* options) 21454aa6d63Sopenharmony_ci{ 21554aa6d63Sopenharmony_ci bool isPathOverlap = false; 21654aa6d63Sopenharmony_ci SignerConfig signerConfig; 21754aa6d63Sopenharmony_ci std::string suffix; 21854aa6d63Sopenharmony_ci if (CheckParmaAndInitConfig(signerConfig, options, suffix) != RET_OK) { 21954aa6d63Sopenharmony_ci return PrintErrorLog("Check Parma And Init Config failed", COMMAND_PARAM_ERROR); 22054aa6d63Sopenharmony_ci } 22154aa6d63Sopenharmony_ci // Since CheckParmaAndInitConfig has already validated all parameters, it is possible to directly use at 22254aa6d63Sopenharmony_ci std::string inputFilePath = signParams.at(ParamConstants::PARAM_BASIC_INPUT_FILE); 22354aa6d63Sopenharmony_ci auto [inputStream, tmpOutput, tmpOutputFilePath] = PrepareIOStreams( 22454aa6d63Sopenharmony_ci inputFilePath, 22554aa6d63Sopenharmony_ci signParams.at(ParamConstants::PARAM_BASIC_OUTPUT_FILE), isPathOverlap); 22654aa6d63Sopenharmony_ci 22754aa6d63Sopenharmony_ci if (!inputStream || !tmpOutput) { 22854aa6d63Sopenharmony_ci return PrintErrorLog("[signHap] Prepare IO Streams failed", IO_ERROR); 22954aa6d63Sopenharmony_ci } 23054aa6d63Sopenharmony_ci 23154aa6d63Sopenharmony_ci std::shared_ptr<ZipSigner> zip = std::make_shared<ZipSigner>(); 23254aa6d63Sopenharmony_ci std::shared_ptr<RandomAccessFile> outputHap = std::make_shared<RandomAccessFile>(); 23354aa6d63Sopenharmony_ci if (!InitZipOutput(outputHap, zip, inputStream, tmpOutput, tmpOutputFilePath)) { 23454aa6d63Sopenharmony_ci return PrintErrorLog("[signHap] Init Zip Output failed", IO_ERROR); 23554aa6d63Sopenharmony_ci } 23654aa6d63Sopenharmony_ci 23754aa6d63Sopenharmony_ci DataSourceContents dataSrcContents; 23854aa6d63Sopenharmony_ci if (!InitDataSourceContents(*outputHap, dataSrcContents)) { 23954aa6d63Sopenharmony_ci return PrintErrorLog("[signHap] Init Data Source Contents failed", ZIP_ERROR, tmpOutputFilePath); 24054aa6d63Sopenharmony_ci } 24154aa6d63Sopenharmony_ci 24254aa6d63Sopenharmony_ci DataSource* contents[] = {dataSrcContents.beforeCentralDir, 24354aa6d63Sopenharmony_ci dataSrcContents.centralDir, dataSrcContents.endOfCentralDir 24454aa6d63Sopenharmony_ci }; 24554aa6d63Sopenharmony_ci if (!AppendCodeSignBlock(&signerConfig, tmpOutputFilePath, suffix, dataSrcContents.cDOffset, *zip)) { 24654aa6d63Sopenharmony_ci return PrintErrorLog("[SignCode] AppendCodeSignBlock failed", SIGN_ERROR, tmpOutputFilePath); 24754aa6d63Sopenharmony_ci } 24854aa6d63Sopenharmony_ci 24954aa6d63Sopenharmony_ci ByteBuffer signingBlock; 25054aa6d63Sopenharmony_ci if (!SignHap::Sign(contents, sizeof(contents) / sizeof(contents[0]), signerConfig, optionalBlocks, 25154aa6d63Sopenharmony_ci signingBlock)) { 25254aa6d63Sopenharmony_ci return PrintErrorLog("[SignHap] SignHap Sign failed.", SIGN_ERROR, tmpOutputFilePath); 25354aa6d63Sopenharmony_ci } 25454aa6d63Sopenharmony_ci 25554aa6d63Sopenharmony_ci int64_t newCentralDirectoryOffset = dataSrcContents.cDOffset + signingBlock.GetCapacity(); 25654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("new Central Directory Offset is %" PRId64, newCentralDirectoryOffset); 25754aa6d63Sopenharmony_ci dataSrcContents.eocdPair.first.SetPosition(0); 25854aa6d63Sopenharmony_ci if (!ZipUtils::SetCentralDirectoryOffset(dataSrcContents.eocdPair.first, newCentralDirectoryOffset)) { 25954aa6d63Sopenharmony_ci return PrintErrorLog("[SignHap] Set Central Directory Offset.", ZIP_ERROR, tmpOutputFilePath); 26054aa6d63Sopenharmony_ci } 26154aa6d63Sopenharmony_ci 26254aa6d63Sopenharmony_ci if (!OutputSignedFile(outputHap.get(), dataSrcContents.cDOffset, signingBlock, dataSrcContents.centralDir, 26354aa6d63Sopenharmony_ci dataSrcContents.eocdPair.first)) { 26454aa6d63Sopenharmony_ci return PrintErrorLog("[SignHap] write output signed file failed.", ZIP_ERROR, tmpOutputFilePath); 26554aa6d63Sopenharmony_ci } 26654aa6d63Sopenharmony_ci return DoAfterSign(isPathOverlap, tmpOutputFilePath, inputFilePath); 26754aa6d63Sopenharmony_ci} 26854aa6d63Sopenharmony_ci 26954aa6d63Sopenharmony_cibool SignProvider::SignElf(Options* options) 27054aa6d63Sopenharmony_ci{ 27154aa6d63Sopenharmony_ci bool isPathOverlap = false; 27254aa6d63Sopenharmony_ci STACK_OF(X509)* publicCerts = nullptr; 27354aa6d63Sopenharmony_ci int ret = GetX509Certificates(options, &publicCerts); 27454aa6d63Sopenharmony_ci if (ret != RET_OK) { 27554aa6d63Sopenharmony_ci sk_X509_pop_free(publicCerts, X509_free); 27654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[SignElf] get X509 Certificates failed! errorCode:%d", ret); 27754aa6d63Sopenharmony_ci return false; 27854aa6d63Sopenharmony_ci } 27954aa6d63Sopenharmony_ci if (!CheckCompatibleVersion()) { 28054aa6d63Sopenharmony_ci sk_X509_pop_free(publicCerts, X509_free); 28154aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[SignElf] check Compatible Version failed!!"); 28254aa6d63Sopenharmony_ci return false; 28354aa6d63Sopenharmony_ci } 28454aa6d63Sopenharmony_ci 28554aa6d63Sopenharmony_ci std::string inputFilePath = signParams.at(ParamConstants::PARAM_BASIC_INPUT_FILE); 28654aa6d63Sopenharmony_ci 28754aa6d63Sopenharmony_ci auto [inputStream, tmpOutput, tmpOutputFilePath] = 28854aa6d63Sopenharmony_ci PrepareIOStreams(inputFilePath, 28954aa6d63Sopenharmony_ci signParams.at(ParamConstants::PARAM_BASIC_OUTPUT_FILE), 29054aa6d63Sopenharmony_ci isPathOverlap); 29154aa6d63Sopenharmony_ci 29254aa6d63Sopenharmony_ci if (!inputStream || !tmpOutput) { 29354aa6d63Sopenharmony_ci sk_X509_pop_free(publicCerts, X509_free); 29454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[signElf] Prepare IO Streams failed"); 29554aa6d63Sopenharmony_ci return false; 29654aa6d63Sopenharmony_ci } 29754aa6d63Sopenharmony_ci 29854aa6d63Sopenharmony_ci SignerConfig signerConfig; 29954aa6d63Sopenharmony_ci if (!InitSigerConfig(signerConfig, publicCerts, options)) { 30054aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("SignElf] create Signer Configs failed"); 30154aa6d63Sopenharmony_ci return false; 30254aa6d63Sopenharmony_ci } 30354aa6d63Sopenharmony_ci 30454aa6d63Sopenharmony_ci if (!profileContent.empty()) { 30554aa6d63Sopenharmony_ci signParams.insert(std::make_pair(ParamConstants::PARAM_PROFILE_JSON_CONTENT, profileContent)); 30654aa6d63Sopenharmony_ci } 30754aa6d63Sopenharmony_ci 30854aa6d63Sopenharmony_ci if (!SignElf::Sign(signerConfig, signParams)) { 30954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[SignElf] sign elf failed"); 31054aa6d63Sopenharmony_ci return false; 31154aa6d63Sopenharmony_ci } 31254aa6d63Sopenharmony_ci 31354aa6d63Sopenharmony_ci return true; 31454aa6d63Sopenharmony_ci} 31554aa6d63Sopenharmony_ci 31654aa6d63Sopenharmony_cibool SignProvider::SignBin(Options* options) 31754aa6d63Sopenharmony_ci{ 31854aa6d63Sopenharmony_ci STACK_OF(X509)* x509Certificates = nullptr; 31954aa6d63Sopenharmony_ci int ret = GetX509Certificates(options, &x509Certificates); 32054aa6d63Sopenharmony_ci if (ret != RET_OK) { 32154aa6d63Sopenharmony_ci sk_X509_pop_free(x509Certificates, X509_free); 32254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[SignBin] get X509 Certificates failed! errorCode:%d", ret); 32354aa6d63Sopenharmony_ci return false; 32454aa6d63Sopenharmony_ci } 32554aa6d63Sopenharmony_ci if (!CheckCompatibleVersion()) { 32654aa6d63Sopenharmony_ci sk_X509_pop_free(x509Certificates, X509_free); 32754aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("check Compatible Version failed!"); 32854aa6d63Sopenharmony_ci return false; 32954aa6d63Sopenharmony_ci } 33054aa6d63Sopenharmony_ci 33154aa6d63Sopenharmony_ci SignerConfig signerConfig; 33254aa6d63Sopenharmony_ci if (!InitSigerConfig(signerConfig, x509Certificates, options)) { 33354aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[SignBin] create Signer Configs failed"); 33454aa6d63Sopenharmony_ci return false; 33554aa6d63Sopenharmony_ci } 33654aa6d63Sopenharmony_ci 33754aa6d63Sopenharmony_ci bool signFlag = SignBin::Sign(signerConfig, signParams); 33854aa6d63Sopenharmony_ci if (!signFlag) { 33954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("sign bin internal failed"); 34054aa6d63Sopenharmony_ci return false; 34154aa6d63Sopenharmony_ci } 34254aa6d63Sopenharmony_ci 34354aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("sign bin success"); 34454aa6d63Sopenharmony_ci return true; 34554aa6d63Sopenharmony_ci} 34654aa6d63Sopenharmony_ci 34754aa6d63Sopenharmony_cibool SignProvider::AppendCodeSignBlock(SignerConfig* signerConfig, std::string outputFilePath, 34854aa6d63Sopenharmony_ci const std::string& suffix, int64_t centralDirectoryOffset, ZipSigner& zip) 34954aa6d63Sopenharmony_ci{ 35054aa6d63Sopenharmony_ci if (signParams.at(ParamConstants::PARAM_SIGN_CODE) == CodeSigning::ENABLE_SIGN_CODE_VALUE) { 35154aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("start code signing."); 35254aa6d63Sopenharmony_ci std::string suffixTmp = suffix; 35354aa6d63Sopenharmony_ci std::transform(suffixTmp.begin(), suffixTmp.end(), suffixTmp.begin(), ::tolower); 35454aa6d63Sopenharmony_ci if (std::find(CodeSigning::SUPPORT_FILE_FORM.begin(), CodeSigning::SUPPORT_FILE_FORM.end(), 35554aa6d63Sopenharmony_ci suffixTmp) == CodeSigning::SUPPORT_FILE_FORM.end()) { 35654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("no need to sign code for %s", suffixTmp.c_str()); 35754aa6d63Sopenharmony_ci return true; 35854aa6d63Sopenharmony_ci } 35954aa6d63Sopenharmony_ci // 4 means hap format occupy 4 byte storage location,2 means optional blocks reserve 2 storage location 36054aa6d63Sopenharmony_ci int64_t codeSignOffset = centralDirectoryOffset + ((4 + 4 + 4) * (optionalBlocks.size() + 2 + 1)); 36154aa6d63Sopenharmony_ci // create CodeSigning Object 36254aa6d63Sopenharmony_ci CodeSigning codeSigning(signerConfig); 36354aa6d63Sopenharmony_ci std::vector<int8_t> codeSignArray; 36454aa6d63Sopenharmony_ci if (!codeSigning.GetCodeSignBlock(outputFilePath, codeSignOffset, suffixTmp, profileContent, zip, 36554aa6d63Sopenharmony_ci codeSignArray)) { 36654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Codesigning getCodeSignBlock Fail."); 36754aa6d63Sopenharmony_ci return false; 36854aa6d63Sopenharmony_ci } 36954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("generate codeSignArray finished."); 37054aa6d63Sopenharmony_ci std::unique_ptr<ByteBuffer> result = 37154aa6d63Sopenharmony_ci std::make_unique<ByteBuffer>(codeSignArray.size() 37254aa6d63Sopenharmony_ci + (FOUR_BYTE + FOUR_BYTE + FOUR_BYTE)); 37354aa6d63Sopenharmony_ci result->PutInt32(HapUtils::HAP_CODE_SIGN_BLOCK_ID); 37454aa6d63Sopenharmony_ci result->PutInt32(codeSignArray.size()); // length 37554aa6d63Sopenharmony_ci result->PutInt32((int32_t)codeSignOffset); // offset 37654aa6d63Sopenharmony_ci result->PutData(codeSignArray.data(), codeSignArray.size()); 37754aa6d63Sopenharmony_ci 37854aa6d63Sopenharmony_ci OptionalBlock tmp = {HapUtils::HAP_PROPERTY_BLOCK_ID, *result}; 37954aa6d63Sopenharmony_ci optionalBlocks.insert(optionalBlocks.begin(), tmp); 38054aa6d63Sopenharmony_ci } 38154aa6d63Sopenharmony_ci return true; 38254aa6d63Sopenharmony_ci} 38354aa6d63Sopenharmony_ci 38454aa6d63Sopenharmony_cibool SignProvider::CreateSignerConfigs(STACK_OF(X509)* certificates, const std::optional<X509_CRL*>& crl, 38554aa6d63Sopenharmony_ci Options* options, SignerConfig& inOut) 38654aa6d63Sopenharmony_ci{ 38754aa6d63Sopenharmony_ci inOut.FillParameters(signParams); 38854aa6d63Sopenharmony_ci inOut.SetCertificates(certificates); 38954aa6d63Sopenharmony_ci inOut.SetOptions(options); 39054aa6d63Sopenharmony_ci std::vector<SignatureAlgorithmHelper> signatureAlgorithms; 39154aa6d63Sopenharmony_ci SignatureAlgorithmHelper alg; 39254aa6d63Sopenharmony_ci // Since CheckParmaAndInitConfig has already validated all parameters, it is possible to directly use at 39354aa6d63Sopenharmony_ci if (!Params::GetSignatureAlgorithm(signParams.at(ParamConstants::PARAM_BASIC_SIGANTURE_ALG), 39454aa6d63Sopenharmony_ci alg)) { 39554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("[SignHap] get Signature Algorithm failed"); 39654aa6d63Sopenharmony_ci return false; 39754aa6d63Sopenharmony_ci } 39854aa6d63Sopenharmony_ci signatureAlgorithms.push_back(alg); 39954aa6d63Sopenharmony_ci inOut.SetSignatureAlgorithms(signatureAlgorithms); 40054aa6d63Sopenharmony_ci if (crl.has_value()) { 40154aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("not support crl"); 40254aa6d63Sopenharmony_ci return false; 40354aa6d63Sopenharmony_ci } 40454aa6d63Sopenharmony_ci return true; 40554aa6d63Sopenharmony_ci} 40654aa6d63Sopenharmony_ci 40754aa6d63Sopenharmony_ciint SignProvider::LoadOptionalBlocks() 40854aa6d63Sopenharmony_ci{ 40954aa6d63Sopenharmony_ci int ret = RET_OK; 41054aa6d63Sopenharmony_ci if (auto property = signParams.find(ParamConstants::PARAM_BASIC_PROPERTY); 41154aa6d63Sopenharmony_ci property != signParams.end()) { 41254aa6d63Sopenharmony_ci if ((ret = LoadOptionalBlock(property->second, HapUtils::HAP_PROPERTY_BLOCK_ID)) != RET_OK) 41354aa6d63Sopenharmony_ci return ret; 41454aa6d63Sopenharmony_ci } 41554aa6d63Sopenharmony_ci if (auto profile = signParams.find(ParamConstants::PARAM_BASIC_PROFILE); profile != signParams.end()) { 41654aa6d63Sopenharmony_ci if ((ret = LoadOptionalBlock(profile->second, HapUtils::HAP_PROFILE_BLOCK_ID)) != RET_OK) 41754aa6d63Sopenharmony_ci return ret; 41854aa6d63Sopenharmony_ci } 41954aa6d63Sopenharmony_ci if (auto proofOfRotation = signParams.find(ParamConstants::PARAM_BASIC_PROOF); 42054aa6d63Sopenharmony_ci proofOfRotation != signParams.end()) { 42154aa6d63Sopenharmony_ci if ((LoadOptionalBlock(proofOfRotation->second, HapUtils::HAP_PROOF_OF_ROTATION_BLOCK_ID)) != RET_OK) 42254aa6d63Sopenharmony_ci return ret; 42354aa6d63Sopenharmony_ci } 42454aa6d63Sopenharmony_ci return ret; 42554aa6d63Sopenharmony_ci} 42654aa6d63Sopenharmony_ci 42754aa6d63Sopenharmony_ciint SignProvider::LoadOptionalBlock(const std::string& file, int type) 42854aa6d63Sopenharmony_ci{ 42954aa6d63Sopenharmony_ci if (file.empty()) 43054aa6d63Sopenharmony_ci return RET_OK; 43154aa6d63Sopenharmony_ci if (!CheckFile(file)) { 43254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("check file failed. Invalid file: %s, file type: %d", 43354aa6d63Sopenharmony_ci file.c_str(), type); 43454aa6d63Sopenharmony_ci return FILE_NOT_FOUND; 43554aa6d63Sopenharmony_ci } 43654aa6d63Sopenharmony_ci ByteBuffer optionalBlockBuffer; 43754aa6d63Sopenharmony_ci if (!HapUtils::ReadFileToByteBuffer(file, optionalBlockBuffer)) 43854aa6d63Sopenharmony_ci return IO_ERROR; 43954aa6d63Sopenharmony_ci if (optionalBlockBuffer.GetCapacity() == 0) { 44054aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, file + " is empty!"); 44154aa6d63Sopenharmony_ci return IO_ERROR; 44254aa6d63Sopenharmony_ci } 44354aa6d63Sopenharmony_ci optionalBlocks.push_back({type, optionalBlockBuffer}); 44454aa6d63Sopenharmony_ci return RET_OK; 44554aa6d63Sopenharmony_ci} 44654aa6d63Sopenharmony_ci 44754aa6d63Sopenharmony_cistd::optional<X509_CRL*> SignProvider::GetCrl() 44854aa6d63Sopenharmony_ci{ 44954aa6d63Sopenharmony_ci return std::nullopt; 45054aa6d63Sopenharmony_ci} 45154aa6d63Sopenharmony_ci 45254aa6d63Sopenharmony_cibool SignProvider::CheckFile(const std::string& filePath) 45354aa6d63Sopenharmony_ci{ 45454aa6d63Sopenharmony_ci if (filePath.empty()) { 45554aa6d63Sopenharmony_ci PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "file name is null."); 45654aa6d63Sopenharmony_ci return false; 45754aa6d63Sopenharmony_ci } 45854aa6d63Sopenharmony_ci if (!std::filesystem::exists(filePath) || !std::filesystem::is_regular_file(filePath)) { 45954aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, filePath + " not exist or can not read!"); 46054aa6d63Sopenharmony_ci return false; 46154aa6d63Sopenharmony_ci } 46254aa6d63Sopenharmony_ci return true; 46354aa6d63Sopenharmony_ci} 46454aa6d63Sopenharmony_ci 46554aa6d63Sopenharmony_ciint SignProvider::GetX509Certificates(Options* options, STACK_OF(X509)** X509Vec) 46654aa6d63Sopenharmony_ci{ 46754aa6d63Sopenharmony_ci int ret = RET_OK; 46854aa6d63Sopenharmony_ci // 1.check the parameters 46954aa6d63Sopenharmony_ci if (!CheckParams(options)) { 47054aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Check Params failed please check"); 47154aa6d63Sopenharmony_ci return COMMAND_ERROR; 47254aa6d63Sopenharmony_ci } 47354aa6d63Sopenharmony_ci // 2.get x509 verify certificate 47454aa6d63Sopenharmony_ci ret = GetPublicCerts(options, X509Vec); 47554aa6d63Sopenharmony_ci if (ret != RET_OK) { 47654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Get Public Certs please check"); 47754aa6d63Sopenharmony_ci return ret; 47854aa6d63Sopenharmony_ci } 47954aa6d63Sopenharmony_ci // 3. load optionalBlocks 48054aa6d63Sopenharmony_ci ret = LoadOptionalBlocks(); 48154aa6d63Sopenharmony_ci if (ret != RET_OK) { 48254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Load Optional Blocks please check"); 48354aa6d63Sopenharmony_ci return ret; 48454aa6d63Sopenharmony_ci } 48554aa6d63Sopenharmony_ci std::string inForm = options->GetString(Options::INFORM); 48654aa6d63Sopenharmony_ci std::string profileFile = options->GetString(Options::PROFILE_FILE); 48754aa6d63Sopenharmony_ci if (StringUtils::CaseCompare(inForm, ELF) && FileUtils::IsEmpty(profileFile)) { 48854aa6d63Sopenharmony_ci return ret; 48954aa6d63Sopenharmony_ci } 49054aa6d63Sopenharmony_ci // 4. check Profile Valid 49154aa6d63Sopenharmony_ci if ((ret = CheckProfileValid(*X509Vec)) < 0) { 49254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("profile check error"); 49354aa6d63Sopenharmony_ci sk_X509_pop_free(*X509Vec, X509_free); 49454aa6d63Sopenharmony_ci *X509Vec = nullptr; 49554aa6d63Sopenharmony_ci return ret; 49654aa6d63Sopenharmony_ci } 49754aa6d63Sopenharmony_ci return ret; 49854aa6d63Sopenharmony_ci} 49954aa6d63Sopenharmony_ci 50054aa6d63Sopenharmony_ciint SignProvider::GetPublicCerts(Options* options, STACK_OF(X509)** ret) 50154aa6d63Sopenharmony_ci{ 50254aa6d63Sopenharmony_ci std::string appCertFileName = options->GetString(Options::APP_CERT_FILE); 50354aa6d63Sopenharmony_ci if (appCertFileName.empty()) { 50454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("appCertFile param can not find,may be is RemoteSigner"); 50554aa6d63Sopenharmony_ci return RET_OK; 50654aa6d63Sopenharmony_ci } 50754aa6d63Sopenharmony_ci return GetCertificateChainFromFile(appCertFileName, ret); 50854aa6d63Sopenharmony_ci} 50954aa6d63Sopenharmony_ci 51054aa6d63Sopenharmony_ciint SignProvider::GetCertificateChainFromFile(const std::string& certChianFile, STACK_OF(X509)** ret) 51154aa6d63Sopenharmony_ci{ 51254aa6d63Sopenharmony_ci return GetCertListFromFile(certChianFile, ret); 51354aa6d63Sopenharmony_ci} 51454aa6d63Sopenharmony_ci 51554aa6d63Sopenharmony_ciint SignProvider::GetCertListFromFile(const std::string& certsFile, STACK_OF(X509)** ret) 51654aa6d63Sopenharmony_ci{ 51754aa6d63Sopenharmony_ci X509* cert = nullptr; 51854aa6d63Sopenharmony_ci *ret = sk_X509_new(nullptr); 51954aa6d63Sopenharmony_ci if (*ret == nullptr) { 52054aa6d63Sopenharmony_ci PrintErrorNumberMsg("RET_FAILED", RET_FAILED, "get CertList FromFile [sk_X509_new] failed"); 52154aa6d63Sopenharmony_ci return RET_FAILED; 52254aa6d63Sopenharmony_ci } 52354aa6d63Sopenharmony_ci BIO* certBio = BIO_new_file(certsFile.c_str(), "rb"); 52454aa6d63Sopenharmony_ci if (!certBio) { 52554aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, 52654aa6d63Sopenharmony_ci std::string("get CertList from file ") + certsFile + " failed"); 52754aa6d63Sopenharmony_ci sk_X509_free(*ret); 52854aa6d63Sopenharmony_ci return IO_ERROR; 52954aa6d63Sopenharmony_ci } 53054aa6d63Sopenharmony_ci while (1) { 53154aa6d63Sopenharmony_ci cert = PEM_read_bio_X509(certBio, NULL, NULL, NULL); 53254aa6d63Sopenharmony_ci if (cert == nullptr) 53354aa6d63Sopenharmony_ci break; 53454aa6d63Sopenharmony_ci sk_X509_push(*ret, cert); 53554aa6d63Sopenharmony_ci } 53654aa6d63Sopenharmony_ci BIO_free(certBio); 53754aa6d63Sopenharmony_ci return RET_OK; 53854aa6d63Sopenharmony_ci} 53954aa6d63Sopenharmony_ci 54054aa6d63Sopenharmony_cibool SignProvider::DoAfterSign(bool isPathOverlap, const std::string& tmpOutputFile, const std::string& inputFilePath) 54154aa6d63Sopenharmony_ci{ 54254aa6d63Sopenharmony_ci if (isPathOverlap) { 54354aa6d63Sopenharmony_ci remove(inputFilePath.c_str()); 54454aa6d63Sopenharmony_ci if (rename(tmpOutputFile.c_str(), inputFilePath.c_str()) != 0) { 54554aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, 54654aa6d63Sopenharmony_ci "File name " + tmpOutputFile + " rename to " + inputFilePath + " failed!"); 54754aa6d63Sopenharmony_ci return false; 54854aa6d63Sopenharmony_ci } 54954aa6d63Sopenharmony_ci } 55054aa6d63Sopenharmony_ci return true; 55154aa6d63Sopenharmony_ci} 55254aa6d63Sopenharmony_ci 55354aa6d63Sopenharmony_cibool SignProvider::CopyFileAndAlignment(std::ifstream& input, std::ofstream& tmpOutput, int alignment, ZipSigner& zip) 55454aa6d63Sopenharmony_ci{ 55554aa6d63Sopenharmony_ci if (!zip.Init(input)) { 55654aa6d63Sopenharmony_ci PrintErrorNumberMsg("ZIP_ERROR", ZIP_ERROR, "zip init failed"); 55754aa6d63Sopenharmony_ci return false; 55854aa6d63Sopenharmony_ci } 55954aa6d63Sopenharmony_ci zip.Alignment(alignment); 56054aa6d63Sopenharmony_ci zip.RemoveSignBlock(); 56154aa6d63Sopenharmony_ci if (!zip.ToFile(input, tmpOutput)) { 56254aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "zip write to file failed"); 56354aa6d63Sopenharmony_ci return false; 56454aa6d63Sopenharmony_ci } 56554aa6d63Sopenharmony_ci return true; 56654aa6d63Sopenharmony_ci} 56754aa6d63Sopenharmony_ci 56854aa6d63Sopenharmony_cibool SignProvider::SetSignParams(Options* options, std::unordered_set<std::string>& paramSet) 56954aa6d63Sopenharmony_ci{ 57054aa6d63Sopenharmony_ci for (auto it = options->begin(); it != options->end(); it++) { 57154aa6d63Sopenharmony_ci if (paramSet.find(it->first) != paramSet.end()) { 57254aa6d63Sopenharmony_ci size_t size = it->first.size(); 57354aa6d63Sopenharmony_ci std::string str = it->first.substr(size - 3); 57454aa6d63Sopenharmony_ci if (str != "Pwd") { 57554aa6d63Sopenharmony_ci this->signParams.insert(std::make_pair(it->first, options->GetString(it->first))); 57654aa6d63Sopenharmony_ci } 57754aa6d63Sopenharmony_ci } 57854aa6d63Sopenharmony_ci } 57954aa6d63Sopenharmony_ci return true; 58054aa6d63Sopenharmony_ci} 58154aa6d63Sopenharmony_ci 58254aa6d63Sopenharmony_cibool SignProvider::CheckParams(Options* options) 58354aa6d63Sopenharmony_ci{ 58454aa6d63Sopenharmony_ci std::vector<std::string> paramFileds; 58554aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_ALIGNMENT); 58654aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_SIGANTURE_ALG); 58754aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_INPUT_FILE); 58854aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_OUTPUT_FILE); 58954aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PRIVATE_KEY); 59054aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PROFILE); 59154aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PROOF); 59254aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PROPERTY); 59354aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_REMOTE_SERVER); 59454aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_PROFILE_SIGNED); 59554aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_LOCAL_PUBLIC_CERT); 59654aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_BASIC_COMPATIBLE_VERSION); 59754aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_SIGN_CODE); 59854aa6d63Sopenharmony_ci paramFileds.emplace_back(ParamConstants::PARAM_IN_FORM); 59954aa6d63Sopenharmony_ci 60054aa6d63Sopenharmony_ci std::unordered_set<std::string> paramSet = Params::InitParamField(paramFileds); 60154aa6d63Sopenharmony_ci for (auto it = options->begin(); it != options->end(); it++) { 60254aa6d63Sopenharmony_ci if (paramSet.find(it->first) != paramSet.end()) { 60354aa6d63Sopenharmony_ci signParams.insert(std::make_pair(it->first, options->GetString(it->first))); 60454aa6d63Sopenharmony_ci } 60554aa6d63Sopenharmony_ci } 60654aa6d63Sopenharmony_ci 60754aa6d63Sopenharmony_ci if (signParams.find(ParamConstants::PARAM_BASIC_PROFILE_SIGNED) == signParams.end() 60854aa6d63Sopenharmony_ci || signParams.at(ParamConstants::PARAM_BASIC_PROFILE_SIGNED).empty()) { 60954aa6d63Sopenharmony_ci signParams[ParamConstants::PARAM_BASIC_PROFILE_SIGNED] = "1"; 61054aa6d63Sopenharmony_ci } 61154aa6d63Sopenharmony_ci if (!CheckSignCode()) { 61254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("signCode Parameter check error, signCode must is 0 or 1"); 61354aa6d63Sopenharmony_ci return false; 61454aa6d63Sopenharmony_ci } 61554aa6d63Sopenharmony_ci if (!CheckSignatureAlg()) { 61654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("signAlg Parameter is not support"); 61754aa6d63Sopenharmony_ci return false; 61854aa6d63Sopenharmony_ci } 61954aa6d63Sopenharmony_ci CheckSignAlignment(); 62054aa6d63Sopenharmony_ci return true; 62154aa6d63Sopenharmony_ci} 62254aa6d63Sopenharmony_ci 62354aa6d63Sopenharmony_cibool SignProvider::CheckSignCode() 62454aa6d63Sopenharmony_ci{ 62554aa6d63Sopenharmony_ci if (signParams.find(ParamConstants::PARAM_SIGN_CODE) == signParams.end()) { 62654aa6d63Sopenharmony_ci signParams.insert(std::make_pair(ParamConstants::PARAM_SIGN_CODE, ParamConstants::ENABLE_SIGN_CODE)); 62754aa6d63Sopenharmony_ci return true; 62854aa6d63Sopenharmony_ci } 62954aa6d63Sopenharmony_ci std::string codeSign = signParams[ParamConstants::PARAM_SIGN_CODE]; 63054aa6d63Sopenharmony_ci if ((codeSign != ParamConstants::ENABLE_SIGN_CODE) && (codeSign != ParamConstants::DISABLE_SIGN_CODE)) { 63154aa6d63Sopenharmony_ci PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, 63254aa6d63Sopenharmony_ci "signCode Parameter must 0 or 1, you put is " + codeSign); 63354aa6d63Sopenharmony_ci return false; 63454aa6d63Sopenharmony_ci } 63554aa6d63Sopenharmony_ci return true; 63654aa6d63Sopenharmony_ci} 63754aa6d63Sopenharmony_ci 63854aa6d63Sopenharmony_cibool SignProvider::CheckSignatureAlg() 63954aa6d63Sopenharmony_ci{ 64054aa6d63Sopenharmony_ci std::string signAlg = signParams[ParamConstants::PARAM_BASIC_SIGANTURE_ALG]; 64154aa6d63Sopenharmony_ci // Remove leading spaces 64254aa6d63Sopenharmony_ci size_t start = signAlg.find_first_not_of(" "); 64354aa6d63Sopenharmony_ci if (start != std::string::npos) { 64454aa6d63Sopenharmony_ci signAlg = signAlg.substr(start); 64554aa6d63Sopenharmony_ci } 64654aa6d63Sopenharmony_ci // Remove trailing spaces 64754aa6d63Sopenharmony_ci size_t end = signAlg.find_last_not_of(" "); 64854aa6d63Sopenharmony_ci if (end != std::string::npos) { 64954aa6d63Sopenharmony_ci signAlg = signAlg.substr(0, end + 1); 65054aa6d63Sopenharmony_ci } 65154aa6d63Sopenharmony_ci for (auto it = VALID_SIGN_ALG_NAME.begin(); it != VALID_SIGN_ALG_NAME.end(); it++) { 65254aa6d63Sopenharmony_ci if (StringUtils::CaseCompare(*it, signAlg)) { 65354aa6d63Sopenharmony_ci return true; 65454aa6d63Sopenharmony_ci } 65554aa6d63Sopenharmony_ci } 65654aa6d63Sopenharmony_ci PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, 65754aa6d63Sopenharmony_ci "signAlg Parameter is only support [SHA256withECDSA / SHA384withECDSA]"); 65854aa6d63Sopenharmony_ci return false; 65954aa6d63Sopenharmony_ci} 66054aa6d63Sopenharmony_ci 66154aa6d63Sopenharmony_civoid SignProvider::CheckSignAlignment() 66254aa6d63Sopenharmony_ci{ 66354aa6d63Sopenharmony_ci if (signParams.find(ParamConstants::PARAM_BASIC_ALIGNMENT) == signParams.end()) { 66454aa6d63Sopenharmony_ci signParams.insert(std::make_pair(ParamConstants::PARAM_BASIC_ALIGNMENT, ParamConstants::ALIGNMENT)); 66554aa6d63Sopenharmony_ci } 66654aa6d63Sopenharmony_ci} 66754aa6d63Sopenharmony_ci 66854aa6d63Sopenharmony_cibool SignProvider::CheckCompatibleVersion() 66954aa6d63Sopenharmony_ci{ 67054aa6d63Sopenharmony_ci auto it = signParams.find(ParamConstants::PARAM_BASIC_COMPATIBLE_VERSION); 67154aa6d63Sopenharmony_ci if (it == signParams.end()) { 67254aa6d63Sopenharmony_ci signParams[ParamConstants::PARAM_BASIC_COMPATIBLE_VERSION] = "9"; 67354aa6d63Sopenharmony_ci return true; 67454aa6d63Sopenharmony_ci } 67554aa6d63Sopenharmony_ci const std::string& compatibleApiVersionVal = it->second; 67654aa6d63Sopenharmony_ci int compatibleApiVersion; 67754aa6d63Sopenharmony_ci if (!StringUtils::CheckStringToint(compatibleApiVersionVal, compatibleApiVersion)) { 67854aa6d63Sopenharmony_ci PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, 67954aa6d63Sopenharmony_ci "compatibleVersion Parameter is must integer"); 68054aa6d63Sopenharmony_ci return false; 68154aa6d63Sopenharmony_ci } 68254aa6d63Sopenharmony_ci return true; 68354aa6d63Sopenharmony_ci} 68454aa6d63Sopenharmony_ci 68554aa6d63Sopenharmony_cibool SignProvider::OutputSignedFile(RandomAccessFile* outputHap, 68654aa6d63Sopenharmony_ci long centralDirectoryOffset, 68754aa6d63Sopenharmony_ci ByteBuffer& signingBlock, 68854aa6d63Sopenharmony_ci ByteBufferDataSource* centralDirectory, 68954aa6d63Sopenharmony_ci ByteBuffer& eocdBuffer) 69054aa6d63Sopenharmony_ci{ 69154aa6d63Sopenharmony_ci std::shared_ptr<RandomAccessFileOutput> outputHapOut = 69254aa6d63Sopenharmony_ci std::make_shared<RandomAccessFileOutput>(outputHap, centralDirectoryOffset); 69354aa6d63Sopenharmony_ci if (!outputHapOut->Write(signingBlock)) { 69454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("output hap file write signingBlock failed"); 69554aa6d63Sopenharmony_ci return false; 69654aa6d63Sopenharmony_ci } 69754aa6d63Sopenharmony_ci if (!outputHapOut->Write(centralDirectory->GetByteBuffer())) { 69854aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("output hap file write central directory failed"); 69954aa6d63Sopenharmony_ci return false; 70054aa6d63Sopenharmony_ci } 70154aa6d63Sopenharmony_ci if (!outputHapOut->Write(eocdBuffer) != 0) { 70254aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("output hap file write eocd failed"); 70354aa6d63Sopenharmony_ci return false; 70454aa6d63Sopenharmony_ci } 70554aa6d63Sopenharmony_ci return true; 70654aa6d63Sopenharmony_ci} 70754aa6d63Sopenharmony_ci 70854aa6d63Sopenharmony_ciX509* SignProvider::GetCertificate(const std::string& certificate)const 70954aa6d63Sopenharmony_ci{ 71054aa6d63Sopenharmony_ci BIO* in = BIO_new_mem_buf(certificate.data(), certificate.size()); 71154aa6d63Sopenharmony_ci if (!in) { 71254aa6d63Sopenharmony_ci PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, 71354aa6d63Sopenharmony_ci "bio new error ,get ceritificate from base64 certificate failed"); 71454aa6d63Sopenharmony_ci return NULL; 71554aa6d63Sopenharmony_ci } 71654aa6d63Sopenharmony_ci X509* cert = NULL; 71754aa6d63Sopenharmony_ci cert = PEM_read_bio_X509(in, NULL, NULL, NULL); 71854aa6d63Sopenharmony_ci if (!cert) { 71954aa6d63Sopenharmony_ci BIO_free(in); 72054aa6d63Sopenharmony_ci PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, 72154aa6d63Sopenharmony_ci "read no cert from base64 certificate failed"); 72254aa6d63Sopenharmony_ci return NULL; 72354aa6d63Sopenharmony_ci } 72454aa6d63Sopenharmony_ci BIO_free(in); 72554aa6d63Sopenharmony_ci return cert; 72654aa6d63Sopenharmony_ci} 72754aa6d63Sopenharmony_ci 72854aa6d63Sopenharmony_cistd::string SignProvider::GetCertificateCN(X509* cert)const 72954aa6d63Sopenharmony_ci{ 73054aa6d63Sopenharmony_ci X509_NAME* name = NULL; 73154aa6d63Sopenharmony_ci int len = 0; 73254aa6d63Sopenharmony_ci std::string ret; 73354aa6d63Sopenharmony_ci if (cert == NULL) { 73454aa6d63Sopenharmony_ci return ""; 73554aa6d63Sopenharmony_ci } 73654aa6d63Sopenharmony_ci name = X509_get_subject_name(cert); 73754aa6d63Sopenharmony_ci if (!name) { 73854aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("name is NULL,get X509_NAME from cert failed"); 73954aa6d63Sopenharmony_ci } 74054aa6d63Sopenharmony_ci len = X509_NAME_get_text_by_NID(name, NID_countryName, NULL, 0); 74154aa6d63Sopenharmony_ci if (len <= 0) { 74254aa6d63Sopenharmony_ci return ""; 74354aa6d63Sopenharmony_ci } 74454aa6d63Sopenharmony_ci ret.resize(len + 1); 74554aa6d63Sopenharmony_ci if (X509_NAME_get_text_by_NID(name, NID_countryName, &ret[0], len + 1) != len) { 74654aa6d63Sopenharmony_ci return ""; 74754aa6d63Sopenharmony_ci } 74854aa6d63Sopenharmony_ci return ret; 74954aa6d63Sopenharmony_ci} 75054aa6d63Sopenharmony_ci 75154aa6d63Sopenharmony_cistd::string SignProvider::FindProfileFromOptionalBlocks()const 75254aa6d63Sopenharmony_ci{ 75354aa6d63Sopenharmony_ci std::string profile; 75454aa6d63Sopenharmony_ci for (const OptionalBlock& optionalBlock : optionalBlocks) { 75554aa6d63Sopenharmony_ci if (optionalBlock.optionalType == HapUtils::HAP_PROFILE_BLOCK_ID) { 75654aa6d63Sopenharmony_ci profile = std::string(optionalBlock.optionalBlockValue.GetBufferPtr(), 75754aa6d63Sopenharmony_ci optionalBlock.optionalBlockValue.GetCapacity()); 75854aa6d63Sopenharmony_ci } 75954aa6d63Sopenharmony_ci } 76054aa6d63Sopenharmony_ci return profile; 76154aa6d63Sopenharmony_ci} 76254aa6d63Sopenharmony_ci 76354aa6d63Sopenharmony_ciint SignProvider::CheckProfileValid(STACK_OF(X509)* inputCerts) 76454aa6d63Sopenharmony_ci{ 76554aa6d63Sopenharmony_ci std::string profile = FindProfileFromOptionalBlocks(); 76654aa6d63Sopenharmony_ci std::map<std::string, std::string>::const_iterator ite = 76754aa6d63Sopenharmony_ci signParams.find(ParamConstants::PARAM_BASIC_PROFILE_SIGNED); 76854aa6d63Sopenharmony_ci if (ite == signParams.end()) { 76954aa6d63Sopenharmony_ci PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, 77054aa6d63Sopenharmony_ci "find PARAM_BASIC_PROFILE_SIGNED failed"); 77154aa6d63Sopenharmony_ci return INVALIDPARAM_ERROR; 77254aa6d63Sopenharmony_ci } 77354aa6d63Sopenharmony_ci bool isProfileWithoutSign = (ParamConstants::DISABLE_SIGN_CODE == ite->second); 77454aa6d63Sopenharmony_ci if (!isProfileWithoutSign) { 77554aa6d63Sopenharmony_ci PKCS7Data p7Data; 77654aa6d63Sopenharmony_ci if (p7Data.Parse(profile) < 0) { 77754aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Parse profile error."); 77854aa6d63Sopenharmony_ci return PARSE_ERROR; 77954aa6d63Sopenharmony_ci } 78054aa6d63Sopenharmony_ci if (p7Data.Verify() < 0) { 78154aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Verify profile pkcs7 failed! Profile is invalid."); 78254aa6d63Sopenharmony_ci return VERIFY_ERROR; 78354aa6d63Sopenharmony_ci } 78454aa6d63Sopenharmony_ci profileContent.clear(); 78554aa6d63Sopenharmony_ci if (p7Data.GetContent(profileContent) < 0) { 78654aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("get content data failed"); 78754aa6d63Sopenharmony_ci return INVALIDPARAM_ERROR; 78854aa6d63Sopenharmony_ci } 78954aa6d63Sopenharmony_ci } else { 79054aa6d63Sopenharmony_ci profileContent = profile; 79154aa6d63Sopenharmony_ci } 79254aa6d63Sopenharmony_ci 79354aa6d63Sopenharmony_ci ProfileInfo info; 79454aa6d63Sopenharmony_ci if (ParseProvision(profileContent, info) != PROVISION_OK) { 79554aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("parse provision error"); 79654aa6d63Sopenharmony_ci return PARSE_ERROR; 79754aa6d63Sopenharmony_ci } 79854aa6d63Sopenharmony_ci if (CheckProfileInfo(info, inputCerts) < 0) { 79954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("Check Profile Info error"); 80054aa6d63Sopenharmony_ci return RET_FAILED; 80154aa6d63Sopenharmony_ci } 80254aa6d63Sopenharmony_ci return 0; 80354aa6d63Sopenharmony_ci} 80454aa6d63Sopenharmony_ci 80554aa6d63Sopenharmony_ciint SignProvider::CheckProfileInfo(const ProfileInfo& info, STACK_OF(X509)* inputCerts)const 80654aa6d63Sopenharmony_ci{ 80754aa6d63Sopenharmony_ci X509* certInProfile = NULL; 80854aa6d63Sopenharmony_ci if (info.type == ProvisionType::RELEASE) { 80954aa6d63Sopenharmony_ci certInProfile = GetCertificate(info.bundleInfo.distributionCertificate); 81054aa6d63Sopenharmony_ci } else if (info.type == ProvisionType::DEBUG) { 81154aa6d63Sopenharmony_ci certInProfile = GetCertificate(info.bundleInfo.developmentCertificate); 81254aa6d63Sopenharmony_ci } else { 81354aa6d63Sopenharmony_ci PrintErrorNumberMsg("NOT_SUPPORT_ERROR", NOT_SUPPORT_ERROR, "Unsupported profile type!"); 81454aa6d63Sopenharmony_ci return NOT_SUPPORT_ERROR; 81554aa6d63Sopenharmony_ci } 81654aa6d63Sopenharmony_ci if (sk_X509_num(inputCerts) > 0 && !CheckInputCertMatchWithProfile(sk_X509_value(inputCerts, 0), 81754aa6d63Sopenharmony_ci certInProfile)) { 81854aa6d63Sopenharmony_ci X509_free(certInProfile); 81954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("input certificates do not match with profile!"); 82054aa6d63Sopenharmony_ci return RET_FAILED; 82154aa6d63Sopenharmony_ci } 82254aa6d63Sopenharmony_ci std::string cn = GetCertificateCN(certInProfile); 82354aa6d63Sopenharmony_ci X509_free(certInProfile); 82454aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGI("certificate in profile: %s", cn.c_str()); 82554aa6d63Sopenharmony_ci if (cn.empty()) { 82654aa6d63Sopenharmony_ci PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "Common name of certificate is empty!"); 82754aa6d63Sopenharmony_ci return CERTIFICATE_ERROR; 82854aa6d63Sopenharmony_ci } 82954aa6d63Sopenharmony_ci return 0; 83054aa6d63Sopenharmony_ci} 83154aa6d63Sopenharmony_ci 83254aa6d63Sopenharmony_cibool SignProvider::CheckInputCertMatchWithProfile(X509* inputCert, X509* certInProfile)const 83354aa6d63Sopenharmony_ci{ 83454aa6d63Sopenharmony_ci return true; 83554aa6d63Sopenharmony_ci} 83654aa6d63Sopenharmony_ci} // namespace SignatureTools 83754aa6d63Sopenharmony_ci} // namespace OHOS