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