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 <cmath> 1654aa6d63Sopenharmony_ci 1754aa6d63Sopenharmony_ci#include "merkle_tree_builder.h" 1854aa6d63Sopenharmony_ci 1954aa6d63Sopenharmony_ciusing namespace OHOS::SignatureTools::Uscript; 2054aa6d63Sopenharmony_cinamespace OHOS { 2154aa6d63Sopenharmony_cinamespace SignatureTools { 2254aa6d63Sopenharmony_ci 2354aa6d63Sopenharmony_ciconst int MerkleTreeBuilder::FSVERITY_HASH_PAGE_SIZE = 4096; 2454aa6d63Sopenharmony_ciconst int64_t MerkleTreeBuilder::INPUTSTREAM_MAX_SIZE = 4503599627370496L; 2554aa6d63Sopenharmony_ciconst int MerkleTreeBuilder::CHUNK_SIZE = 4096; 2654aa6d63Sopenharmony_ciconst long MerkleTreeBuilder::MAX_READ_SIZE = 4194304L; 2754aa6d63Sopenharmony_ciconst int MerkleTreeBuilder::MAX_PROCESSORS = 32; 2854aa6d63Sopenharmony_ciconst int MerkleTreeBuilder::BLOCKINGQUEUE = 4; 2954aa6d63Sopenharmony_ci 3054aa6d63Sopenharmony_civoid MerkleTreeBuilder::SetAlgorithm(const std::string& algorithm) 3154aa6d63Sopenharmony_ci{ 3254aa6d63Sopenharmony_ci mAlgorithm = algorithm; 3354aa6d63Sopenharmony_ci} 3454aa6d63Sopenharmony_ci 3554aa6d63Sopenharmony_civoid MerkleTreeBuilder::TransInputStreamToHashData(std::istream& inputStream, 3654aa6d63Sopenharmony_ci long size, ByteBuffer* outputBuffer, int bufStartIdx) 3754aa6d63Sopenharmony_ci{ 3854aa6d63Sopenharmony_ci if (size == 0 || static_cast<int64_t>(size) > INPUTSTREAM_MAX_SIZE) { 3954aa6d63Sopenharmony_ci SIGNATURE_TOOLS_LOGE("invalid input stream size"); 4054aa6d63Sopenharmony_ci CheckCalculateHashResult = false; 4154aa6d63Sopenharmony_ci return; 4254aa6d63Sopenharmony_ci } 4354aa6d63Sopenharmony_ci std::vector<std::vector<int8_t>> hashes = GetDataHashes(inputStream, size); 4454aa6d63Sopenharmony_ci int32_t writeSize = 0; 4554aa6d63Sopenharmony_ci for (const auto& hash : hashes) { 4654aa6d63Sopenharmony_ci outputBuffer->PutData(writeSize + bufStartIdx, hash.data(), hash.size()); 4754aa6d63Sopenharmony_ci writeSize += hash.size(); 4854aa6d63Sopenharmony_ci } 4954aa6d63Sopenharmony_ci outputBuffer->SetLimit(outputBuffer->GetCapacity() - bufStartIdx); 5054aa6d63Sopenharmony_ci outputBuffer->SetCapacity(outputBuffer->GetCapacity() - bufStartIdx); 5154aa6d63Sopenharmony_ci outputBuffer->SetPosition(writeSize); 5254aa6d63Sopenharmony_ci} 5354aa6d63Sopenharmony_ci 5454aa6d63Sopenharmony_cistd::vector<std::vector<int8_t>> MerkleTreeBuilder::GetDataHashes(std::istream& inputStream, long size) 5554aa6d63Sopenharmony_ci{ 5654aa6d63Sopenharmony_ci int count = (int)(GetChunkCount(size, MAX_READ_SIZE)); 5754aa6d63Sopenharmony_ci int chunks = (int)(GetChunkCount(size, CHUNK_SIZE)); 5854aa6d63Sopenharmony_ci std::vector<std::vector<int8_t>> hashes(chunks); 5954aa6d63Sopenharmony_ci std::vector<std::future<void>> thread_results; 6054aa6d63Sopenharmony_ci long readOffset = 0L; 6154aa6d63Sopenharmony_ci for (int i = 0; i < count; i++) { 6254aa6d63Sopenharmony_ci long readLimit = std::min(readOffset + MAX_READ_SIZE, size); 6354aa6d63Sopenharmony_ci int readSize = (int)((readLimit - readOffset)); 6454aa6d63Sopenharmony_ci int fullChunkSize = (int)(GetFullChunkSize(readSize, CHUNK_SIZE, CHUNK_SIZE)); 6554aa6d63Sopenharmony_ci ByteBuffer* byteBuffer(new ByteBuffer(fullChunkSize)); 6654aa6d63Sopenharmony_ci std::vector<char> buffer(CHUNK_SIZE); 6754aa6d63Sopenharmony_ci int num = 0; 6854aa6d63Sopenharmony_ci int offset = 0; 6954aa6d63Sopenharmony_ci int flag = 0; 7054aa6d63Sopenharmony_ci int len = CHUNK_SIZE; 7154aa6d63Sopenharmony_ci while (num > 0 || flag == 0) { 7254aa6d63Sopenharmony_ci inputStream.read((buffer.data()), len); 7354aa6d63Sopenharmony_ci if (inputStream.fail() && !inputStream.eof()) { 7454aa6d63Sopenharmony_ci PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "Error occurred while reading data"); 7554aa6d63Sopenharmony_ci CheckCalculateHashResult = false; 7654aa6d63Sopenharmony_ci return std::vector<std::vector<int8_t>>(); 7754aa6d63Sopenharmony_ci } 7854aa6d63Sopenharmony_ci num = inputStream.gcount(); 7954aa6d63Sopenharmony_ci byteBuffer->PutData(buffer.data(), num); 8054aa6d63Sopenharmony_ci offset += num; 8154aa6d63Sopenharmony_ci len = std::min(CHUNK_SIZE, readSize - offset); 8254aa6d63Sopenharmony_ci if (len <= 0 || offset == readSize) { 8354aa6d63Sopenharmony_ci break; 8454aa6d63Sopenharmony_ci } 8554aa6d63Sopenharmony_ci flag = 1; 8654aa6d63Sopenharmony_ci } 8754aa6d63Sopenharmony_ci if (offset != readSize) { 8854aa6d63Sopenharmony_ci PrintErrorNumberMsg("READ_FILE_ERROR", IO_ERROR, "Error reading buffer from input"); 8954aa6d63Sopenharmony_ci CheckCalculateHashResult = false; 9054aa6d63Sopenharmony_ci return std::vector<std::vector<int8_t>>(); 9154aa6d63Sopenharmony_ci } 9254aa6d63Sopenharmony_ci byteBuffer->Flip(); 9354aa6d63Sopenharmony_ci int readChunkIndex = (int)(GetFullChunkSize(MAX_READ_SIZE, CHUNK_SIZE, i)); 9454aa6d63Sopenharmony_ci thread_results.push_back(mPools->Enqueue(&MerkleTreeBuilder::RunHashTask, this, std::ref(hashes), 9554aa6d63Sopenharmony_ci byteBuffer, readChunkIndex, 0)); 9654aa6d63Sopenharmony_ci readOffset += readSize; 9754aa6d63Sopenharmony_ci } 9854aa6d63Sopenharmony_ci for (auto& thread_result : thread_results) { 9954aa6d63Sopenharmony_ci thread_result.wait(); 10054aa6d63Sopenharmony_ci } 10154aa6d63Sopenharmony_ci return hashes; 10254aa6d63Sopenharmony_ci} 10354aa6d63Sopenharmony_ci 10454aa6d63Sopenharmony_ciByteBuffer* MerkleTreeBuilder::Slice(ByteBuffer* buffer, int begin, int end) 10554aa6d63Sopenharmony_ci{ 10654aa6d63Sopenharmony_ci ByteBuffer* tmpBuffer = buffer->Duplicate(); 10754aa6d63Sopenharmony_ci tmpBuffer->SetPosition(0); 10854aa6d63Sopenharmony_ci tmpBuffer->SetLimit(end); 10954aa6d63Sopenharmony_ci tmpBuffer->SetPosition(begin); 11054aa6d63Sopenharmony_ci return &tmpBuffer->slice_for_codesigning(); 11154aa6d63Sopenharmony_ci} 11254aa6d63Sopenharmony_ci 11354aa6d63Sopenharmony_cistd::vector<int64_t> MerkleTreeBuilder::GetOffsetArrays(long dataSize, int digestSize) 11454aa6d63Sopenharmony_ci{ 11554aa6d63Sopenharmony_ci std::vector<long> levelSize = GetLevelSize(dataSize, digestSize); 11654aa6d63Sopenharmony_ci std::vector<int64_t> levelOffset(levelSize.size() + 1); 11754aa6d63Sopenharmony_ci levelOffset[0] = 0; 11854aa6d63Sopenharmony_ci for (int i = 0; i < levelSize.size(); i++) { 11954aa6d63Sopenharmony_ci levelOffset[i + 1] = levelOffset[i] + levelSize[levelSize.size() - i - 1]; 12054aa6d63Sopenharmony_ci } 12154aa6d63Sopenharmony_ci return levelOffset; 12254aa6d63Sopenharmony_ci} 12354aa6d63Sopenharmony_ci 12454aa6d63Sopenharmony_cistd::vector<long> MerkleTreeBuilder::GetLevelSize(long dataSize, int digestSize) 12554aa6d63Sopenharmony_ci{ 12654aa6d63Sopenharmony_ci std::vector<long> levelSize; 12754aa6d63Sopenharmony_ci 12854aa6d63Sopenharmony_ci long fullChunkSize = 0L; 12954aa6d63Sopenharmony_ci long originalDataSize = dataSize; 13054aa6d63Sopenharmony_ci do { 13154aa6d63Sopenharmony_ci fullChunkSize = GetFullChunkSize(originalDataSize, CHUNK_SIZE, digestSize); 13254aa6d63Sopenharmony_ci int size = GetFullChunkSize(fullChunkSize, CHUNK_SIZE, CHUNK_SIZE); 13354aa6d63Sopenharmony_ci levelSize.push_back(size); 13454aa6d63Sopenharmony_ci originalDataSize = fullChunkSize; 13554aa6d63Sopenharmony_ci } while (fullChunkSize > CHUNK_SIZE); 13654aa6d63Sopenharmony_ci return levelSize; 13754aa6d63Sopenharmony_ci} 13854aa6d63Sopenharmony_ci 13954aa6d63Sopenharmony_civoid MerkleTreeBuilder::RunHashTask(std::vector<std::vector<int8_t>>& hashes, 14054aa6d63Sopenharmony_ci ByteBuffer* buffer, int readChunkIndex, int bufStartIdx) 14154aa6d63Sopenharmony_ci{ 14254aa6d63Sopenharmony_ci int offset = 0; 14354aa6d63Sopenharmony_ci 14454aa6d63Sopenharmony_ci std::shared_ptr<ByteBuffer> bufferPtr(buffer); 14554aa6d63Sopenharmony_ci int bufferSize = bufferPtr->GetCapacity(); 14654aa6d63Sopenharmony_ci int index = readChunkIndex; 14754aa6d63Sopenharmony_ci while (offset < bufferSize) { 14854aa6d63Sopenharmony_ci ByteBuffer* chunk = Slice(bufferPtr.get(), offset, offset + CHUNK_SIZE); 14954aa6d63Sopenharmony_ci std::vector<int8_t> tmpByte(CHUNK_SIZE); 15054aa6d63Sopenharmony_ci chunk->GetData(offset + bufStartIdx, tmpByte.data(), CHUNK_SIZE); 15154aa6d63Sopenharmony_ci DigestUtils digestUtils(HASH_SHA256); 15254aa6d63Sopenharmony_ci std::string tmpByteStr(tmpByte.begin(), tmpByte.end()); 15354aa6d63Sopenharmony_ci digestUtils.AddData(tmpByteStr); 15454aa6d63Sopenharmony_ci std::string result = digestUtils.Result(DigestUtils::Type::BINARY); 15554aa6d63Sopenharmony_ci std::vector<int8_t> hashEle; 15654aa6d63Sopenharmony_ci for (int i = 0; i < result.size(); i++) { 15754aa6d63Sopenharmony_ci hashEle.push_back(result[i]); 15854aa6d63Sopenharmony_ci } 15954aa6d63Sopenharmony_ci hashes[index++] = hashEle; 16054aa6d63Sopenharmony_ci offset += CHUNK_SIZE; 16154aa6d63Sopenharmony_ci delete chunk; 16254aa6d63Sopenharmony_ci } 16354aa6d63Sopenharmony_ci} 16454aa6d63Sopenharmony_ci 16554aa6d63Sopenharmony_civoid MerkleTreeBuilder::TransInputDataToHashData(ByteBuffer* inputBuffer, ByteBuffer* outputBuffer, 16654aa6d63Sopenharmony_ci int64_t inputStartIdx, int64_t outputStartIdx) 16754aa6d63Sopenharmony_ci{ 16854aa6d63Sopenharmony_ci long size = inputBuffer->GetCapacity(); 16954aa6d63Sopenharmony_ci int chunks = (int)GetChunkCount(size, CHUNK_SIZE); 17054aa6d63Sopenharmony_ci std::vector<std::vector<int8_t>> hashes(chunks); 17154aa6d63Sopenharmony_ci long readOffset = 0L; 17254aa6d63Sopenharmony_ci int startChunkIndex = 0; 17354aa6d63Sopenharmony_ci while (readOffset < size) { 17454aa6d63Sopenharmony_ci long readLimit = std::min(readOffset + MAX_READ_SIZE, size); 17554aa6d63Sopenharmony_ci ByteBuffer* buffer = Slice(inputBuffer, (int)readOffset, (int)readLimit); 17654aa6d63Sopenharmony_ci buffer->SetPosition(0); 17754aa6d63Sopenharmony_ci int readChunkIndex = startChunkIndex; 17854aa6d63Sopenharmony_ci RunHashTask(hashes, buffer, readChunkIndex, inputStartIdx); 17954aa6d63Sopenharmony_ci int readSize = (int)(readLimit - readOffset); 18054aa6d63Sopenharmony_ci startChunkIndex += (int)GetChunkCount(readSize, CHUNK_SIZE); 18154aa6d63Sopenharmony_ci readOffset += readSize; 18254aa6d63Sopenharmony_ci inputStartIdx += readSize; 18354aa6d63Sopenharmony_ci } 18454aa6d63Sopenharmony_ci int32_t writeSize = 0; 18554aa6d63Sopenharmony_ci for (const auto& hash : hashes) { 18654aa6d63Sopenharmony_ci outputBuffer->PutData(writeSize + outputStartIdx, hash.data(), hash.size()); 18754aa6d63Sopenharmony_ci writeSize += hash.size(); 18854aa6d63Sopenharmony_ci } 18954aa6d63Sopenharmony_ci} 19054aa6d63Sopenharmony_ci 19154aa6d63Sopenharmony_ciOHOS::SignatureTools::MerkleTreeBuilder::MerkleTreeBuilder() :mPools(new Uscript::ThreadPool(POOL_SIZE)) 19254aa6d63Sopenharmony_ci{ 19354aa6d63Sopenharmony_ci CheckCalculateHashResult = true; 19454aa6d63Sopenharmony_ci} 19554aa6d63Sopenharmony_ci 19654aa6d63Sopenharmony_ciMerkleTree* MerkleTreeBuilder::GenerateMerkleTree(std::istream& inputStream, long size, 19754aa6d63Sopenharmony_ci const FsVerityHashAlgorithm& fsVerityHashAlgorithm) 19854aa6d63Sopenharmony_ci{ 19954aa6d63Sopenharmony_ci SetAlgorithm(fsVerityHashAlgorithm.GetHashAlgorithm()); 20054aa6d63Sopenharmony_ci int digestSize = fsVerityHashAlgorithm.GetOutputByteSize(); 20154aa6d63Sopenharmony_ci std::vector<int64_t> offsetArrays = GetOffsetArrays(size, digestSize); 20254aa6d63Sopenharmony_ci std::unique_ptr<ByteBuffer> allHashBuffer = std::make_unique<ByteBuffer> 20354aa6d63Sopenharmony_ci (ByteBuffer(offsetArrays[offsetArrays.size() - 1])); 20454aa6d63Sopenharmony_ci GenerateHashDataByInputData(inputStream, size, allHashBuffer.get(), offsetArrays, digestSize); 20554aa6d63Sopenharmony_ci GenerateHashDataByHashData(allHashBuffer.get(), offsetArrays, digestSize); 20654aa6d63Sopenharmony_ci 20754aa6d63Sopenharmony_ci if (CheckCalculateHashResult) { 20854aa6d63Sopenharmony_ci return GetMerkleTree(allHashBuffer.get(), size, fsVerityHashAlgorithm); 20954aa6d63Sopenharmony_ci } 21054aa6d63Sopenharmony_ci return nullptr; 21154aa6d63Sopenharmony_ci} 21254aa6d63Sopenharmony_ci 21354aa6d63Sopenharmony_civoid MerkleTreeBuilder::GenerateHashDataByInputData(std::istream& inputStream, long size, ByteBuffer* outputBuffer, 21454aa6d63Sopenharmony_ci std::vector<int64_t>& offsetArrays, int digestSize) 21554aa6d63Sopenharmony_ci{ 21654aa6d63Sopenharmony_ci int64_t inputDataOffsetBegin = offsetArrays[offsetArrays.size() - 2]; 21754aa6d63Sopenharmony_ci int64_t inputDataOffsetEnd = offsetArrays[offsetArrays.size() - 1]; 21854aa6d63Sopenharmony_ci ByteBuffer* hashBuffer = Slice(outputBuffer, 0, inputDataOffsetEnd); 21954aa6d63Sopenharmony_ci TransInputStreamToHashData(inputStream, size, hashBuffer, inputDataOffsetBegin); 22054aa6d63Sopenharmony_ci DataRoundupChunkSize(hashBuffer, size, digestSize); 22154aa6d63Sopenharmony_ci delete hashBuffer; 22254aa6d63Sopenharmony_ci} 22354aa6d63Sopenharmony_ci 22454aa6d63Sopenharmony_civoid MerkleTreeBuilder::GenerateHashDataByHashData(ByteBuffer* buffer, 22554aa6d63Sopenharmony_ci std::vector<int64_t>& offsetArrays, int digestSize) 22654aa6d63Sopenharmony_ci{ 22754aa6d63Sopenharmony_ci for (int i = offsetArrays.size() - 3; i >= 0; i--) { 22854aa6d63Sopenharmony_ci int64_t generateOffset = offsetArrays[i]; 22954aa6d63Sopenharmony_ci int64_t originalOffset = offsetArrays[i + 1]; 23054aa6d63Sopenharmony_ci ByteBuffer* generateHashBuffer = Slice(buffer, offsetArrays[i], offsetArrays[i + 1] + offsetArrays[i]); 23154aa6d63Sopenharmony_ci ByteBuffer* readOnlyBuffer = buffer->Duplicate(); 23254aa6d63Sopenharmony_ci ByteBuffer* originalHashBuffer = Slice(readOnlyBuffer, offsetArrays[i + 1], offsetArrays[i + 2]); 23354aa6d63Sopenharmony_ci TransInputDataToHashData(originalHashBuffer, generateHashBuffer, originalOffset, generateOffset); 23454aa6d63Sopenharmony_ci DataRoundupChunkSize(generateHashBuffer, originalHashBuffer->GetCapacity(), digestSize); 23554aa6d63Sopenharmony_ci delete originalHashBuffer; 23654aa6d63Sopenharmony_ci delete readOnlyBuffer; 23754aa6d63Sopenharmony_ci delete generateHashBuffer; 23854aa6d63Sopenharmony_ci } 23954aa6d63Sopenharmony_ci} 24054aa6d63Sopenharmony_ci 24154aa6d63Sopenharmony_ciMerkleTree* MerkleTreeBuilder::GetMerkleTree(ByteBuffer* dataBuffer, long inputDataSize, 24254aa6d63Sopenharmony_ci FsVerityHashAlgorithm fsVerityHashAlgorithm) 24354aa6d63Sopenharmony_ci{ 24454aa6d63Sopenharmony_ci int digestSize = fsVerityHashAlgorithm.GetOutputByteSize(); 24554aa6d63Sopenharmony_ci dataBuffer->Flip(); 24654aa6d63Sopenharmony_ci std::vector<int8_t> rootHash; 24754aa6d63Sopenharmony_ci std::vector<int8_t> tree; 24854aa6d63Sopenharmony_ci if (inputDataSize < FSVERITY_HASH_PAGE_SIZE) { 24954aa6d63Sopenharmony_ci ByteBuffer* fsVerityHashPageBuffer = Slice(dataBuffer, 0, digestSize); 25054aa6d63Sopenharmony_ci rootHash = std::vector<int8_t>(digestSize); 25154aa6d63Sopenharmony_ci fsVerityHashPageBuffer->GetByte((int8_t*)rootHash.data(), digestSize); 25254aa6d63Sopenharmony_ci if (fsVerityHashPageBuffer != nullptr) { 25354aa6d63Sopenharmony_ci delete fsVerityHashPageBuffer; 25454aa6d63Sopenharmony_ci fsVerityHashPageBuffer = nullptr; 25554aa6d63Sopenharmony_ci } 25654aa6d63Sopenharmony_ci } else { 25754aa6d63Sopenharmony_ci tree = std::vector<int8_t>(dataBuffer->GetBufferPtr(), dataBuffer->GetBufferPtr() + dataBuffer->GetCapacity()); 25854aa6d63Sopenharmony_ci ByteBuffer* fsVerityHashPageBuffer = Slice(dataBuffer, 0, FSVERITY_HASH_PAGE_SIZE); 25954aa6d63Sopenharmony_ci std::vector<int8_t> fsVerityHashPage(FSVERITY_HASH_PAGE_SIZE); 26054aa6d63Sopenharmony_ci fsVerityHashPageBuffer->GetData(0, fsVerityHashPage.data(), FSVERITY_HASH_PAGE_SIZE); 26154aa6d63Sopenharmony_ci DigestUtils digestUtils(HASH_SHA256); 26254aa6d63Sopenharmony_ci std::string fsVerityHashPageStr(fsVerityHashPage.begin(), fsVerityHashPage.end()); 26354aa6d63Sopenharmony_ci digestUtils.AddData(fsVerityHashPageStr); 26454aa6d63Sopenharmony_ci std::string result = digestUtils.Result(DigestUtils::Type::BINARY); 26554aa6d63Sopenharmony_ci for (int i = 0; i < static_cast<int>(result.size()); i++) { 26654aa6d63Sopenharmony_ci rootHash.push_back(result[i]); 26754aa6d63Sopenharmony_ci } 26854aa6d63Sopenharmony_ci if (fsVerityHashPageBuffer != nullptr) { 26954aa6d63Sopenharmony_ci delete fsVerityHashPageBuffer; 27054aa6d63Sopenharmony_ci fsVerityHashPageBuffer = nullptr; 27154aa6d63Sopenharmony_ci } 27254aa6d63Sopenharmony_ci } 27354aa6d63Sopenharmony_ci 27454aa6d63Sopenharmony_ci return new MerkleTree(rootHash, tree, fsVerityHashAlgorithm); 27554aa6d63Sopenharmony_ci} 27654aa6d63Sopenharmony_ci 27754aa6d63Sopenharmony_civoid MerkleTreeBuilder::DataRoundupChunkSize(ByteBuffer* data, long originalDataSize, int digestSize) 27854aa6d63Sopenharmony_ci{ 27954aa6d63Sopenharmony_ci long fullChunkSize = GetFullChunkSize(originalDataSize, CHUNK_SIZE, digestSize); 28054aa6d63Sopenharmony_ci int diffValue = (int)(fullChunkSize % CHUNK_SIZE); 28154aa6d63Sopenharmony_ci if (diffValue > 0) { 28254aa6d63Sopenharmony_ci std::vector<int8_t> padding(CHUNK_SIZE - diffValue); 28354aa6d63Sopenharmony_ci data->SetPosition(data->GetPosition() + (CHUNK_SIZE - diffValue)); 28454aa6d63Sopenharmony_ci } 28554aa6d63Sopenharmony_ci} 28654aa6d63Sopenharmony_ci 28754aa6d63Sopenharmony_cilong MerkleTreeBuilder::GetChunkCount(long dataSize, long divisor) 28854aa6d63Sopenharmony_ci{ 28954aa6d63Sopenharmony_ci return (long)std::ceil((double)dataSize / (double)divisor); 29054aa6d63Sopenharmony_ci} 29154aa6d63Sopenharmony_ci 29254aa6d63Sopenharmony_cilong MerkleTreeBuilder::GetFullChunkSize(long dataSize, long divisor, long multiplier) 29354aa6d63Sopenharmony_ci{ 29454aa6d63Sopenharmony_ci return GetChunkCount(dataSize, divisor) * multiplier; 29554aa6d63Sopenharmony_ci} 29654aa6d63Sopenharmony_ci} // namespace SignatureTools 29754aa6d63Sopenharmony_ci} // namespace OHOS