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 "verify_code_signature.h"
1654aa6d63Sopenharmony_ci#include "elf_sign_block.h"
1754aa6d63Sopenharmony_ci#include "constant.h"
1854aa6d63Sopenharmony_ci
1954aa6d63Sopenharmony_cinamespace OHOS {
2054aa6d63Sopenharmony_cinamespace SignatureTools {
2154aa6d63Sopenharmony_cibool VerifyCodeSignature::VerifyHap(std::string file, int64_t offset, int64_t length,
2254aa6d63Sopenharmony_ci                                    std::string fileFormat, std::string profileContent)
2354aa6d63Sopenharmony_ci{
2454aa6d63Sopenharmony_ci    std::string fileFromatTmp = fileFormat;
2554aa6d63Sopenharmony_ci    std::transform(fileFromatTmp.begin(), fileFromatTmp.end(), fileFromatTmp.begin(), ::tolower);
2654aa6d63Sopenharmony_ci    if (std::find(CodeSigning::SUPPORT_FILE_FORM.begin(), CodeSigning::SUPPORT_FILE_FORM.end(),
2754aa6d63Sopenharmony_ci        fileFromatTmp) == CodeSigning::SUPPORT_FILE_FORM.end()) {
2854aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGI("Not hap, hsp or hqf file, skip code signing verify, file type: %s",
2954aa6d63Sopenharmony_ci            fileFromatTmp.c_str());
3054aa6d63Sopenharmony_ci        return true;
3154aa6d63Sopenharmony_ci    }
3254aa6d63Sopenharmony_ci    // 1) generate CodeSignBlock
3354aa6d63Sopenharmony_ci    std::pair<std::string, std::string> pairResult = HapUtils::ParseAppIdentifier(profileContent);
3454aa6d63Sopenharmony_ci    CodeSignBlock csb;
3554aa6d63Sopenharmony_ci    bool generateFlag = GenerateCodeSignBlock(file, offset, length, csb);
3654aa6d63Sopenharmony_ci    if (!generateFlag) {
3754aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("VerifyHap GenerateCodeSignBlock failed, file: %s", file.c_str());
3854aa6d63Sopenharmony_ci        return false;
3954aa6d63Sopenharmony_ci    }
4054aa6d63Sopenharmony_ci    // 2) verify hap
4154aa6d63Sopenharmony_ci    bool verifyFlag = VerifyCodeSign(file, pairResult, csb);
4254aa6d63Sopenharmony_ci    if (!verifyFlag) {
4354aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("VerifyHap VerifyCodeSign failed");
4454aa6d63Sopenharmony_ci        return false;
4554aa6d63Sopenharmony_ci    }
4654aa6d63Sopenharmony_ci    return true;
4754aa6d63Sopenharmony_ci}
4854aa6d63Sopenharmony_ci
4954aa6d63Sopenharmony_cibool VerifyCodeSignature::VerifyElf(std::string file, int64_t offset, int64_t length,
5054aa6d63Sopenharmony_ci                                    std::string fileFormat, std::string profileContent)
5154aa6d63Sopenharmony_ci{
5254aa6d63Sopenharmony_ci    std::transform(fileFormat.begin(), fileFormat.end(), fileFormat.begin(), ::tolower);
5354aa6d63Sopenharmony_ci    if (ELF != fileFormat) {
5454aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGI("Not elf file, skip code signing verify, file type: %s", fileFormat.c_str());
5554aa6d63Sopenharmony_ci        return true;
5654aa6d63Sopenharmony_ci    }
5754aa6d63Sopenharmony_ci    // 1) parse sign block to ElfSignBlock object
5854aa6d63Sopenharmony_ci    std::ifstream signedElf(file, std::ios::binary);
5954aa6d63Sopenharmony_ci    if (!signedElf.is_open()) {
6054aa6d63Sopenharmony_ci        PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open file: " + file + "failed");
6154aa6d63Sopenharmony_ci        return false;
6254aa6d63Sopenharmony_ci    }
6354aa6d63Sopenharmony_ci    signedElf.seekg(offset, std::ios::beg);
6454aa6d63Sopenharmony_ci    std::vector<char> codeSignBlockBytes(length);
6554aa6d63Sopenharmony_ci    signedElf.read(codeSignBlockBytes.data(), codeSignBlockBytes.size());
6654aa6d63Sopenharmony_ci    signedElf.close();
6754aa6d63Sopenharmony_ci    ElfSignBlock elfSignBlock;
6854aa6d63Sopenharmony_ci    bool arrFlag = ElfSignBlock::FromByteArray(*(std::vector<int8_t> *) & codeSignBlockBytes, elfSignBlock);
6954aa6d63Sopenharmony_ci    if (!arrFlag) {
7054aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("parse sign block to ElfCodeSignBlock object failed");
7154aa6d63Sopenharmony_ci        return false;
7254aa6d63Sopenharmony_ci    }
7354aa6d63Sopenharmony_ci    // 2) verify file data
7454aa6d63Sopenharmony_ci    int32_t paddingSize = ElfSignBlock::ComputeMerkleTreePaddingLength(offset);
7554aa6d63Sopenharmony_ci    std::vector<int8_t> &merkleTreeWithPadding = elfSignBlock.GetMerkleTreeWithPadding();
7654aa6d63Sopenharmony_ci    std::vector<int8_t> merkleTree;
7754aa6d63Sopenharmony_ci    merkleTree.insert(merkleTree.end(), merkleTreeWithPadding.begin() + paddingSize, merkleTreeWithPadding.end());
7854aa6d63Sopenharmony_ci    std::ifstream elf(file, std::ios::binary);
7954aa6d63Sopenharmony_ci    bool verifySingleFileFlag = VerifySingleFile(elf, elfSignBlock.GetDataSize(), elfSignBlock.GetSignature(),
8054aa6d63Sopenharmony_ci        elfSignBlock.GetTreeOffset(), merkleTree);
8154aa6d63Sopenharmony_ci    if (!verifySingleFileFlag) {
8254aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("verify elf file data failed");
8354aa6d63Sopenharmony_ci        elf.close();
8454aa6d63Sopenharmony_ci        return false;
8554aa6d63Sopenharmony_ci    }
8654aa6d63Sopenharmony_ci    elf.close();
8754aa6d63Sopenharmony_ci    // 3) check ownerID
8854aa6d63Sopenharmony_ci    if (!profileContent.empty()) {
8954aa6d63Sopenharmony_ci        std::pair<std::string, std::string> pairResult = HapUtils::ParseAppIdentifier(profileContent);
9054aa6d63Sopenharmony_ci        std::vector<int8_t>& signature = elfSignBlock.GetSignature();
9154aa6d63Sopenharmony_ci        std::string signatureStr(signature.begin(), signature.end());
9254aa6d63Sopenharmony_ci        bool checkOwnerIDFlag = CmsUtils::CheckOwnerID(signatureStr, pairResult.first, pairResult.second);
9354aa6d63Sopenharmony_ci        if (!checkOwnerIDFlag) {
9454aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("elf check owner id failed");
9554aa6d63Sopenharmony_ci            return false;
9654aa6d63Sopenharmony_ci        }
9754aa6d63Sopenharmony_ci    }
9854aa6d63Sopenharmony_ci    return true;
9954aa6d63Sopenharmony_ci}
10054aa6d63Sopenharmony_ci
10154aa6d63Sopenharmony_cibool VerifyCodeSignature::VerifyNativeLib(CodeSignBlock& csb, std::string& file, unzFile& zFile,
10254aa6d63Sopenharmony_ci                                          std::pair<std::string, std::string>& pairResult)
10354aa6d63Sopenharmony_ci{
10454aa6d63Sopenharmony_ci    UnzipHandleParam param(csb, pairResult, false);
10554aa6d63Sopenharmony_ci    CodeSigning codeSigning;
10654aa6d63Sopenharmony_ci    bool nativeFlag = codeSigning.GetNativeEntriesFromHap(file, param);
10754aa6d63Sopenharmony_ci    if (!nativeFlag) {
10854aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("verify native libs failed, file: %s", file.c_str());
10954aa6d63Sopenharmony_ci        return false;
11054aa6d63Sopenharmony_ci    }
11154aa6d63Sopenharmony_ci    return true;
11254aa6d63Sopenharmony_ci}
11354aa6d63Sopenharmony_ci
11454aa6d63Sopenharmony_cibool VerifyCodeSignature::VerifyCodeSign(std::string file, std::pair<std::string, std::string>& pairResult,
11554aa6d63Sopenharmony_ci                                         CodeSignBlock& csb)
11654aa6d63Sopenharmony_ci{
11754aa6d63Sopenharmony_ci    // 1) verify hap
11854aa6d63Sopenharmony_ci    std::ifstream hap(file, std::ios::binary);
11954aa6d63Sopenharmony_ci    if (!hap.is_open()) {
12054aa6d63Sopenharmony_ci        PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open file: " + file + "failed");
12154aa6d63Sopenharmony_ci        return false;
12254aa6d63Sopenharmony_ci    }
12354aa6d63Sopenharmony_ci    int64_t dataSize = csb.GetHapInfoSegment().GetSignInfo().GetDataSize();
12454aa6d63Sopenharmony_ci    std::vector<int8_t> signature = csb.GetHapInfoSegment().GetSignInfo().GetSignature();
12554aa6d63Sopenharmony_ci    Extension* ext = csb.GetHapInfoSegment().GetSignInfo()
12654aa6d63Sopenharmony_ci        .GetExtensionByType(MerkleTreeExtension::MERKLE_TREE_INLINED);
12754aa6d63Sopenharmony_ci    MerkleTreeExtension* mte = new MerkleTreeExtension(0, 0, std::vector<int8_t>());
12854aa6d63Sopenharmony_ci    if (mte == nullptr) {
12954aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "system failed to allocate memory for MerkleTreeExtension");
13054aa6d63Sopenharmony_ci        return false;
13154aa6d63Sopenharmony_ci    }
13254aa6d63Sopenharmony_ci    if (ext != nullptr) {
13354aa6d63Sopenharmony_ci        delete mte;
13454aa6d63Sopenharmony_ci        mte = (MerkleTreeExtension*)(ext);
13554aa6d63Sopenharmony_ci    } else {
13654aa6d63Sopenharmony_ci        std::shared_ptr<MerkleTreeExtension> merkleTreeExt(mte);
13754aa6d63Sopenharmony_ci    }
13854aa6d63Sopenharmony_ci    // temporary: merkle tree offset set to zero, change to merkleTreeOffset
13954aa6d63Sopenharmony_ci    bool verifyFlag = VerifySingleFile(hap, dataSize, signature, mte->GetMerkleTreeOffset(),
14054aa6d63Sopenharmony_ci        csb.GetOneMerkleTreeByFileName(CodeSigning::HAP_SIGNATURE_ENTRY_NAME));
14154aa6d63Sopenharmony_ci    if (!verifyFlag) {
14254aa6d63Sopenharmony_ci        return false;
14354aa6d63Sopenharmony_ci    }
14454aa6d63Sopenharmony_ci    hap.close();
14554aa6d63Sopenharmony_ci    std::string signature_(signature.begin(), signature.end());
14654aa6d63Sopenharmony_ci    bool checkOwnerIDFlag = CmsUtils::CheckOwnerID(signature_, pairResult.first, pairResult.second);
14754aa6d63Sopenharmony_ci    if (!checkOwnerIDFlag) {
14854aa6d63Sopenharmony_ci        return false;
14954aa6d63Sopenharmony_ci    }
15054aa6d63Sopenharmony_ci    // 2) verify native libs
15154aa6d63Sopenharmony_ci    unzFile zFile = unzOpen(file.c_str());
15254aa6d63Sopenharmony_ci    if (zFile == NULL) {
15354aa6d63Sopenharmony_ci        PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "unzOpen file: " + file + "failed");
15454aa6d63Sopenharmony_ci        return false;
15554aa6d63Sopenharmony_ci    }
15654aa6d63Sopenharmony_ci    bool verifyNativeLibFlag = VerifyNativeLib(csb, file, zFile, pairResult);
15754aa6d63Sopenharmony_ci    if (!verifyNativeLibFlag) {
15854aa6d63Sopenharmony_ci        return false;
15954aa6d63Sopenharmony_ci    }
16054aa6d63Sopenharmony_ci    unzClose(zFile);
16154aa6d63Sopenharmony_ci    return true;
16254aa6d63Sopenharmony_ci}
16354aa6d63Sopenharmony_ci
16454aa6d63Sopenharmony_cibool VerifyCodeSignature::VerifySingleFile(std::istream& input, int64_t length,
16554aa6d63Sopenharmony_ci                                           std::vector<int8_t> signature,
16654aa6d63Sopenharmony_ci                                           int64_t merkleTreeOffset,
16754aa6d63Sopenharmony_ci                                           std::vector<int8_t> inMerkleTreeBytes)
16854aa6d63Sopenharmony_ci{
16954aa6d63Sopenharmony_ci    std::pair<std::vector<int8_t>, std::vector<int8_t>> pairResult
17054aa6d63Sopenharmony_ci        = GenerateFsVerityDigest(input, length, merkleTreeOffset);
17154aa6d63Sopenharmony_ci    std::vector<int8_t> generatedMerkleTreeBytes = pairResult.second;
17254aa6d63Sopenharmony_ci    // For native libs, inMerkleTreeBytes is null, skip check here
17354aa6d63Sopenharmony_ci    bool verifyFlag = (!inMerkleTreeBytes.empty()) && !AreVectorsEqual(inMerkleTreeBytes, generatedMerkleTreeBytes);
17454aa6d63Sopenharmony_ci    if (verifyFlag) {
17554aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "verify merkle tree bytes failed");
17654aa6d63Sopenharmony_ci        return false;
17754aa6d63Sopenharmony_ci    }
17854aa6d63Sopenharmony_ci    return CmsUtils::VerifySignDataWithUnsignedDataDigest(pairResult.first, signature);
17954aa6d63Sopenharmony_ci}
18054aa6d63Sopenharmony_ci
18154aa6d63Sopenharmony_cibool VerifyCodeSignature::GenerateCodeSignBlock(const std::string& file, int64_t offset,
18254aa6d63Sopenharmony_ci                                                int64_t length, CodeSignBlock& csb)
18354aa6d63Sopenharmony_ci{
18454aa6d63Sopenharmony_ci    // 1) parse sign block to CodeSignBlock object
18554aa6d63Sopenharmony_ci    std::ifstream signedHap(file, std::ios::binary);
18654aa6d63Sopenharmony_ci    if (!signedHap.is_open()) {
18754aa6d63Sopenharmony_ci        PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open file: " + file + "failed");
18854aa6d63Sopenharmony_ci        return false;
18954aa6d63Sopenharmony_ci    }
19054aa6d63Sopenharmony_ci    int32_t fileReadOffset = 0;
19154aa6d63Sopenharmony_ci    // 1.1) skip data part, but fileReadOffset remains at start(0)
19254aa6d63Sopenharmony_ci    signedHap.seekg(offset, std::ios::beg);
19354aa6d63Sopenharmony_ci    // 1.2) parse codeSignBlockHeader
19454aa6d63Sopenharmony_ci    std::vector<char> codeSignBlockHeaderByteArray(CodeSignBlockHeader::Size());
19554aa6d63Sopenharmony_ci    signedHap.read(codeSignBlockHeaderByteArray.data(), codeSignBlockHeaderByteArray.size());
19654aa6d63Sopenharmony_ci    fileReadOffset += signedHap.gcount();
19754aa6d63Sopenharmony_ci    CodeSignBlockHeader* pCodeSignBlockHeader =
19854aa6d63Sopenharmony_ci        CodeSignBlockHeader::FromByteArray(*(std::vector<int8_t>*) &codeSignBlockHeaderByteArray);
19954aa6d63Sopenharmony_ci    if (pCodeSignBlockHeader == nullptr) {
20054aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("Invalid code Sign block header");
20154aa6d63Sopenharmony_ci        signedHap.close();
20254aa6d63Sopenharmony_ci        return false;
20354aa6d63Sopenharmony_ci    }
20454aa6d63Sopenharmony_ci    std::shared_ptr<CodeSignBlockHeader> codeSignBlockHeader(pCodeSignBlockHeader);
20554aa6d63Sopenharmony_ci    csb.SetCodeSignBlockHeader(*codeSignBlockHeader);
20654aa6d63Sopenharmony_ci    int64_t headerBlockSize = csb.GetCodeSignBlockHeader().GetBlockSize();
20754aa6d63Sopenharmony_ci    if (headerBlockSize != length) {
20854aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
20954aa6d63Sopenharmony_ci            "Invalid code Sign block size of setCodeSignBlockHeader");
21054aa6d63Sopenharmony_ci        signedHap.close();
21154aa6d63Sopenharmony_ci        return false;
21254aa6d63Sopenharmony_ci    }
21354aa6d63Sopenharmony_ci    // 2) parse segment headers
21454aa6d63Sopenharmony_ci    for (int i = 0; i < csb.GetCodeSignBlockHeader().GetSegmentNum(); i++) {
21554aa6d63Sopenharmony_ci        std::vector<char> segmentHeaderByteArray(SegmentHeader::SEGMENT_HEADER_LENGTH);
21654aa6d63Sopenharmony_ci        signedHap.read(segmentHeaderByteArray.data(), segmentHeaderByteArray.size());
21754aa6d63Sopenharmony_ci        fileReadOffset += signedHap.gcount();
21854aa6d63Sopenharmony_ci        csb.AddToSegmentList(*SegmentHeader::FromByteArray(*(std::vector<int8_t> *) &segmentHeaderByteArray));
21954aa6d63Sopenharmony_ci    }
22054aa6d63Sopenharmony_ci    // compute merkle tree offset by alignment, based on file start
22154aa6d63Sopenharmony_ci    int64_t computedTreeOffset = GetAlignmentAddr(CodeSignBlock::PAGE_SIZE_4K, fileReadOffset + offset);
22254aa6d63Sopenharmony_ci    // skip zero padding before merkle tree, adds zero padding length to fileReadOffset
22354aa6d63Sopenharmony_ci    signedHap.seekg(computedTreeOffset - offset - fileReadOffset, std::ios::cur);
22454aa6d63Sopenharmony_ci    fileReadOffset += computedTreeOffset - offset - fileReadOffset;
22554aa6d63Sopenharmony_ci    bool parseMerkleTreeFlag = ParseMerkleTree(csb, fileReadOffset, signedHap, computedTreeOffset);
22654aa6d63Sopenharmony_ci    if (!parseMerkleTreeFlag) {
22754aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("GenerateCodeSignBlock parse merkle tree failed.");
22854aa6d63Sopenharmony_ci        return false;
22954aa6d63Sopenharmony_ci    }
23054aa6d63Sopenharmony_ci    signedHap.close();
23154aa6d63Sopenharmony_ci    return true;
23254aa6d63Sopenharmony_ci}
23354aa6d63Sopenharmony_ci
23454aa6d63Sopenharmony_cibool VerifyCodeSignature::ParseSegmentHead(CodeSignBlock& csb, std::ifstream& signedHap,
23554aa6d63Sopenharmony_ci    std::vector<char> &merkleTreeBytes, int32_t &fileReadOffset)
23654aa6d63Sopenharmony_ci{
23754aa6d63Sopenharmony_ci    for (auto& segmentHeader : csb.GetSegmentHeaderList()) {
23854aa6d63Sopenharmony_ci        if (fileReadOffset > segmentHeader.GetSegmentOffset()) {
23954aa6d63Sopenharmony_ci            PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "Invaild offset of merkle tree and segment header");
24054aa6d63Sopenharmony_ci            return false;
24154aa6d63Sopenharmony_ci        }
24254aa6d63Sopenharmony_ci        // get merkle tree bytes
24354aa6d63Sopenharmony_ci        if (fileReadOffset < segmentHeader.GetSegmentOffset()) {
24454aa6d63Sopenharmony_ci            merkleTreeBytes.resize(segmentHeader.GetSegmentOffset() - fileReadOffset);
24554aa6d63Sopenharmony_ci            signedHap.read(merkleTreeBytes.data(), merkleTreeBytes.size());
24654aa6d63Sopenharmony_ci            fileReadOffset += signedHap.gcount();
24754aa6d63Sopenharmony_ci        }
24854aa6d63Sopenharmony_ci        std::vector<char> sh(segmentHeader.GetSegmentSize(), 0);
24954aa6d63Sopenharmony_ci        signedHap.read(sh.data(), sh.size());
25054aa6d63Sopenharmony_ci        fileReadOffset += signedHap.gcount();
25154aa6d63Sopenharmony_ci        int32_t type = segmentHeader.GetType();
25254aa6d63Sopenharmony_ci        if (type == SegmentHeader::CSB_FSVERITY_INFO_SEG) {
25354aa6d63Sopenharmony_ci            // 3) parse fs-verity info segment
25454aa6d63Sopenharmony_ci            FsVerityInfoSegment fsVerityInfoSegment =
25554aa6d63Sopenharmony_ci                FsVerityInfoSegment::FromByteArray(*(std::vector<int8_t> *) & sh);
25654aa6d63Sopenharmony_ci            csb.SetFsVerityInfoSegment(fsVerityInfoSegment);
25754aa6d63Sopenharmony_ci        } else if (type == SegmentHeader::CSB_HAP_META_SEG) {
25854aa6d63Sopenharmony_ci            // 4) parse hap info segment
25954aa6d63Sopenharmony_ci            HapInfoSegment hapInfoSegment = HapInfoSegment::FromByteArray(*(std::vector<int8_t> *) & sh);
26054aa6d63Sopenharmony_ci            csb.SetHapInfoSegment(hapInfoSegment);
26154aa6d63Sopenharmony_ci        } else if (type == SegmentHeader::CSB_NATIVE_LIB_INFO_SEG) {
26254aa6d63Sopenharmony_ci            // 5) parse so info segment
26354aa6d63Sopenharmony_ci            NativeLibInfoSegment nativeLibInfoSegment =
26454aa6d63Sopenharmony_ci                NativeLibInfoSegment::FromByteArray(*(std::vector<int8_t> *) & sh);
26554aa6d63Sopenharmony_ci            csb.SetSoInfoSegment(nativeLibInfoSegment);
26654aa6d63Sopenharmony_ci        }
26754aa6d63Sopenharmony_ci    }
26854aa6d63Sopenharmony_ci
26954aa6d63Sopenharmony_ci    return true;
27054aa6d63Sopenharmony_ci}
27154aa6d63Sopenharmony_ci
27254aa6d63Sopenharmony_cibool VerifyCodeSignature::ParseMerkleTree(CodeSignBlock& csb, int32_t readOffset, std::ifstream& signedHap,
27354aa6d63Sopenharmony_ci                                          int64_t computedTreeOffset)
27454aa6d63Sopenharmony_ci{
27554aa6d63Sopenharmony_ci    std::vector<char> merkleTreeBytes;
27654aa6d63Sopenharmony_ci    int32_t fileReadOffset = readOffset;
27754aa6d63Sopenharmony_ci    bool parseFlag = ParseSegmentHead(csb, signedHap, merkleTreeBytes, fileReadOffset);
27854aa6d63Sopenharmony_ci    if (!parseFlag) {
27954aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("ParsesegmentHead failed");
28054aa6d63Sopenharmony_ci        return false;
28154aa6d63Sopenharmony_ci    }
28254aa6d63Sopenharmony_ci    int32_t blockSize = csb.GetCodeSignBlockHeader().GetBlockSize();
28354aa6d63Sopenharmony_ci    if (fileReadOffset != blockSize) {
28454aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
28554aa6d63Sopenharmony_ci            "Invalid blockSize of getCodeSignBlockHeader");
28654aa6d63Sopenharmony_ci        return false;
28754aa6d63Sopenharmony_ci    }
28854aa6d63Sopenharmony_ci    // parse merkle tree
28954aa6d63Sopenharmony_ci    Extension* extension = csb.GetHapInfoSegment().GetSignInfo().
29054aa6d63Sopenharmony_ci        GetExtensionByType(MerkleTreeExtension::MERKLE_TREE_INLINED);
29154aa6d63Sopenharmony_ci    if (!extension) {
29254aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("Missing merkleTreeExtension in verifycation");
29354aa6d63Sopenharmony_ci        return false;
29454aa6d63Sopenharmony_ci    }
29554aa6d63Sopenharmony_ci    MerkleTreeExtension* mte = (MerkleTreeExtension*)(extension);
29654aa6d63Sopenharmony_ci    if (mte) {
29754aa6d63Sopenharmony_ci        bool merkleTreeFlag = computedTreeOffset != mte->GetMerkleTreeOffset() ||
29854aa6d63Sopenharmony_ci            merkleTreeBytes.size() != mte->GetMerkleTreeSize();
29954aa6d63Sopenharmony_ci        if (merkleTreeFlag) {
30054aa6d63Sopenharmony_ci            PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "Invalid merkle tree offset or tree size");
30154aa6d63Sopenharmony_ci            return false;
30254aa6d63Sopenharmony_ci        }
30354aa6d63Sopenharmony_ci        csb.AddOneMerkleTree(CodeSigning::HAP_SIGNATURE_ENTRY_NAME, *(std::vector<int8_t> *) &merkleTreeBytes);
30454aa6d63Sopenharmony_ci    }
30554aa6d63Sopenharmony_ci    return true;
30654aa6d63Sopenharmony_ci}
30754aa6d63Sopenharmony_ci
30854aa6d63Sopenharmony_ciint64_t VerifyCodeSignature::GetAlignmentAddr(int64_t alignment, int64_t input)
30954aa6d63Sopenharmony_ci{
31054aa6d63Sopenharmony_ci    if (alignment == 0) {
31154aa6d63Sopenharmony_ci        return input;
31254aa6d63Sopenharmony_ci    }
31354aa6d63Sopenharmony_ci    int64_t residual = input % alignment;
31454aa6d63Sopenharmony_ci    if (residual == 0) {
31554aa6d63Sopenharmony_ci        return input;
31654aa6d63Sopenharmony_ci    } else {
31754aa6d63Sopenharmony_ci        return input + (alignment - residual);
31854aa6d63Sopenharmony_ci    }
31954aa6d63Sopenharmony_ci}
32054aa6d63Sopenharmony_ci
32154aa6d63Sopenharmony_cistd::pair<std::vector<int8_t>, std::vector<int8_t>> VerifyCodeSignature::GenerateFsVerityDigest(
32254aa6d63Sopenharmony_ci    std::istream& inputStream, int64_t size, int64_t merkleTreeOffset)
32354aa6d63Sopenharmony_ci{
32454aa6d63Sopenharmony_ci    std::unique_ptr<FsVerityGenerator> fsVerityGenerator = std::make_unique<FsVerityGenerator>();
32554aa6d63Sopenharmony_ci    fsVerityGenerator->GenerateFsVerityDigest(inputStream, size, merkleTreeOffset);
32654aa6d63Sopenharmony_ci    return std::make_pair(fsVerityGenerator->GetFsVerityDigest(), fsVerityGenerator->GetTreeBytes());
32754aa6d63Sopenharmony_ci}
32854aa6d63Sopenharmony_ci
32954aa6d63Sopenharmony_cibool VerifyCodeSignature::AreVectorsEqual(const std::vector<int8_t>& vec1, const std::vector<int8_t>& vec2)
33054aa6d63Sopenharmony_ci{
33154aa6d63Sopenharmony_ci    if (vec1.size() != vec2.size()) {
33254aa6d63Sopenharmony_ci        return false;
33354aa6d63Sopenharmony_ci    }
33454aa6d63Sopenharmony_ci    for (int64_t i = 0; i < vec1.size(); i++) {
33554aa6d63Sopenharmony_ci        if (vec1[i] != vec2[i]) {
33654aa6d63Sopenharmony_ci            return false;
33754aa6d63Sopenharmony_ci        }
33854aa6d63Sopenharmony_ci    }
33954aa6d63Sopenharmony_ci    return true;
34054aa6d63Sopenharmony_ci}
34154aa6d63Sopenharmony_ci} // namespace SignatureTools
34254aa6d63Sopenharmony_ci} // namespace OHOS