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
1654aa6d63Sopenharmony_ci#include "hap_signer_block_utils.h"
1754aa6d63Sopenharmony_ci#include <cinttypes>
1854aa6d63Sopenharmony_ci#include <climits>
1954aa6d63Sopenharmony_ci#include <vector>
2054aa6d63Sopenharmony_ci
2154aa6d63Sopenharmony_ci#include "signature_info.h"
2254aa6d63Sopenharmony_ci#include "algorithm"
2354aa6d63Sopenharmony_ci#include "openssl/evp.h"
2454aa6d63Sopenharmony_ci#include "securec.h"
2554aa6d63Sopenharmony_ci#include "byte_buffer_data_source.h"
2654aa6d63Sopenharmony_ci#include "file_data_source.h"
2754aa6d63Sopenharmony_ci#include "digest_common.h"
2854aa6d63Sopenharmony_ci//#include "verify_hap_openssl_utils.h"
2954aa6d63Sopenharmony_ci#include "signature_tools_log.h"
3054aa6d63Sopenharmony_ci#include "signature_tools_errno.h"
3154aa6d63Sopenharmony_ci
3254aa6d63Sopenharmony_cinamespace OHOS {
3354aa6d63Sopenharmony_cinamespace SignatureTools {
3454aa6d63Sopenharmony_ciconst int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW_OLD = 2334950737560224072LL;
3554aa6d63Sopenharmony_ciconst int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH_OLD = 3617552046287187010LL;
3654aa6d63Sopenharmony_ciconst int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW = 7451613641622775868LL;
3754aa6d63Sopenharmony_ciconst int64_t HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH = 4497797983070462062LL;
3854aa6d63Sopenharmony_ci
3954aa6d63Sopenharmony_ci/* 1MB = 1024 * 1024 Bytes */
4054aa6d63Sopenharmony_ciconst int64_t HapSignerBlockUtils::CHUNK_SIZE = 1048576LL;
4154aa6d63Sopenharmony_ci
4254aa6d63Sopenharmony_ciconst int32_t HapSignerBlockUtils::HAP_SIG_BLOCK_MIN_SIZE = 32;
4354aa6d63Sopenharmony_ciconst int32_t HapSignerBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH = 32;
4454aa6d63Sopenharmony_ci
4554aa6d63Sopenharmony_ciconst int32_t HapSignerBlockUtils::ZIP_EOCD_SEG_MIN_SIZE = 22;
4654aa6d63Sopenharmony_ciconst int32_t HapSignerBlockUtils::ZIP_EOCD_SEGMENT_FLAG = 0x06054b50;
4754aa6d63Sopenharmony_ciconst int32_t HapSignerBlockUtils::ZIP_EOCD_COMMENT_LENGTH_OFFSET = 20;
4854aa6d63Sopenharmony_ciconst int32_t HapSignerBlockUtils::ZIP_CD_OFFSET_IN_EOCD = 16;
4954aa6d63Sopenharmony_ciconst int32_t HapSignerBlockUtils::ZIP_CD_SIZE_OFFSET_IN_EOCD = 12;
5054aa6d63Sopenharmony_ciconst int32_t HapSignerBlockUtils::ZIP_BLOCKS_NUM_NEED_DIGEST = 3;
5154aa6d63Sopenharmony_ci
5254aa6d63Sopenharmony_ciconst char HapSignerBlockUtils::ZIP_FIRST_LEVEL_CHUNK_PREFIX = 0x5a;
5354aa6d63Sopenharmony_ciconst char HapSignerBlockUtils::ZIP_SECOND_LEVEL_CHUNK_PREFIX = 0xa5;
5454aa6d63Sopenharmony_ci
5554aa6d63Sopenharmony_ci/*
5654aa6d63Sopenharmony_ci * The package of hap is ZIP format, and contains four segments: contents of Zip entry,
5754aa6d63Sopenharmony_ci * hap signatures block, central directory and end of central directory.
5854aa6d63Sopenharmony_ci * The function will find the data segment of hap signature block from hap file.
5954aa6d63Sopenharmony_ci */
6054aa6d63Sopenharmony_cibool HapSignerBlockUtils::FindHapSignature(RandomAccessFile& hapFile, SignatureInfo& signInfo)
6154aa6d63Sopenharmony_ci{
6254aa6d63Sopenharmony_ci    std::pair<ByteBuffer, int64_t> eocdAndOffsetInFile;
6354aa6d63Sopenharmony_ci    if (!FindEocdInHap(hapFile, eocdAndOffsetInFile)) {
6454aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("find EoCD failed");
6554aa6d63Sopenharmony_ci        return false;
6654aa6d63Sopenharmony_ci    }
6754aa6d63Sopenharmony_ci
6854aa6d63Sopenharmony_ci    signInfo.hapEocd = eocdAndOffsetInFile.first;
6954aa6d63Sopenharmony_ci    signInfo.hapEocdOffset = eocdAndOffsetInFile.second;
7054aa6d63Sopenharmony_ci    if (!GetCentralDirectoryOffset(signInfo.hapEocd, signInfo.hapEocdOffset, signInfo.hapCentralDirOffset)) {
7154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("get CD offset failed");
7254aa6d63Sopenharmony_ci        PrintErrorNumberMsg("verify", VERIFY_ERROR, "ZIP End of Central Directory not found");
7354aa6d63Sopenharmony_ci        return false;
7454aa6d63Sopenharmony_ci    }
7554aa6d63Sopenharmony_ci
7654aa6d63Sopenharmony_ci    if (!FindHapSigningBlock(hapFile, signInfo.hapCentralDirOffset, signInfo)) {
7754aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("find signing block failed");
7854aa6d63Sopenharmony_ci        return false;
7954aa6d63Sopenharmony_ci    }
8054aa6d63Sopenharmony_ci    return true;
8154aa6d63Sopenharmony_ci}
8254aa6d63Sopenharmony_ci
8354aa6d63Sopenharmony_cibool HapSignerBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, std::pair<ByteBuffer, int64_t>& eocd)
8454aa6d63Sopenharmony_ci{
8554aa6d63Sopenharmony_ci    /*
8654aa6d63Sopenharmony_ci     * EoCD has an optional comment block. Most hap packages do not contain this block.
8754aa6d63Sopenharmony_ci     * For hap packages without comment block, EoCD is the last 22 bytes of hap file.
8854aa6d63Sopenharmony_ci     * Try as a hap without comment block first to avoid unnecessarily reading more data.
8954aa6d63Sopenharmony_ci     */
9054aa6d63Sopenharmony_ci    if (FindEocdInHap(hapFile, 0, eocd)) {
9154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGD("Find EoCD of Zip file");
9254aa6d63Sopenharmony_ci        return true;
9354aa6d63Sopenharmony_ci    }
9454aa6d63Sopenharmony_ci    /*
9554aa6d63Sopenharmony_ci     * If EoCD contain the comment block, we should find it from the offset of (fileLen - maxCommentSize - 22).
9654aa6d63Sopenharmony_ci     * The max size of comment block is 65535, because the comment length is an unsigned 16-bit number.
9754aa6d63Sopenharmony_ci     */
9854aa6d63Sopenharmony_ci    return FindEocdInHap(hapFile, USHRT_MAX, eocd);
9954aa6d63Sopenharmony_ci}
10054aa6d63Sopenharmony_ci
10154aa6d63Sopenharmony_cibool HapSignerBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, unsigned short maxCommentSize,
10254aa6d63Sopenharmony_ci                                        std::pair<ByteBuffer, int64_t>& eocd)
10354aa6d63Sopenharmony_ci{
10454aa6d63Sopenharmony_ci    int64_t fileLength = hapFile.GetLength();
10554aa6d63Sopenharmony_ci    /* check whether has enough space for EoCD in the file. */
10654aa6d63Sopenharmony_ci    if (fileLength < ZIP_EOCD_SEG_MIN_SIZE) {
10754aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("file length %" PRId64 " is too smaller", fileLength);
10854aa6d63Sopenharmony_ci        return false;
10954aa6d63Sopenharmony_ci    }
11054aa6d63Sopenharmony_ci
11154aa6d63Sopenharmony_ci    int32_t searchRange = static_cast<int>(maxCommentSize) + ZIP_EOCD_SEG_MIN_SIZE;
11254aa6d63Sopenharmony_ci    if (fileLength < static_cast<int64_t>(searchRange)) {
11354aa6d63Sopenharmony_ci        searchRange = static_cast<int>(fileLength);
11454aa6d63Sopenharmony_ci    }
11554aa6d63Sopenharmony_ci
11654aa6d63Sopenharmony_ci    ByteBuffer searchEocdBuffer(searchRange);
11754aa6d63Sopenharmony_ci    int64_t searchRangeOffset = fileLength - searchEocdBuffer.GetCapacity();
11854aa6d63Sopenharmony_ci    int64_t ret = hapFile.ReadFileFullyFromOffset(searchEocdBuffer, searchRangeOffset);
11954aa6d63Sopenharmony_ci    if (ret < 0) {
12054aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("read data from hap file error: %" PRId64, ret);
12154aa6d63Sopenharmony_ci        return false;
12254aa6d63Sopenharmony_ci    }
12354aa6d63Sopenharmony_ci
12454aa6d63Sopenharmony_ci    int32_t eocdOffsetInSearchBuffer = 0;
12554aa6d63Sopenharmony_ci    if (!FindEocdInSearchBuffer(searchEocdBuffer, eocdOffsetInSearchBuffer)) {
12654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("eocd is not found");
12754aa6d63Sopenharmony_ci        return false;
12854aa6d63Sopenharmony_ci    }
12954aa6d63Sopenharmony_ci
13054aa6d63Sopenharmony_ci    searchEocdBuffer.SetPosition(eocdOffsetInSearchBuffer);
13154aa6d63Sopenharmony_ci    searchEocdBuffer.Slice();
13254aa6d63Sopenharmony_ci    eocd.first = searchEocdBuffer;
13354aa6d63Sopenharmony_ci    eocd.second = searchRangeOffset + eocdOffsetInSearchBuffer;
13454aa6d63Sopenharmony_ci    return true;
13554aa6d63Sopenharmony_ci}
13654aa6d63Sopenharmony_ci
13754aa6d63Sopenharmony_ci
13854aa6d63Sopenharmony_ci/*
13954aa6d63Sopenharmony_ci* 4-bytes: End of central directory flag
14054aa6d63Sopenharmony_ci* 2-bytes: Number of this disk
14154aa6d63Sopenharmony_ci* 2-bytes: Number of the disk with the start of central directory
14254aa6d63Sopenharmony_ci* 2-bytes: Total number of entries in the central directory on this disk
14354aa6d63Sopenharmony_ci* 2-bytes: Total number of entries in the central directory
14454aa6d63Sopenharmony_ci* 4-bytes: Size of central directory
14554aa6d63Sopenharmony_ci* 4-bytes: offset of central directory in zip file
14654aa6d63Sopenharmony_ci* 2-bytes: ZIP file comment length, the value n is in the range of [0, 65535]
14754aa6d63Sopenharmony_ci* n-bytes: ZIP Comment block data
14854aa6d63Sopenharmony_ci*
14954aa6d63Sopenharmony_ci* This function find Eocd by searching Eocd flag from input buffer(searchBuffer) and
15054aa6d63Sopenharmony_ci* making sure the comment length is equal to the expected value.
15154aa6d63Sopenharmony_ci*/
15254aa6d63Sopenharmony_cibool HapSignerBlockUtils::FindEocdInSearchBuffer(ByteBuffer& searchBuffer, int& offset)
15354aa6d63Sopenharmony_ci{
15454aa6d63Sopenharmony_ci    int32_t searchBufferSize = searchBuffer.GetCapacity();
15554aa6d63Sopenharmony_ci    if (searchBufferSize < ZIP_EOCD_SEG_MIN_SIZE) {
15654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("The size of searchBuffer %d is smaller than min size of Eocd",
15754aa6d63Sopenharmony_ci                             searchBufferSize);
15854aa6d63Sopenharmony_ci        return false;
15954aa6d63Sopenharmony_ci    }
16054aa6d63Sopenharmony_ci
16154aa6d63Sopenharmony_ci    int32_t calcCurrentOffset = searchBufferSize - ZIP_EOCD_SEG_MIN_SIZE;
16254aa6d63Sopenharmony_ci    while (calcCurrentOffset >= 0) {
16354aa6d63Sopenharmony_ci        int32_t hapEocdSegmentFlag;
16454aa6d63Sopenharmony_ci        if (searchBuffer.GetInt32(calcCurrentOffset, hapEocdSegmentFlag) &&
16554aa6d63Sopenharmony_ci            (hapEocdSegmentFlag == ZIP_EOCD_SEGMENT_FLAG)) {
16654aa6d63Sopenharmony_ci            unsigned short commentLength;
16754aa6d63Sopenharmony_ci            int32_t expectedCommentLength = searchBufferSize - ZIP_EOCD_SEG_MIN_SIZE - calcCurrentOffset;
16854aa6d63Sopenharmony_ci            if (searchBuffer.GetUInt16(calcCurrentOffset + ZIP_EOCD_COMMENT_LENGTH_OFFSET, commentLength) &&
16954aa6d63Sopenharmony_ci                static_cast<int>(commentLength) == expectedCommentLength) {
17054aa6d63Sopenharmony_ci                offset = calcCurrentOffset;
17154aa6d63Sopenharmony_ci                return true;
17254aa6d63Sopenharmony_ci            }
17354aa6d63Sopenharmony_ci        }
17454aa6d63Sopenharmony_ci        calcCurrentOffset--;
17554aa6d63Sopenharmony_ci    }
17654aa6d63Sopenharmony_ci    return false;
17754aa6d63Sopenharmony_ci}
17854aa6d63Sopenharmony_ci
17954aa6d63Sopenharmony_cibool HapSignerBlockUtils::GetCentralDirectoryOffset(ByteBuffer& eocd, int64_t eocdOffset,
18054aa6d63Sopenharmony_ci                                                    int64_t& centralDirectoryOffset)
18154aa6d63Sopenharmony_ci{
18254aa6d63Sopenharmony_ci    uint32_t offsetValue;
18354aa6d63Sopenharmony_ci    uint32_t sizeValue;
18454aa6d63Sopenharmony_ci    if (!eocd.GetUInt32(ZIP_CD_OFFSET_IN_EOCD, offsetValue) ||
18554aa6d63Sopenharmony_ci        !eocd.GetUInt32(ZIP_CD_SIZE_OFFSET_IN_EOCD, sizeValue)) {
18654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("GetUInt32 failed");
18754aa6d63Sopenharmony_ci        return false;
18854aa6d63Sopenharmony_ci    }
18954aa6d63Sopenharmony_ci
19054aa6d63Sopenharmony_ci    centralDirectoryOffset = static_cast<int64_t>(offsetValue);
19154aa6d63Sopenharmony_ci    if (centralDirectoryOffset > eocdOffset) {
19254aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("centralDirOffset %" PRId64 " is larger than eocdOffset %" PRId64,
19354aa6d63Sopenharmony_ci                             centralDirectoryOffset, eocdOffset);
19454aa6d63Sopenharmony_ci        return false;
19554aa6d63Sopenharmony_ci    }
19654aa6d63Sopenharmony_ci
19754aa6d63Sopenharmony_ci    int64_t centralDirectorySize = static_cast<int64_t>(sizeValue);
19854aa6d63Sopenharmony_ci    if (centralDirectoryOffset + centralDirectorySize != eocdOffset) {
19954aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("centralDirOffset %" PRId64 " add centralDirSize %" PRId64 " is"
20054aa6d63Sopenharmony_ci                             " not equal to eocdOffset %" PRId64, centralDirectoryOffset,
20154aa6d63Sopenharmony_ci                             centralDirectorySize, eocdOffset);
20254aa6d63Sopenharmony_ci        return false;
20354aa6d63Sopenharmony_ci    }
20454aa6d63Sopenharmony_ci    return true;
20554aa6d63Sopenharmony_ci}
20654aa6d63Sopenharmony_ci
20754aa6d63Sopenharmony_cibool HapSignerBlockUtils::GetCentralDirectorySize(ByteBuffer& eocd, long& centralDirectorySize)
20854aa6d63Sopenharmony_ci{
20954aa6d63Sopenharmony_ci    uint32_t cdSize;
21054aa6d63Sopenharmony_ci    if (!eocd.GetUInt32(ZIP_CD_SIZE_OFFSET_IN_EOCD, cdSize)) {
21154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("GetUInt32 failed");
21254aa6d63Sopenharmony_ci        return false;
21354aa6d63Sopenharmony_ci    }
21454aa6d63Sopenharmony_ci    centralDirectorySize = (long)cdSize;
21554aa6d63Sopenharmony_ci    return true;
21654aa6d63Sopenharmony_ci}
21754aa6d63Sopenharmony_ci
21854aa6d63Sopenharmony_cibool HapSignerBlockUtils::SetUnsignedInt32(ByteBuffer& buffer, int32_t offset, int64_t value)
21954aa6d63Sopenharmony_ci{
22054aa6d63Sopenharmony_ci    if ((value < 0) || (value > static_cast<int64_t>(UINT_MAX))) {
22154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("uint32 value of out range: %" PRId64, value);
22254aa6d63Sopenharmony_ci        return false;
22354aa6d63Sopenharmony_ci    }
22454aa6d63Sopenharmony_ci    buffer.PutInt32(offset, static_cast<int>(value));
22554aa6d63Sopenharmony_ci    return true;
22654aa6d63Sopenharmony_ci}
22754aa6d63Sopenharmony_ci
22854aa6d63Sopenharmony_cibool HapSignerBlockUtils::FindHapSigningBlock(RandomAccessFile& hapFile, int64_t centralDirOffset,
22954aa6d63Sopenharmony_ci                                              SignatureInfo& signInfo)
23054aa6d63Sopenharmony_ci{
23154aa6d63Sopenharmony_ci    if (centralDirOffset < HAP_SIG_BLOCK_MIN_SIZE) {
23254aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("HAP too small for HAP Signing Block: %" PRId64, centralDirOffset);
23354aa6d63Sopenharmony_ci        return false;
23454aa6d63Sopenharmony_ci    }
23554aa6d63Sopenharmony_ci    /*
23654aa6d63Sopenharmony_ci     * read hap signing block head, it's format:
23754aa6d63Sopenharmony_ci     * int32: blockCount
23854aa6d63Sopenharmony_ci     * int64: size
23954aa6d63Sopenharmony_ci     * 16 bytes: magic
24054aa6d63Sopenharmony_ci     * int32: version
24154aa6d63Sopenharmony_ci     */
24254aa6d63Sopenharmony_ci    ByteBuffer hapBlockHead(ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH);
24354aa6d63Sopenharmony_ci    int64_t ret = hapFile.ReadFileFullyFromOffset(hapBlockHead,
24454aa6d63Sopenharmony_ci                                                  centralDirOffset - hapBlockHead.GetCapacity());
24554aa6d63Sopenharmony_ci    if (ret < 0) {
24654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("read hapBlockHead error: %" PRId64, ret);
24754aa6d63Sopenharmony_ci        return false;
24854aa6d63Sopenharmony_ci    }
24954aa6d63Sopenharmony_ci    HapSignBlockHead hapSignBlockHead;
25054aa6d63Sopenharmony_ci    if (!ParseSignBlockHead(hapSignBlockHead, hapBlockHead)) {
25154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("ParseSignBlockHead failed");
25254aa6d63Sopenharmony_ci        return false;
25354aa6d63Sopenharmony_ci    }
25454aa6d63Sopenharmony_ci
25554aa6d63Sopenharmony_ci    if (!CheckSignBlockHead(hapSignBlockHead)) {
25654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("hapSignBlockHead is invalid");
25754aa6d63Sopenharmony_ci        return false;
25854aa6d63Sopenharmony_ci    }
25954aa6d63Sopenharmony_ci
26054aa6d63Sopenharmony_ci    signInfo.version = hapSignBlockHead.version;
26154aa6d63Sopenharmony_ci    int64_t blockArrayLen = hapSignBlockHead.hapSignBlockSize - ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH;
26254aa6d63Sopenharmony_ci    int64_t hapSignBlockOffset = centralDirOffset - hapSignBlockHead.hapSignBlockSize;
26354aa6d63Sopenharmony_ci    if (hapSignBlockOffset < 0) {
26454aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("HAP Signing Block offset out of range %" PRId64, hapSignBlockOffset);
26554aa6d63Sopenharmony_ci        return false;
26654aa6d63Sopenharmony_ci    }
26754aa6d63Sopenharmony_ci    signInfo.hapSigningBlockOffset = hapSignBlockOffset;
26854aa6d63Sopenharmony_ci    return FindHapSubSigningBlock(hapFile, hapSignBlockHead.blockCount,
26954aa6d63Sopenharmony_ci                                  blockArrayLen, hapSignBlockOffset, signInfo);
27054aa6d63Sopenharmony_ci}
27154aa6d63Sopenharmony_ci
27254aa6d63Sopenharmony_cibool HapSignerBlockUtils::CheckSignBlockHead(const HapSignBlockHead& hapSignBlockHead)
27354aa6d63Sopenharmony_ci{
27454aa6d63Sopenharmony_ci    int64_t magicLow = HAP_SIG_BLOCK_MAGIC_LOW;
27554aa6d63Sopenharmony_ci    int64_t magicHigh = HAP_SIG_BLOCK_MAGIC_HIGH;
27654aa6d63Sopenharmony_ci    if (hapSignBlockHead.version < VERSION_FOR_NEW_MAGIC_NUM) {
27754aa6d63Sopenharmony_ci        magicLow = HAP_SIG_BLOCK_MAGIC_LOW_OLD;
27854aa6d63Sopenharmony_ci        magicHigh = HAP_SIG_BLOCK_MAGIC_HIGH_OLD;
27954aa6d63Sopenharmony_ci    }
28054aa6d63Sopenharmony_ci
28154aa6d63Sopenharmony_ci    if ((hapSignBlockHead.hapSignBlockMagicLo != magicLow) ||
28254aa6d63Sopenharmony_ci        (hapSignBlockHead.hapSignBlockMagicHi != magicHigh)) {
28354aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("No HAP Signing Block before ZIP Central Directory");
28454aa6d63Sopenharmony_ci        return false;
28554aa6d63Sopenharmony_ci    }
28654aa6d63Sopenharmony_ci
28754aa6d63Sopenharmony_ci    if ((hapSignBlockHead.hapSignBlockSize < ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH) ||
28854aa6d63Sopenharmony_ci        (hapSignBlockHead.hapSignBlockSize > MAX_HAP_SIGN_BLOCK_SIZE)) {
28954aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("HAP Signing Block size out of range %" PRId64,
29054aa6d63Sopenharmony_ci                             hapSignBlockHead.hapSignBlockSize);
29154aa6d63Sopenharmony_ci        return false;
29254aa6d63Sopenharmony_ci    }
29354aa6d63Sopenharmony_ci
29454aa6d63Sopenharmony_ci    if (hapSignBlockHead.blockCount > MAX_BLOCK_COUNT) {
29554aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("HAP Signing Block count out of range %d", hapSignBlockHead.blockCount);
29654aa6d63Sopenharmony_ci        return false;
29754aa6d63Sopenharmony_ci    }
29854aa6d63Sopenharmony_ci
29954aa6d63Sopenharmony_ci    return true;
30054aa6d63Sopenharmony_ci}
30154aa6d63Sopenharmony_ci
30254aa6d63Sopenharmony_cibool HapSignerBlockUtils::ParseSignBlockHead(HapSignBlockHead& hapSignBlockHead, ByteBuffer& hapBlockHead)
30354aa6d63Sopenharmony_ci{
30454aa6d63Sopenharmony_ci    return hapBlockHead.GetInt32(hapSignBlockHead.blockCount) &&
30554aa6d63Sopenharmony_ci        hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockSize) &&
30654aa6d63Sopenharmony_ci        hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockMagicLo) &&
30754aa6d63Sopenharmony_ci        hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockMagicHi) &&
30854aa6d63Sopenharmony_ci        hapBlockHead.GetInt32(hapSignBlockHead.version);
30954aa6d63Sopenharmony_ci}
31054aa6d63Sopenharmony_ci
31154aa6d63Sopenharmony_cibool HapSignerBlockUtils::ParseSubSignBlockHead(HapSubSignBlockHead& subSignBlockHead,
31254aa6d63Sopenharmony_ci                                                ByteBuffer& hapBlockHead)
31354aa6d63Sopenharmony_ci{
31454aa6d63Sopenharmony_ci    return hapBlockHead.GetUInt32(subSignBlockHead.type) &&
31554aa6d63Sopenharmony_ci        hapBlockHead.GetUInt32(subSignBlockHead.length) &&
31654aa6d63Sopenharmony_ci        hapBlockHead.GetUInt32(subSignBlockHead.offset);
31754aa6d63Sopenharmony_ci}
31854aa6d63Sopenharmony_ci
31954aa6d63Sopenharmony_ci/*
32054aa6d63Sopenharmony_ci * Hap Sign Block Format:
32154aa6d63Sopenharmony_ci * HapSubSignBlock1_Head
32254aa6d63Sopenharmony_ci * HapSubSignBlock2_Head
32354aa6d63Sopenharmony_ci * ...
32454aa6d63Sopenharmony_ci * HapSubSignBlockn_Head
32554aa6d63Sopenharmony_ci * HapSubSignBlock1_data
32654aa6d63Sopenharmony_ci * HapSubSignBlock2_data
32754aa6d63Sopenharmony_ci * ...
32854aa6d63Sopenharmony_ci * HapSubSignBlockn_data
32954aa6d63Sopenharmony_ci * hap signing block head
33054aa6d63Sopenharmony_ci *
33154aa6d63Sopenharmony_ci * This function reads the head of the HapSubSignBlocks,
33254aa6d63Sopenharmony_ci * and then reads the corresponding data of each block according to the offset provided by the head
33354aa6d63Sopenharmony_ci */
33454aa6d63Sopenharmony_cibool HapSignerBlockUtils::FindHapSubSigningBlock(RandomAccessFile& hapFile,
33554aa6d63Sopenharmony_ci                                                 int32_t blockCount,
33654aa6d63Sopenharmony_ci                                                 int64_t blockArrayLen,
33754aa6d63Sopenharmony_ci                                                 int64_t hapSignBlockOffset,
33854aa6d63Sopenharmony_ci                                                 SignatureInfo& signInfo)
33954aa6d63Sopenharmony_ci{
34054aa6d63Sopenharmony_ci    int64_t offsetMax = hapSignBlockOffset + blockArrayLen;
34154aa6d63Sopenharmony_ci    int64_t readLen = 0;
34254aa6d63Sopenharmony_ci    int64_t readHeadOffset = hapSignBlockOffset;
34354aa6d63Sopenharmony_ci    for (int32_t i = 0; i < blockCount; i++) {
34454aa6d63Sopenharmony_ci        ByteBuffer hapBlockHead(ZIP_CD_SIZE_OFFSET_IN_EOCD);
34554aa6d63Sopenharmony_ci        int64_t ret = hapFile.ReadFileFullyFromOffset(hapBlockHead, readHeadOffset);
34654aa6d63Sopenharmony_ci        if (ret < 0) {
34754aa6d63Sopenharmony_ci            return false;
34854aa6d63Sopenharmony_ci        }
34954aa6d63Sopenharmony_ci        HapSubSignBlockHead subSignBlockHead;
35054aa6d63Sopenharmony_ci        if (!ParseSubSignBlockHead(subSignBlockHead, hapBlockHead)) {
35154aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("ParseSubSignBlockHead failed");
35254aa6d63Sopenharmony_ci            return false;
35354aa6d63Sopenharmony_ci        }
35454aa6d63Sopenharmony_ci        readLen += sizeof(HapSubSignBlockHead);
35554aa6d63Sopenharmony_ci
35654aa6d63Sopenharmony_ci        readHeadOffset += sizeof(HapSubSignBlockHead);
35754aa6d63Sopenharmony_ci        if (readHeadOffset > offsetMax) {
35854aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("find %dst next head offset error", i);
35954aa6d63Sopenharmony_ci            return false;
36054aa6d63Sopenharmony_ci        }
36154aa6d63Sopenharmony_ci
36254aa6d63Sopenharmony_ci        int64_t headOffset = static_cast<int64_t>(subSignBlockHead.offset);
36354aa6d63Sopenharmony_ci        int64_t headLength = static_cast<int64_t>(subSignBlockHead.length);
36454aa6d63Sopenharmony_ci        /* check subSignBlockHead */
36554aa6d63Sopenharmony_ci        if ((offsetMax - headOffset) < hapSignBlockOffset) {
36654aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("Find %dst subblock data offset error", i);
36754aa6d63Sopenharmony_ci            return false;
36854aa6d63Sopenharmony_ci        }
36954aa6d63Sopenharmony_ci        if ((blockArrayLen - headLength) < readLen) {
37054aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("no enough data to be read for %dst subblock", i);
37154aa6d63Sopenharmony_ci            return false;
37254aa6d63Sopenharmony_ci        }
37354aa6d63Sopenharmony_ci
37454aa6d63Sopenharmony_ci        int64_t dataOffset = hapSignBlockOffset + headOffset;
37554aa6d63Sopenharmony_ci        ByteBuffer signBuffer(subSignBlockHead.length);
37654aa6d63Sopenharmony_ci        if ((ret = hapFile.ReadFileFullyFromOffset(signBuffer, dataOffset)) < 0) {
37754aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("read %dst subblock error: %" PRId64, i, ret);
37854aa6d63Sopenharmony_ci            return false;
37954aa6d63Sopenharmony_ci        }
38054aa6d63Sopenharmony_ci        readLen += headLength;
38154aa6d63Sopenharmony_ci
38254aa6d63Sopenharmony_ci        if (!ClassifyHapSubSigningBlock(signInfo, signBuffer, subSignBlockHead.type)) {
38354aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("subSigningBlock error, type is %d", subSignBlockHead.type);
38454aa6d63Sopenharmony_ci            return false;
38554aa6d63Sopenharmony_ci        }
38654aa6d63Sopenharmony_ci    }
38754aa6d63Sopenharmony_ci
38854aa6d63Sopenharmony_ci    /* size of block must be equal to the sum of all subblocks length */
38954aa6d63Sopenharmony_ci    if (readLen != blockArrayLen) {
39054aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("Len: %" PRId64 " is not equal blockArrayLen: %" PRId64,
39154aa6d63Sopenharmony_ci                             readLen, blockArrayLen);
39254aa6d63Sopenharmony_ci        return false;
39354aa6d63Sopenharmony_ci    }
39454aa6d63Sopenharmony_ci    return true;
39554aa6d63Sopenharmony_ci}
39654aa6d63Sopenharmony_ci
39754aa6d63Sopenharmony_cibool HapSignerBlockUtils::ClassifyHapSubSigningBlock(SignatureInfo& signInfo,
39854aa6d63Sopenharmony_ci                                                     const ByteBuffer& subBlock, uint32_t type)
39954aa6d63Sopenharmony_ci{
40054aa6d63Sopenharmony_ci    bool ret = false;
40154aa6d63Sopenharmony_ci    switch (type) {
40254aa6d63Sopenharmony_ci        case HAP_SIGN_BLOB:
40354aa6d63Sopenharmony_ci            {
40454aa6d63Sopenharmony_ci                if (signInfo.hapSignatureBlock.GetCapacity() != 0) {
40554aa6d63Sopenharmony_ci                    SIGNATURE_TOOLS_LOGE("find more than one hap sign block");
40654aa6d63Sopenharmony_ci                    break;
40754aa6d63Sopenharmony_ci                }
40854aa6d63Sopenharmony_ci                signInfo.hapSignatureBlock = subBlock;
40954aa6d63Sopenharmony_ci                ret = true;
41054aa6d63Sopenharmony_ci                break;
41154aa6d63Sopenharmony_ci            }
41254aa6d63Sopenharmony_ci        case PROFILE_BLOB:
41354aa6d63Sopenharmony_ci        case PROOF_ROTATION_BLOB:
41454aa6d63Sopenharmony_ci        case PROPERTY_BLOB:
41554aa6d63Sopenharmony_ci            {
41654aa6d63Sopenharmony_ci                OptionalBlock optionalBlockObject;
41754aa6d63Sopenharmony_ci                optionalBlockObject.optionalType = static_cast<int>(type);
41854aa6d63Sopenharmony_ci                optionalBlockObject.optionalBlockValue = subBlock;
41954aa6d63Sopenharmony_ci                signInfo.optionBlocks.push_back(optionalBlockObject);
42054aa6d63Sopenharmony_ci                ret = true;
42154aa6d63Sopenharmony_ci                break;
42254aa6d63Sopenharmony_ci            }
42354aa6d63Sopenharmony_ci        default:
42454aa6d63Sopenharmony_ci            break;
42554aa6d63Sopenharmony_ci    }
42654aa6d63Sopenharmony_ci    return ret;
42754aa6d63Sopenharmony_ci}
42854aa6d63Sopenharmony_ci
42954aa6d63Sopenharmony_cibool HapSignerBlockUtils::GetOptionalBlockIndex(std::vector<OptionalBlock>& optionBlocks,
43054aa6d63Sopenharmony_ci                                                int32_t type,
43154aa6d63Sopenharmony_ci                                                int& index)
43254aa6d63Sopenharmony_ci{
43354aa6d63Sopenharmony_ci    int32_t len = static_cast<int>(optionBlocks.size());
43454aa6d63Sopenharmony_ci    for (int32_t i = 0; i < len; i++) {
43554aa6d63Sopenharmony_ci        if (optionBlocks[i].optionalType == type) {
43654aa6d63Sopenharmony_ci            index = i;
43754aa6d63Sopenharmony_ci            return true;
43854aa6d63Sopenharmony_ci        }
43954aa6d63Sopenharmony_ci    }
44054aa6d63Sopenharmony_ci    SIGNATURE_TOOLS_LOGE("get optional block type:%d failed.", type);
44154aa6d63Sopenharmony_ci    return false;
44254aa6d63Sopenharmony_ci}
44354aa6d63Sopenharmony_ci
44454aa6d63Sopenharmony_cibool HapSignerBlockUtils::VerifyHapIntegrity(
44554aa6d63Sopenharmony_ci    Pkcs7Context& digestInfo, RandomAccessFile& hapFile, SignatureInfo& signInfo)
44654aa6d63Sopenharmony_ci{
44754aa6d63Sopenharmony_ci    if (!SetUnsignedInt32(signInfo.hapEocd, ZIP_CD_OFFSET_IN_EOCD, signInfo.hapSigningBlockOffset)) {
44854aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("Set central dir offset failed");
44954aa6d63Sopenharmony_ci        return false;
45054aa6d63Sopenharmony_ci    }
45154aa6d63Sopenharmony_ci
45254aa6d63Sopenharmony_ci    int64_t centralDirSize = signInfo.hapEocdOffset - signInfo.hapCentralDirOffset;
45354aa6d63Sopenharmony_ci    FileDataSource contentsZip(hapFile, 0, signInfo.hapSigningBlockOffset, 0);
45454aa6d63Sopenharmony_ci    FileDataSource centralDir(hapFile, signInfo.hapCentralDirOffset, centralDirSize, 0);
45554aa6d63Sopenharmony_ci    ByteBufferDataSource eocd(signInfo.hapEocd);
45654aa6d63Sopenharmony_ci    DataSource* content[ZIP_BLOCKS_NUM_NEED_DIGEST] = {&contentsZip, &centralDir, &eocd};
45754aa6d63Sopenharmony_ci    int32_t nId = DigestCommon::GetDigestAlgorithmId(digestInfo.digestAlgorithm);
45854aa6d63Sopenharmony_ci    DigestParameter digestParam = GetDigestParameter(nId);
45954aa6d63Sopenharmony_ci    ByteBuffer chunkDigest;
46054aa6d63Sopenharmony_ci    if (!ComputeDigestsForEachChunk(digestParam, content, ZIP_BLOCKS_NUM_NEED_DIGEST, chunkDigest)) {
46154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("Compute Content Digests failed, alg: %d", nId);
46254aa6d63Sopenharmony_ci        return false;
46354aa6d63Sopenharmony_ci    }
46454aa6d63Sopenharmony_ci
46554aa6d63Sopenharmony_ci    ByteBuffer actualDigest;
46654aa6d63Sopenharmony_ci    if (!ComputeDigestsWithOptionalBlock(digestParam, signInfo.optionBlocks, chunkDigest, actualDigest)) {
46754aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("Compute Final Digests failed, alg: %d", nId);
46854aa6d63Sopenharmony_ci        return false;
46954aa6d63Sopenharmony_ci    }
47054aa6d63Sopenharmony_ci
47154aa6d63Sopenharmony_ci    if (!digestInfo.content.IsEqual(actualDigest)) {
47254aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("digest of contents verify failed, alg %d", nId);
47354aa6d63Sopenharmony_ci        return false;
47454aa6d63Sopenharmony_ci    }
47554aa6d63Sopenharmony_ci    PrintMsg(std::string("Digest verify result: ") + "success" + ", DigestAlgorithm: "
47654aa6d63Sopenharmony_ci             + DigestCommon::GetDigestAlgorithmString(digestInfo.digestAlgorithm));
47754aa6d63Sopenharmony_ci
47854aa6d63Sopenharmony_ci    return true;
47954aa6d63Sopenharmony_ci}
48054aa6d63Sopenharmony_ci
48154aa6d63Sopenharmony_cibool HapSignerBlockUtils::ComputeDigestsWithOptionalBlock(const DigestParameter& digestParam,
48254aa6d63Sopenharmony_ci                                                          const std::vector<OptionalBlock>& optionalBlocks,
48354aa6d63Sopenharmony_ci                                                          const ByteBuffer& chunkDigest,
48454aa6d63Sopenharmony_ci                                                          ByteBuffer& finalDigest)
48554aa6d63Sopenharmony_ci{
48654aa6d63Sopenharmony_ci    unsigned char out[EVP_MAX_MD_SIZE];
48754aa6d63Sopenharmony_ci    int32_t digestLen = DigestCommon::GetDigest(chunkDigest, optionalBlocks, digestParam, out);
48854aa6d63Sopenharmony_ci    if (digestLen != digestParam.digestOutputSizeBytes) {
48954aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("GetDigest failed, outLen is not right, %u, %d",
49054aa6d63Sopenharmony_ci                             digestLen, digestParam.digestOutputSizeBytes);
49154aa6d63Sopenharmony_ci        return false;
49254aa6d63Sopenharmony_ci    }
49354aa6d63Sopenharmony_ci
49454aa6d63Sopenharmony_ci    finalDigest.SetCapacity(digestParam.digestOutputSizeBytes);
49554aa6d63Sopenharmony_ci    finalDigest.PutData(0, reinterpret_cast<char*>(out), digestParam.digestOutputSizeBytes);
49654aa6d63Sopenharmony_ci    return true;
49754aa6d63Sopenharmony_ci}
49854aa6d63Sopenharmony_ci
49954aa6d63Sopenharmony_cibool HapSignerBlockUtils::GetSumOfChunkDigestLen(DataSource* contents[], int32_t len,
50054aa6d63Sopenharmony_ci                                                 int32_t chunkDigestLen, int& chunkCount,
50154aa6d63Sopenharmony_ci                                                 int& sumOfChunkDigestLen)
50254aa6d63Sopenharmony_ci{
50354aa6d63Sopenharmony_ci    for (int32_t i = 0; i < len; i++) {
50454aa6d63Sopenharmony_ci        if (contents[i] == nullptr) {
50554aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("contents[%d] is nullptr", i);
50654aa6d63Sopenharmony_ci            return false;
50754aa6d63Sopenharmony_ci        }
50854aa6d63Sopenharmony_ci        contents[i]->Reset();
50954aa6d63Sopenharmony_ci        chunkCount += GetChunkCount(contents[i]->Remaining(), CHUNK_SIZE);
51054aa6d63Sopenharmony_ci    }
51154aa6d63Sopenharmony_ci
51254aa6d63Sopenharmony_ci    if (chunkCount <= 0) {
51354aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("no content for digest");
51454aa6d63Sopenharmony_ci        return false;
51554aa6d63Sopenharmony_ci    }
51654aa6d63Sopenharmony_ci    if (chunkCount == 0) {
51754aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("no content for digest");
51854aa6d63Sopenharmony_ci        return false;
51954aa6d63Sopenharmony_ci    }
52054aa6d63Sopenharmony_ci    if (chunkDigestLen < 0 || ((INT_MAX - ZIP_CHUNK_DIGEST_PRIFIX_LEN) / chunkCount) < chunkDigestLen) {
52154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("overflow chunkCount: %d, chunkDigestLen: %d",
52254aa6d63Sopenharmony_ci                             chunkCount, chunkDigestLen);
52354aa6d63Sopenharmony_ci        return false;
52454aa6d63Sopenharmony_ci    }
52554aa6d63Sopenharmony_ci
52654aa6d63Sopenharmony_ci    sumOfChunkDigestLen = ZIP_CHUNK_DIGEST_PRIFIX_LEN + chunkCount * chunkDigestLen;
52754aa6d63Sopenharmony_ci    return true;
52854aa6d63Sopenharmony_ci}
52954aa6d63Sopenharmony_ci
53054aa6d63Sopenharmony_cibool HapSignerBlockUtils::ComputeDigestsForEachChunk(const DigestParameter& digestParam,
53154aa6d63Sopenharmony_ci                                                     DataSource* contents[], int32_t len, ByteBuffer& result)
53254aa6d63Sopenharmony_ci{
53354aa6d63Sopenharmony_ci    int32_t chunkCount = 0;
53454aa6d63Sopenharmony_ci    int32_t sumOfChunksLen = 0;
53554aa6d63Sopenharmony_ci    if (!GetSumOfChunkDigestLen(contents, len, digestParam.digestOutputSizeBytes, chunkCount, sumOfChunksLen)) {
53654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("GetSumOfChunkDigestLen failed");
53754aa6d63Sopenharmony_ci        return false;
53854aa6d63Sopenharmony_ci    }
53954aa6d63Sopenharmony_ci    result.SetCapacity(sumOfChunksLen);
54054aa6d63Sopenharmony_ci    result.PutByte(0, ZIP_FIRST_LEVEL_CHUNK_PREFIX);
54154aa6d63Sopenharmony_ci    result.PutInt32(1, chunkCount);
54254aa6d63Sopenharmony_ci
54354aa6d63Sopenharmony_ci    int32_t chunkIndex = 0;
54454aa6d63Sopenharmony_ci    unsigned char outBlock[EVP_MAX_MD_SIZE];
54554aa6d63Sopenharmony_ci    unsigned char zipChunkContentPrefix[ZIP_CHUNK_DIGEST_PRIFIX_LEN] = {
54654aa6d63Sopenharmony_ci    (unsigned char)ZIP_SECOND_LEVEL_CHUNK_PREFIX, 0, 0, 0, 0};
54754aa6d63Sopenharmony_ci
54854aa6d63Sopenharmony_ci    int32_t zipOffset = ZIP_CHUNK_DIGEST_PRIFIX_LEN;
54954aa6d63Sopenharmony_ci    for (int32_t i = 0; i < len; i++) {
55054aa6d63Sopenharmony_ci        while (contents[i]->HasRemaining()) {
55154aa6d63Sopenharmony_ci            int32_t digestChunkSize = std::min(contents[i]->Remaining(), CHUNK_SIZE);
55254aa6d63Sopenharmony_ci            if (!InitDigestPrefix(digestParam, zipChunkContentPrefix, digestChunkSize)) {
55354aa6d63Sopenharmony_ci                SIGNATURE_TOOLS_LOGE("InitDigestPrefix failed");
55454aa6d63Sopenharmony_ci                return false;
55554aa6d63Sopenharmony_ci            }
55654aa6d63Sopenharmony_ci
55754aa6d63Sopenharmony_ci            if (!contents[i]->ReadDataAndDigestUpdate(digestParam, digestChunkSize)) {
55854aa6d63Sopenharmony_ci                SIGNATURE_TOOLS_LOGE("Copy Partial Buffer failed, count: %d", chunkIndex);
55954aa6d63Sopenharmony_ci                return false;
56054aa6d63Sopenharmony_ci            }
56154aa6d63Sopenharmony_ci
56254aa6d63Sopenharmony_ci            int32_t digestLen = DigestCommon::GetDigest(digestParam, outBlock);
56354aa6d63Sopenharmony_ci            if (digestLen != digestParam.digestOutputSizeBytes) {
56454aa6d63Sopenharmony_ci                SIGNATURE_TOOLS_LOGE("GetDigest failed len: %d digestSizeBytes: %d",
56554aa6d63Sopenharmony_ci                                     digestLen, digestParam.digestOutputSizeBytes);
56654aa6d63Sopenharmony_ci                return false;
56754aa6d63Sopenharmony_ci            }
56854aa6d63Sopenharmony_ci            result.PutData(zipOffset, reinterpret_cast<char*>(outBlock), digestParam.digestOutputSizeBytes);
56954aa6d63Sopenharmony_ci            zipOffset += digestLen;
57054aa6d63Sopenharmony_ci            chunkIndex++;
57154aa6d63Sopenharmony_ci        }
57254aa6d63Sopenharmony_ci    }
57354aa6d63Sopenharmony_ci    return true;
57454aa6d63Sopenharmony_ci}
57554aa6d63Sopenharmony_ci
57654aa6d63Sopenharmony_ciDigestParameter HapSignerBlockUtils::GetDigestParameter(int32_t nId)
57754aa6d63Sopenharmony_ci{
57854aa6d63Sopenharmony_ci    DigestParameter digestParam;
57954aa6d63Sopenharmony_ci    digestParam.digestOutputSizeBytes = DigestCommon::GetDigestAlgorithmOutputSizeBytes(nId);
58054aa6d63Sopenharmony_ci    digestParam.md = EVP_get_digestbynid(nId);
58154aa6d63Sopenharmony_ci    digestParam.ctxPtr = EVP_MD_CTX_create();
58254aa6d63Sopenharmony_ci    EVP_MD_CTX_init(digestParam.ctxPtr);
58354aa6d63Sopenharmony_ci    return digestParam;
58454aa6d63Sopenharmony_ci}
58554aa6d63Sopenharmony_ci
58654aa6d63Sopenharmony_ciint32_t HapSignerBlockUtils::GetChunkCount(int64_t inputSize, int64_t chunkSize)
58754aa6d63Sopenharmony_ci{
58854aa6d63Sopenharmony_ci    if (chunkSize <= 0 || inputSize > LLONG_MAX - chunkSize) {
58954aa6d63Sopenharmony_ci        return 0;
59054aa6d63Sopenharmony_ci    }
59154aa6d63Sopenharmony_ci    if (chunkSize == 0)
59254aa6d63Sopenharmony_ci        return 0;
59354aa6d63Sopenharmony_ci    int64_t res = (inputSize + chunkSize - 1) / chunkSize;
59454aa6d63Sopenharmony_ci    if (res > INT_MAX || res < 0) {
59554aa6d63Sopenharmony_ci        return 0;
59654aa6d63Sopenharmony_ci    }
59754aa6d63Sopenharmony_ci    return static_cast<int>(res);
59854aa6d63Sopenharmony_ci}
59954aa6d63Sopenharmony_ci
60054aa6d63Sopenharmony_cibool HapSignerBlockUtils::InitDigestPrefix(const DigestParameter& digestParam,
60154aa6d63Sopenharmony_ci                                           unsigned char(&chunkContentPrefix)[ZIP_CHUNK_DIGEST_PRIFIX_LEN],
60254aa6d63Sopenharmony_ci                                           int32_t chunkLen)
60354aa6d63Sopenharmony_ci{
60454aa6d63Sopenharmony_ci    if (memcpy_s((chunkContentPrefix + 1), ZIP_CHUNK_DIGEST_PRIFIX_LEN - 1,
60554aa6d63Sopenharmony_ci                 (&chunkLen), sizeof(chunkLen)) != EOK) {
60654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("memcpy_s failed");
60754aa6d63Sopenharmony_ci        return false;
60854aa6d63Sopenharmony_ci    }
60954aa6d63Sopenharmony_ci
61054aa6d63Sopenharmony_ci    if (!DigestCommon::DigestInit(digestParam)) {
61154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("DigestInit failed");
61254aa6d63Sopenharmony_ci        return false;
61354aa6d63Sopenharmony_ci    }
61454aa6d63Sopenharmony_ci
61554aa6d63Sopenharmony_ci    if (!DigestCommon::DigestUpdate(digestParam, chunkContentPrefix, ZIP_CHUNK_DIGEST_PRIFIX_LEN)) {
61654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("DigestUpdate failed");
61754aa6d63Sopenharmony_ci        return false;
61854aa6d63Sopenharmony_ci    }
61954aa6d63Sopenharmony_ci    return true;
62054aa6d63Sopenharmony_ci}
62154aa6d63Sopenharmony_ci
62254aa6d63Sopenharmony_ciint64_t HapSignerBlockUtils::CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo)
62354aa6d63Sopenharmony_ci{
62454aa6d63Sopenharmony_ci    std::ofstream hapFileInfo(pathFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc);
62554aa6d63Sopenharmony_ci    if (!hapFileInfo.is_open()) {
62654aa6d63Sopenharmony_ci        return 0;
62754aa6d63Sopenharmony_ci    }
62854aa6d63Sopenharmony_ci    char block[TEST_FILE_BLOCK_LENGTH] = {0};
62954aa6d63Sopenharmony_ci    /* input contents of ZIP entries */
63054aa6d63Sopenharmony_ci    hapFileInfo.seekp(0, std::ios_base::beg);
63154aa6d63Sopenharmony_ci    hapFileInfo.write(block, sizeof(block));
63254aa6d63Sopenharmony_ci    /* input sign block */
63354aa6d63Sopenharmony_ci    HapSubSignBlockHead signBlob;
63454aa6d63Sopenharmony_ci    HapSubSignBlockHead profileBlob;
63554aa6d63Sopenharmony_ci    HapSubSignBlockHead propertyBlob;
63654aa6d63Sopenharmony_ci    CreateHapSubSignBlockHead(signBlob, profileBlob, propertyBlob);
63754aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&signBlob), sizeof(signBlob));
63854aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&profileBlob), sizeof(profileBlob));
63954aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&propertyBlob), sizeof(propertyBlob));
64054aa6d63Sopenharmony_ci    for (int32_t i = 0; i < TEST_FILE_BLOCK_COUNT; i++) {
64154aa6d63Sopenharmony_ci        hapFileInfo.write(block, sizeof(block));
64254aa6d63Sopenharmony_ci    }
64354aa6d63Sopenharmony_ci    int32_t blockCount = TEST_FILE_BLOCK_COUNT;
64454aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&blockCount), sizeof(blockCount));
64554aa6d63Sopenharmony_ci    int64_t signBlockSize = (sizeof(HapSubSignBlockHead) + sizeof(block)) * TEST_FILE_BLOCK_COUNT +
64654aa6d63Sopenharmony_ci        HapSignerBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH;
64754aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&signBlockSize), sizeof(signBlockSize));
64854aa6d63Sopenharmony_ci    int64_t magic = HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW_OLD;
64954aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&magic), sizeof(magic));
65054aa6d63Sopenharmony_ci    magic = HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH_OLD;
65154aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&magic), sizeof(magic));
65254aa6d63Sopenharmony_ci    int32_t version = 1;
65354aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&version), sizeof(version));
65454aa6d63Sopenharmony_ci    /* input central direction */
65554aa6d63Sopenharmony_ci    hapFileInfo.write(block, sizeof(block));
65654aa6d63Sopenharmony_ci    /* input end of central direction */
65754aa6d63Sopenharmony_ci    int32_t zidEocdSign = HapSignerBlockUtils::ZIP_EOCD_SEGMENT_FLAG;
65854aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&zidEocdSign), sizeof(zidEocdSign));
65954aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&magic), sizeof(magic));
66054aa6d63Sopenharmony_ci    uint32_t centralDirLen = sizeof(block);
66154aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&centralDirLen), sizeof(centralDirLen));
66254aa6d63Sopenharmony_ci    uint32_t centralDirOffset = TEST_FILE_BLOCK_LENGTH + signBlockSize;
66354aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&centralDirOffset), sizeof(centralDirOffset));
66454aa6d63Sopenharmony_ci    short eocdCommentLen = 0;
66554aa6d63Sopenharmony_ci    hapFileInfo.write(reinterpret_cast<char*>(&eocdCommentLen), sizeof(eocdCommentLen));
66654aa6d63Sopenharmony_ci    hapFileInfo.close();
66754aa6d63Sopenharmony_ci    signInfo.hapCentralDirOffset = centralDirOffset;
66854aa6d63Sopenharmony_ci    signInfo.hapEocdOffset = centralDirOffset + centralDirLen;
66954aa6d63Sopenharmony_ci    signInfo.hapSignatureBlock.SetCapacity(TEST_FILE_BLOCK_LENGTH);
67054aa6d63Sopenharmony_ci    signInfo.hapSignatureBlock.PutData(0, block, sizeof(block));
67154aa6d63Sopenharmony_ci    int64_t sumLen = signInfo.hapEocdOffset + sizeof(zidEocdSign) + sizeof(centralDirLen) +
67254aa6d63Sopenharmony_ci        sizeof(centralDirOffset) + sizeof(magic) + sizeof(eocdCommentLen);
67354aa6d63Sopenharmony_ci    return sumLen;
67454aa6d63Sopenharmony_ci}
67554aa6d63Sopenharmony_ci
67654aa6d63Sopenharmony_civoid HapSignerBlockUtils::CreateHapSubSignBlockHead(HapSubSignBlockHead& signBlob,
67754aa6d63Sopenharmony_ci                                                    HapSubSignBlockHead& profileBlob,
67854aa6d63Sopenharmony_ci                                                    HapSubSignBlockHead& propertyBlob)
67954aa6d63Sopenharmony_ci{
68054aa6d63Sopenharmony_ci    signBlob.type = HAP_SIGN_BLOB;
68154aa6d63Sopenharmony_ci    signBlob.length = TEST_FILE_BLOCK_LENGTH;
68254aa6d63Sopenharmony_ci    signBlob.offset = sizeof(HapSubSignBlockHead) * TEST_FILE_BLOCK_COUNT;
68354aa6d63Sopenharmony_ci    propertyBlob.type = PROPERTY_BLOB;
68454aa6d63Sopenharmony_ci    propertyBlob.length = TEST_FILE_BLOCK_LENGTH;
68554aa6d63Sopenharmony_ci    propertyBlob.offset = profileBlob.offset + profileBlob.length;
68654aa6d63Sopenharmony_ci    profileBlob.type = PROFILE_BLOB;
68754aa6d63Sopenharmony_ci    profileBlob.length = TEST_FILE_BLOCK_LENGTH;
68854aa6d63Sopenharmony_ci    profileBlob.offset = signBlob.offset + signBlob.length;
68954aa6d63Sopenharmony_ci}
69054aa6d63Sopenharmony_ci} // namespace SignatureTools
69154aa6d63Sopenharmony_ci} // namespace OHOS