diff --git a/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h b/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h index 53959ecccd630c2008e343663d4d0ca2f180840e..1f118d853f46510ce9412c1f94ff2b23487e1e99 100644 --- a/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h +++ b/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h @@ -14,9 +14,9 @@ */ #ifndef HAP_SIGNING_BLOCK_UTILS_H #define HAP_SIGNING_BLOCK_UTILS_H - + #include - + #include "common/data_source.h" #include "common/export_define.h" #include "common/hap_byte_buffer.h" @@ -26,19 +26,19 @@ #include "util/pkcs7_context.h" #include "util/signature_info.h" #include "util/signature_info.h" - + namespace OHOS { namespace Security { namespace Verify { constexpr int32_t ZIP_CHUNK_DIGEST_PRIFIX_LEN = 5; - + enum HapBlobType { HAP_SIGN_BLOB = 0x20000000, PROOF_ROTATION_BLOB = 0x20000001, PROFILE_BLOB = 0x20000002, PROPERTY_BLOB = 0x20000003, }; - + struct HapSignBlockHead { int32_t version = 0; int32_t blockCount = 0; @@ -46,20 +46,20 @@ struct HapSignBlockHead { long long hapSignBlockMagicLo; long long hapSignBlockMagicHi; }; - + struct HapSubSignBlockHead { uint32_t type = 0; uint32_t length = 0; uint32_t offset = 0; }; - + class HapSigningBlockUtils { public: DLL_EXPORT static bool FindHapSignature(RandomAccessFile& hapFile, SignatureInfo& signInfo); DLL_EXPORT static bool GetOptionalBlockIndex(std::vector& optionBlocks, int32_t type, int& index); DLL_EXPORT static bool VerifyHapIntegrity(Pkcs7Context& digestInfo, RandomAccessFile& hapFile, SignatureInfo& signInfo); - + private: DLL_EXPORT static const long long HAP_SIG_BLOCK_MAGIC_HIGH_OLD; DLL_EXPORT static const long long HAP_SIG_BLOCK_MAGIC_LOW_OLD; @@ -76,11 +76,13 @@ private: static const int32_t ZIP_BLOCKS_NUM_NEED_DIGEST; static const char ZIP_FIRST_LEVEL_CHUNK_PREFIX; static const char ZIP_SECOND_LEVEL_CHUNK_PREFIX; + static const int32_t ZIP_UPDATE_DIGEST_THREADS_NUM; + static const long long SMALL_FILE_SIZE; /* the specifications of hap sign block */ static constexpr long long MAX_HAP_SIGN_BLOCK_SIZE = 1024 * 1024 * 1024LL; // 1024MB static constexpr int32_t MAX_BLOCK_COUNT = 10; static constexpr int32_t VERSION_FOR_NEW_MAGIC_NUM = 3; - + private: DLL_EXPORT static bool FindEocdInHap(RandomAccessFile& hapFile, std::pair& eocd); DLL_EXPORT static bool FindEocdInHap(RandomAccessFile& hapFile, unsigned short maxCommentSize, @@ -99,7 +101,11 @@ private: const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, HapByteBuffer& finalDigest); static bool ComputeDigestsForEachChunk(const DigestParameter& digestParam, DataSource* contents[], - int32_t len, HapByteBuffer& result); + int32_t len, HapByteBuffer& result, int32_t& offset); + static bool ComputeDigestsForDataSource(const DigestParameter& digestParam, DataSource* content, + HapByteBuffer& result, int32_t& offset); + static bool ComputeDigestsForContentsZip(int32_t nId, RandomAccessFile& hapFile, + int32_t chunkNum, long long fileSize, HapByteBuffer& digestsBuffer); static int32_t GetChunkCount(long long inputSize, long long chunkSize); static bool InitDigestPrefix(const DigestParameter& digestParam, unsigned char (&chunkContentPrefix)[ZIP_CHUNK_DIGEST_PRIFIX_LEN], int32_t chunkLen); @@ -114,3 +120,4 @@ private: } // namespace Security } // namespace OHOS #endif // HAP_SIGNING_BLOCK_UTILS_H + \ No newline at end of file diff --git a/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp b/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp index b8b4d8bb5d3ae4128090cd0e9eecd16143ff806c..623356c240e6a88e3e05abc048ff1e8004ed7545 100644 --- a/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp +++ b/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp @@ -12,12 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #include "util/hap_signing_block_utils.h" - + #include #include - +#include + #include "algorithm" #include "common/hap_byte_buffer_data_source.h" #include "common/hap_file_data_source.h" @@ -25,7 +26,7 @@ #include "openssl/evp.h" #include "securec.h" #include "util/hap_verify_openssl_utils.h" - + namespace OHOS { namespace Security { namespace Verify { @@ -33,23 +34,25 @@ const long long HapSigningBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW_OLD = 233495073756 const long long HapSigningBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH_OLD = 3617552046287187010LL; const long long HapSigningBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW = 7451613641622775868LL; const long long HapSigningBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH = 4497797983070462062LL; - + /* 1MB = 1024 * 1024 Bytes */ const long long HapSigningBlockUtils::CHUNK_SIZE = 1048576LL; - +const long long HapSigningBlockUtils::SMALL_FILE_SIZE = CHUNK_SIZE * 2; + const int32_t HapSigningBlockUtils::HAP_SIG_BLOCK_MIN_SIZE = 32; const int32_t HapSigningBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH = 32; - + const int32_t HapSigningBlockUtils::ZIP_EOCD_SEG_MIN_SIZE = 22; const int32_t HapSigningBlockUtils::ZIP_EOCD_SEGMENT_FLAG = 0x06054b50; const int32_t HapSigningBlockUtils::ZIP_EOCD_COMMENT_LENGTH_OFFSET = 20; const int32_t HapSigningBlockUtils::ZIP_CD_OFFSET_IN_EOCD = 16; const int32_t HapSigningBlockUtils::ZIP_CD_SIZE_OFFSET_IN_EOCD = 12; const int32_t HapSigningBlockUtils::ZIP_BLOCKS_NUM_NEED_DIGEST = 3; - +const int32_t HapSigningBlockUtils::ZIP_UPDATE_DIGEST_THREADS_NUM = 4; + const char HapSigningBlockUtils::ZIP_FIRST_LEVEL_CHUNK_PREFIX = 0x5a; const char HapSigningBlockUtils::ZIP_SECOND_LEVEL_CHUNK_PREFIX = 0xa5; - + /* * The package of hap is ZIP format, and contains four segments: contents of Zip entry, * hap signatures block, central directory and end of central directory. @@ -62,21 +65,21 @@ bool HapSigningBlockUtils::FindHapSignature(RandomAccessFile& hapFile, Signature HAPVERIFY_LOG_ERROR("find EoCD failed"); return false; } - + signInfo.hapEocd = eocdAndOffsetInFile.first; signInfo.hapEocdOffset = eocdAndOffsetInFile.second; if (!GetCentralDirectoryOffset(signInfo.hapEocd, signInfo.hapEocdOffset, signInfo.hapCentralDirOffset)) { HAPVERIFY_LOG_ERROR("get CD offset failed"); return false; } - + if (!FindHapSigningBlock(hapFile, signInfo.hapCentralDirOffset, signInfo)) { HAPVERIFY_LOG_ERROR("find signing block failed"); return false; } return true; } - + bool HapSigningBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, std::pair& eocd) { /* @@ -94,7 +97,7 @@ bool HapSigningBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, std::pair& eocd) { @@ -104,12 +107,12 @@ bool HapSigningBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, unsigned sho HAPVERIFY_LOG_ERROR("file length %{public}lld is too smaller", fileLength); return false; } - + int32_t searchRange = static_cast(maxCommentSize) + ZIP_EOCD_SEG_MIN_SIZE; if (fileLength < static_cast(searchRange)) { searchRange = static_cast(fileLength); } - + HapByteBuffer searchEocdBuffer(searchRange); long long searchRangeOffset = fileLength - searchEocdBuffer.GetCapacity(); long long ret = hapFile.ReadFileFullyFromOffset(searchEocdBuffer, searchRangeOffset); @@ -117,20 +120,20 @@ bool HapSigningBlockUtils::FindEocdInHap(RandomAccessFile& hapFile, unsigned sho HAPVERIFY_LOG_ERROR("read data from hap file error: %{public}lld", ret); return false; } - + int32_t eocdOffsetInSearchBuffer = 0; if (!FindEocdInSearchBuffer(searchEocdBuffer, eocdOffsetInSearchBuffer)) { HAPVERIFY_LOG_ERROR("No Eocd is found"); return false; } - + searchEocdBuffer.SetPosition(eocdOffsetInSearchBuffer); searchEocdBuffer.Slice(); eocd.first = searchEocdBuffer; eocd.second = searchRangeOffset + eocdOffsetInSearchBuffer; return true; } - + /* * Eocd format: * 4-bytes: End of central directory flag @@ -154,7 +157,7 @@ bool HapSigningBlockUtils::FindEocdInSearchBuffer(HapByteBuffer& searchBuffer, i searchBufferSize); return false; } - + int32_t currentOffset = searchBufferSize - ZIP_EOCD_SEG_MIN_SIZE; while (currentOffset >= 0) { int32_t hapEocdSegmentFlag; @@ -172,7 +175,7 @@ bool HapSigningBlockUtils::FindEocdInSearchBuffer(HapByteBuffer& searchBuffer, i } return false; } - + bool HapSigningBlockUtils::GetCentralDirectoryOffset(HapByteBuffer& eocd, long long eocdOffset, long long& centralDirectoryOffset) { @@ -183,14 +186,14 @@ bool HapSigningBlockUtils::GetCentralDirectoryOffset(HapByteBuffer& eocd, long l HAPVERIFY_LOG_ERROR("GetUInt32 failed"); return false; } - + centralDirectoryOffset = static_cast(offsetValue); if (centralDirectoryOffset > eocdOffset) { HAPVERIFY_LOG_ERROR("centralDirOffset %{public}lld is larger than eocdOffset %{public}lld", centralDirectoryOffset, eocdOffset); return false; } - + long long centralDirectorySize = static_cast(sizeValue); if (centralDirectoryOffset + centralDirectorySize != eocdOffset) { HAPVERIFY_LOG_ERROR("centralDirOffset %{public}lld add centralDirSize %{public}lld is not equal\ @@ -199,7 +202,7 @@ bool HapSigningBlockUtils::GetCentralDirectoryOffset(HapByteBuffer& eocd, long l } return true; } - + bool HapSigningBlockUtils::SetUnsignedInt32(HapByteBuffer& buffer, int32_t offset, long long value) { if ((value < 0) || (value > static_cast(UINT_MAX))) { @@ -209,7 +212,7 @@ bool HapSigningBlockUtils::SetUnsignedInt32(HapByteBuffer& buffer, int32_t offse buffer.PutInt32(offset, static_cast(value)); return true; } - + bool HapSigningBlockUtils::FindHapSigningBlock(RandomAccessFile& hapFile, long long centralDirOffset, SignatureInfo& signInfo) { @@ -235,12 +238,12 @@ bool HapSigningBlockUtils::FindHapSigningBlock(RandomAccessFile& hapFile, long l HAPVERIFY_LOG_ERROR("ParseSignBlockHead failed"); return false; } - + if (!CheckSignBlockHead(hapSignBlockHead)) { HAPVERIFY_LOG_ERROR("hapSignBlockHead is invalid"); return false; } - + signInfo.version = hapSignBlockHead.version; long long blockArrayLen = hapSignBlockHead.hapSignBlockSize - ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH; long long hapSignBlockOffset = centralDirOffset - hapSignBlockHead.hapSignBlockSize; @@ -251,7 +254,7 @@ bool HapSigningBlockUtils::FindHapSigningBlock(RandomAccessFile& hapFile, long l signInfo.hapSigningBlockOffset = hapSignBlockOffset; return FindHapSubSigningBlock(hapFile, hapSignBlockHead.blockCount, blockArrayLen, hapSignBlockOffset, signInfo); } - + bool HapSigningBlockUtils::CheckSignBlockHead(const HapSignBlockHead& hapSignBlockHead) { long long magic_low = HAP_SIG_BLOCK_MAGIC_LOW; @@ -260,28 +263,28 @@ bool HapSigningBlockUtils::CheckSignBlockHead(const HapSignBlockHead& hapSignBlo magic_low = HAP_SIG_BLOCK_MAGIC_LOW_OLD; magic_high = HAP_SIG_BLOCK_MAGIC_HIGH_OLD; } - + if ((hapSignBlockHead.hapSignBlockMagicLo != magic_low) || (hapSignBlockHead.hapSignBlockMagicHi != magic_high)) { HAPVERIFY_LOG_ERROR("No HAP Signing Block before ZIP Central Directory"); return false; } - + if ((hapSignBlockHead.hapSignBlockSize < ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH) || (hapSignBlockHead.hapSignBlockSize > MAX_HAP_SIGN_BLOCK_SIZE)) { HAPVERIFY_LOG_ERROR("HAP Signing Block size out of range %{public}lld", hapSignBlockHead.hapSignBlockSize); return false; } - + if (hapSignBlockHead.blockCount > MAX_BLOCK_COUNT) { HAPVERIFY_LOG_ERROR("HAP Signing Block count out of range %{public}d", hapSignBlockHead.blockCount); return false; } - + return true; } - + bool HapSigningBlockUtils::ParseSignBlockHead(HapSignBlockHead& hapSignBlockHead, HapByteBuffer& hapBlockHead) { return hapBlockHead.GetInt32(hapSignBlockHead.blockCount) && @@ -290,14 +293,14 @@ bool HapSigningBlockUtils::ParseSignBlockHead(HapSignBlockHead& hapSignBlockHead hapBlockHead.GetInt64(hapSignBlockHead.hapSignBlockMagicHi) && hapBlockHead.GetInt32(hapSignBlockHead.version); } - + bool HapSigningBlockUtils::ParseSubSignBlockHead(HapSubSignBlockHead& subSignBlockHead, HapByteBuffer& hapBlockHead) { return hapBlockHead.GetUInt32(subSignBlockHead.type) && hapBlockHead.GetUInt32(subSignBlockHead.length) && hapBlockHead.GetUInt32(subSignBlockHead.offset); } - + /* * Hap Sign Block Format: * HapSubSignBlock1_Head @@ -334,13 +337,13 @@ bool HapSigningBlockUtils::FindHapSubSigningBlock(RandomAccessFile& hapFile, int return false; } readLen += sizeof(HapSubSignBlockHead); - + readHeadOffset += sizeof(HapSubSignBlockHead); if (readHeadOffset > offsetMax) { HAPVERIFY_LOG_ERROR("find %{public}dst next head offset error", i); return false; } - + long long headOffset = static_cast(subSignBlockHead.offset); long long headLength = static_cast(subSignBlockHead.length); /* check subSignBlockHead */ @@ -352,7 +355,7 @@ bool HapSigningBlockUtils::FindHapSubSigningBlock(RandomAccessFile& hapFile, int HAPVERIFY_LOG_ERROR("no enough data to be read for %{public}dst subblock", i); return false; } - + long long dataOffset = hapSignBlockOffset + headOffset; HapByteBuffer signBuffer(subSignBlockHead.length); ret = hapFile.ReadFileFullyFromOffset(signBuffer, dataOffset); @@ -361,14 +364,14 @@ bool HapSigningBlockUtils::FindHapSubSigningBlock(RandomAccessFile& hapFile, int return false; } readLen += headLength; - + if (!ClassifyHapSubSigningBlock(signInfo, signBuffer, subSignBlockHead.type)) { HAPVERIFY_LOG_ERROR("ClassifyHapSubSigningBlock error, type is %{public}d", subSignBlockHead.type); return false; } } - + /* size of block must be equal to the sum of all subblocks length */ if (readLen != blockArrayLen) { HAPVERIFY_LOG_ERROR("readLen: %{public}lld is not same as blockArrayLen: %{public}lld", @@ -377,7 +380,7 @@ bool HapSigningBlockUtils::FindHapSubSigningBlock(RandomAccessFile& hapFile, int } return true; } - + bool HapSigningBlockUtils::ClassifyHapSubSigningBlock(SignatureInfo& signInfo, const HapByteBuffer& subBlock, uint32_t type) { @@ -407,7 +410,7 @@ bool HapSigningBlockUtils::ClassifyHapSubSigningBlock(SignatureInfo& signInfo, } return ret; } - + bool HapSigningBlockUtils::GetOptionalBlockIndex(std::vector& optionBlocks, int32_t type, int& index) { int32_t len = static_cast(optionBlocks.size()); @@ -419,7 +422,7 @@ bool HapSigningBlockUtils::GetOptionalBlockIndex(std::vector& opt } return false; } - + bool HapSigningBlockUtils::VerifyHapIntegrity( Pkcs7Context& digestInfo, RandomAccessFile& hapFile, SignatureInfo& signInfo) { @@ -427,33 +430,62 @@ bool HapSigningBlockUtils::VerifyHapIntegrity( HAPVERIFY_LOG_ERROR("Set central dir offset failed"); return false; } - + + long long fileSize = signInfo.hapSigningBlockOffset; long long centralDirSize = signInfo.hapEocdOffset - signInfo.hapCentralDirOffset; - HapFileDataSource contentsZip(hapFile, 0, signInfo.hapSigningBlockOffset, 0); + HapFileDataSource contentsZip(hapFile, 0, fileSize, 0); HapFileDataSource centralDir(hapFile, signInfo.hapCentralDirOffset, centralDirSize, 0); HapByteBufferDataSource eocd(signInfo.hapEocd); DataSource* content[ZIP_BLOCKS_NUM_NEED_DIGEST] = { &contentsZip, ¢ralDir, &eocd }; int32_t nId = HapVerifyOpensslUtils::GetDigestAlgorithmId(digestInfo.digestAlgorithm); DigestParameter digestParam = GetDigestParameter(nId); HapByteBuffer chunkDigest; - if (!ComputeDigestsForEachChunk(digestParam, content, ZIP_BLOCKS_NUM_NEED_DIGEST, chunkDigest)) { - HAPVERIFY_LOG_ERROR("Compute Content Digests failed, alg: %{public}d", nId); + int32_t chunkCount = 0; + int32_t sumOfChunksLen = 0; + if (!GetSumOfChunkDigestLen(content, ZIP_BLOCKS_NUM_NEED_DIGEST, digestParam.digestOutputSizeBytes, + chunkCount, sumOfChunksLen)) { + HAPVERIFY_LOG_ERROR("GetSumOfChunkDigestLen failed"); return false; } - + chunkDigest.SetCapacity(sumOfChunksLen); + chunkDigest.PutByte(0, ZIP_FIRST_LEVEL_CHUNK_PREFIX); + chunkDigest.PutInt32(1, chunkCount); + if (fileSize <= SMALL_FILE_SIZE) { + // No parallel for small size <= 2MB. + int32_t offset = ZIP_CHUNK_DIGEST_PRIFIX_LEN; + if (!ComputeDigestsForEachChunk(digestParam, content, ZIP_BLOCKS_NUM_NEED_DIGEST, chunkDigest, offset)) { + HAPVERIFY_LOG_ERROR("Compute Content Digests failed, alg: %{public}d", nId); + return false; + } + } else { + // Compute digests for contents zip in parallel. + int32_t contentsZipChunkCount = GetChunkCount(fileSize, CHUNK_SIZE); + if (!ComputeDigestsForContentsZip(nId, hapFile, contentsZipChunkCount, fileSize, chunkDigest)) { + HAPVERIFY_LOG_ERROR("ComputeDigestsForContentsZip failed, alg: %{public}d", nId); + return false; + } + // Compute digests for other contents. + int32_t offset = ZIP_CHUNK_DIGEST_PRIFIX_LEN + contentsZipChunkCount * digestParam.digestOutputSizeBytes; + if (!ComputeDigestsForEachChunk(digestParam, content + 1, ZIP_BLOCKS_NUM_NEED_DIGEST - 1, chunkDigest, + offset)) { + HAPVERIFY_LOG_ERROR("Compute Content Digests failed, alg: %{public}d", nId); + return false; + } + } + HapByteBuffer actualDigest; if (!ComputeDigestsWithOptionalBlock(digestParam, signInfo.optionBlocks, chunkDigest, actualDigest)) { HAPVERIFY_LOG_ERROR("Compute Final Digests failed, alg: %{public}d", nId); return false; } - + if (!digestInfo.content.IsEqual(actualDigest)) { HAPVERIFY_LOG_ERROR("digest of contents verify failed, alg %{public}d", nId); return false; } return true; } - + bool HapSigningBlockUtils::ComputeDigestsWithOptionalBlock(const DigestParameter& digestParam, const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, HapByteBuffer& finalDigest) { @@ -464,12 +496,12 @@ bool HapSigningBlockUtils::ComputeDigestsWithOptionalBlock(const DigestParameter digestLen, digestParam.digestOutputSizeBytes); return false; } - + finalDigest.SetCapacity(digestParam.digestOutputSizeBytes); finalDigest.PutData(0, reinterpret_cast(out), digestParam.digestOutputSizeBytes); return true; } - + bool HapSigningBlockUtils::GetSumOfChunkDigestLen(DataSource* contents[], int32_t len, int32_t chunkDigestLen, int& chunkCount, int& sumOfChunkDigestLen) { @@ -481,66 +513,94 @@ bool HapSigningBlockUtils::GetSumOfChunkDigestLen(DataSource* contents[], int32_ contents[i]->Reset(); chunkCount += GetChunkCount(contents[i]->Remaining(), CHUNK_SIZE); } - + if (chunkCount <= 0) { HAPVERIFY_LOG_ERROR("no content for digest"); return false; } - + if (chunkDigestLen < 0 || ((INT_MAX - ZIP_CHUNK_DIGEST_PRIFIX_LEN) / chunkCount) < chunkDigestLen) { HAPVERIFY_LOG_ERROR("overflow chunkCount: %{public}d, chunkDigestLen: %{public}d", chunkCount, chunkDigestLen); return false; } - + sumOfChunkDigestLen = ZIP_CHUNK_DIGEST_PRIFIX_LEN + chunkCount * chunkDigestLen; return true; } - -bool HapSigningBlockUtils::ComputeDigestsForEachChunk(const DigestParameter& digestParam, - DataSource* contents[], int32_t len, HapByteBuffer& result) + +bool HapSigningBlockUtils::ComputeDigestsForContentsZip(int32_t nId, RandomAccessFile& hapFile, int32_t chunkNum, + long long fileSize, HapByteBuffer& digestsBuffer) { - int32_t chunkCount = 0; - int32_t sumOfChunksLen = 0; - if (!GetSumOfChunkDigestLen(contents, len, digestParam.digestOutputSizeBytes, chunkCount, sumOfChunksLen)) { - HAPVERIFY_LOG_ERROR("GetSumOfChunkDigestLen failed"); - return false; + int32_t chunkNumToUpdate = (chunkNum + ZIP_UPDATE_DIGEST_THREADS_NUM - 1) / ZIP_UPDATE_DIGEST_THREADS_NUM; + int32_t offset = ZIP_CHUNK_DIGEST_PRIFIX_LEN; + std::vector threads; + std::vector results(ZIP_UPDATE_DIGEST_THREADS_NUM, false); + for (int i = 0; i < ZIP_UPDATE_DIGEST_THREADS_NUM; i++) { + threads.emplace_back([&, i, chunkNumToUpdate, fileSize]() { + long long fileBeginPosition = CHUNK_SIZE * chunkNumToUpdate * i; + long long fileEndPosition = std::min(CHUNK_SIZE * chunkNumToUpdate * (i + 1), fileSize); + HapFileDataSource hapDataChunk(hapFile, fileBeginPosition, fileEndPosition - fileBeginPosition, 0); + DigestParameter digestParam = GetDigestParameter(nId); + int32_t digestOffset = offset + chunkNumToUpdate * digestParam.digestOutputSizeBytes * i; + results[i] = ComputeDigestsForDataSource(digestParam, &hapDataChunk, digestsBuffer, digestOffset); + }); + } + + for (auto& thread : threads) { + thread.join(); + } + + for (bool computeDigestResult : results) { + if (!computeDigestResult) { + HAPVERIFY_LOG_ERROR("Compute digests failed"); + return false; + } } - result.SetCapacity(sumOfChunksLen); - result.PutByte(0, ZIP_FIRST_LEVEL_CHUNK_PREFIX); - result.PutInt32(1, chunkCount); - - int32_t chunkIndex = 0; + + return true; +} + +bool HapSigningBlockUtils::ComputeDigestsForDataSource(const DigestParameter& digestParam, DataSource* content, + HapByteBuffer& result, int32_t& offset) +{ unsigned char out[EVP_MAX_MD_SIZE]; unsigned char chunkContentPrefix[ZIP_CHUNK_DIGEST_PRIFIX_LEN] = {ZIP_SECOND_LEVEL_CHUNK_PREFIX, 0, 0, 0, 0}; - int32_t offset = ZIP_CHUNK_DIGEST_PRIFIX_LEN; + while (content->HasRemaining()) { + int32_t chunkSize = std::min(content->Remaining(), CHUNK_SIZE); + if (!InitDigestPrefix(digestParam, chunkContentPrefix, chunkSize)) { + HAPVERIFY_LOG_ERROR("InitDigestPrefix failed"); + return false; + } + + if (!content->ReadDataAndDigestUpdate(digestParam, chunkSize)) { + HAPVERIFY_LOG_ERROR("Copy Partial Buffer failed"); + return false; + } + + int32_t digestLen = HapVerifyOpensslUtils::GetDigest(digestParam, out); + if (digestLen != digestParam.digestOutputSizeBytes) { + HAPVERIFY_LOG_ERROR("GetDigest failed len: %{public}d digestSizeBytes: %{public}d", + digestLen, digestParam.digestOutputSizeBytes); + return false; + } + result.PutData(offset, reinterpret_cast(out), digestParam.digestOutputSizeBytes); + offset += digestLen; + } + return true; +} +bool HapSigningBlockUtils::ComputeDigestsForEachChunk(const DigestParameter& digestParam, + DataSource* contents[], int32_t len, HapByteBuffer& result, int32_t& offset) +{ for (int32_t i = 0; i < len; i++) { - while (contents[i]->HasRemaining()) { - int32_t chunkSize = std::min(contents[i]->Remaining(), CHUNK_SIZE); - if (!InitDigestPrefix(digestParam, chunkContentPrefix, chunkSize)) { - HAPVERIFY_LOG_ERROR("InitDigestPrefix failed"); - return false; - } - - if (!contents[i]->ReadDataAndDigestUpdate(digestParam, chunkSize)) { - HAPVERIFY_LOG_ERROR("Copy Partial Buffer failed, count: %{public}d", chunkIndex); - return false; - } - - int32_t digestLen = HapVerifyOpensslUtils::GetDigest(digestParam, out); - if (digestLen != digestParam.digestOutputSizeBytes) { - HAPVERIFY_LOG_ERROR("GetDigest failed len: %{public}d digestSizeBytes: %{public}d", - digestLen, digestParam.digestOutputSizeBytes); - return false; - } - result.PutData(offset, reinterpret_cast(out), digestParam.digestOutputSizeBytes); - offset += digestLen; - chunkIndex++; + if (!ComputeDigestsForDataSource(digestParam, contents[i], result, offset)) { + HAPVERIFY_LOG_ERROR("Compute digest failed"); + return false; } } return true; } - + DigestParameter HapSigningBlockUtils::GetDigestParameter(int32_t nId) { DigestParameter digestParam; @@ -550,20 +610,20 @@ DigestParameter HapSigningBlockUtils::GetDigestParameter(int32_t nId) EVP_MD_CTX_init(digestParam.ptrCtx); return digestParam; } - + int32_t HapSigningBlockUtils::GetChunkCount(long long inputSize, long long chunkSize) { if (chunkSize <= 0 || inputSize > LLONG_MAX - chunkSize) { return 0; } - + long long res = (inputSize + chunkSize - 1) / chunkSize; if (res > INT_MAX || res < 0) { return 0; } return static_cast(res); } - + bool HapSigningBlockUtils::InitDigestPrefix(const DigestParameter& digestParam, unsigned char (&chunkContentPrefix)[ZIP_CHUNK_DIGEST_PRIFIX_LEN], int32_t chunkLen) { @@ -571,12 +631,12 @@ bool HapSigningBlockUtils::InitDigestPrefix(const DigestParameter& digestParam, HAPVERIFY_LOG_ERROR("memcpy_s failed"); return false; } - + if (!HapVerifyOpensslUtils::DigestInit(digestParam)) { HAPVERIFY_LOG_ERROR("DigestInit failed"); return false; } - + if (!HapVerifyOpensslUtils::DigestUpdate(digestParam, chunkContentPrefix, ZIP_CHUNK_DIGEST_PRIFIX_LEN)) { HAPVERIFY_LOG_ERROR("DigestUpdate failed"); return false;