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