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