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, ¢ralDir, &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*>(¢ralDirLen), sizeof(centralDirLen)); 66254aa6d63Sopenharmony_ci uint32_t centralDirOffset = TEST_FILE_BLOCK_LENGTH + signBlockSize; 66354aa6d63Sopenharmony_ci hapFileInfo.write(reinterpret_cast<char*>(¢ralDirOffset), 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