From d00db663366798df80f1883344f25ca5d4da2d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=9B=E6=99=93=E5=AE=87?= Date: Wed, 14 May 2025 15:59:21 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E9=AA=8C=E7=AD=BE=E5=B9=B6=E8=A1=8C=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 丛晓宇 --- .../include/util/hap_signing_block_utils.h | 10 +- .../src/util/hap_signing_block_utils.cpp | 139 +++++++++++++----- 2 files changed, 112 insertions(+), 37 deletions(-) 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 53959ec..69b0c1d 100644 --- a/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h +++ b/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h @@ -76,6 +76,8 @@ 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; @@ -99,7 +101,13 @@ 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 bool VerifySignInfo(const DigestParameter& digestParam, int32_t nId, + const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, Pkcs7Context& digestInfo); 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); 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 b8b4d8b..d7b1c7b 100644 --- a/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp +++ b/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp @@ -16,6 +16,7 @@ #include "util/hap_signing_block_utils.h" #include +#include #include #include "algorithm" @@ -36,6 +37,7 @@ const long long HapSigningBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH = 449779798307046 /* 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; @@ -46,6 +48,7 @@ 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; @@ -428,21 +431,56 @@ bool HapSigningBlockUtils::VerifyHapIntegrity( 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; + } + } + + return VerifySignInfo(digestParam, nId, signInfo.optionBlocks, chunkDigest, digestInfo); +} +bool HapSigningBlockUtils::VerifySignInfo(const DigestParameter& digestParam, int32_t nId, + const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, Pkcs7Context& digestInfo) +{ HapByteBuffer actualDigest; - if (!ComputeDigestsWithOptionalBlock(digestParam, signInfo.optionBlocks, chunkDigest, actualDigest)) { + if (!ComputeDigestsWithOptionalBlock(digestParam, optionalBlocks, chunkDigest, actualDigest)) { HAPVERIFY_LOG_ERROR("Compute Final Digests failed, alg: %{public}d", nId); return false; } @@ -497,45 +535,74 @@ bool HapSigningBlockUtils::GetSumOfChunkDigestLen(DataSource* contents[], int32_ 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; - 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; - } + 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 (!contents[i]->ReadDataAndDigestUpdate(digestParam, chunkSize)) { - HAPVERIFY_LOG_ERROR("Copy Partial Buffer failed, count: %{public}d", chunkIndex); - 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; - chunkIndex++; + 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++) { + if (!ComputeDigestsForDataSource(digestParam, contents[i], result, offset)) { + HAPVERIFY_LOG_ERROR("Compute digest failed"); + return false; } } return true; -- Gitee From a9ac836a705b27853cd6cb230eafd5bcfb602a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=9B=E6=99=93=E5=AE=87?= Date: Mon, 19 May 2025 15:58:24 +0800 Subject: [PATCH 2/5] update function name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 丛晓宇 --- .../include/util/hap_signing_block_utils.h | 6 ++-- .../src/util/hap_signing_block_utils.cpp | 32 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) 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 69b0c1d..d5c44b0 100644 --- a/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h +++ b/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h @@ -100,13 +100,13 @@ private: DLL_EXPORT static bool ComputeDigestsWithOptionalBlock(const DigestParameter& digestParam, const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, HapByteBuffer& finalDigest); - static bool ComputeDigestsForEachChunk(const DigestParameter& digestParam, DataSource* contents[], - int32_t len, HapByteBuffer& result, int32_t& offset); + static bool ComputeDigestsForDataSourceArray(const DigestParameter& digestParam, DataSource* contents[], + int32_t len, HapByteBuffer& result, const 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 bool VerifySignInfo(const DigestParameter& digestParam, int32_t nId, + static bool VerifyDigest(const DigestParameter& digestParam, const int32_t nId, const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, Pkcs7Context& digestInfo); static int32_t GetChunkCount(long long inputSize, long long chunkSize); static bool InitDigestPrefix(const DigestParameter& digestParam, 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 d7b1c7b..319919a 100644 --- a/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp +++ b/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp @@ -431,9 +431,9 @@ bool HapSigningBlockUtils::VerifyHapIntegrity( return false; } - long long fileSize = signInfo.hapSigningBlockOffset; + long long contentsZipSize = signInfo.hapSigningBlockOffset; long long centralDirSize = signInfo.hapEocdOffset - signInfo.hapCentralDirOffset; - HapFileDataSource contentsZip(hapFile, 0, fileSize, 0); + HapFileDataSource contentsZip(hapFile, 0, contentsZipSize, 0); HapFileDataSource centralDir(hapFile, signInfo.hapCentralDirOffset, centralDirSize, 0); HapByteBufferDataSource eocd(signInfo.hapEocd); DataSource* content[ZIP_BLOCKS_NUM_NEED_DIGEST] = { &contentsZip, ¢ralDir, &eocd }; @@ -450,33 +450,33 @@ bool HapSigningBlockUtils::VerifyHapIntegrity( chunkDigest.SetCapacity(sumOfChunksLen); chunkDigest.PutByte(0, ZIP_FIRST_LEVEL_CHUNK_PREFIX); chunkDigest.PutInt32(1, chunkCount); - if (fileSize <= SMALL_FILE_SIZE) { + if (contentsZipSize <= 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)) { + if (!ComputeDigestsForDataSourceArray(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)) { + int32_t contentsZipChunkCount = GetChunkCount(contentsZipSize, CHUNK_SIZE); + if (!ComputeDigestsForContentsZip(nId, hapFile, contentsZipChunkCount, contentsZipSize, 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)) { + if (!ComputeDigestsForDataSourceArray(digestParam, content + 1, + ZIP_BLOCKS_NUM_NEED_DIGEST - 1, chunkDigest, offset)) { HAPVERIFY_LOG_ERROR("Compute Content Digests failed, alg: %{public}d", nId); return false; } } - return VerifySignInfo(digestParam, nId, signInfo.optionBlocks, chunkDigest, digestInfo); + return VerifyDigest(digestParam, nId, signInfo.optionBlocks, chunkDigest, digestInfo); } -bool HapSigningBlockUtils::VerifySignInfo(const DigestParameter& digestParam, int32_t nId, +bool HapSigningBlockUtils::VerifyDigest(const DigestParameter& digestParam, const int32_t nId, const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, Pkcs7Context& digestInfo) { HapByteBuffer actualDigest; @@ -536,16 +536,16 @@ bool HapSigningBlockUtils::GetSumOfChunkDigestLen(DataSource* contents[], int32_ } bool HapSigningBlockUtils::ComputeDigestsForContentsZip(int32_t nId, RandomAccessFile& hapFile, int32_t chunkNum, - long long fileSize, HapByteBuffer& digestsBuffer) + long long contentsZipSize, HapByteBuffer& digestsBuffer) { 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]() { + for (int32_t i = 0; i < ZIP_UPDATE_DIGEST_THREADS_NUM; i++) { + threads.emplace_back([&, i, chunkNumToUpdate, contentsZipSize]() { long long fileBeginPosition = CHUNK_SIZE * chunkNumToUpdate * i; - long long fileEndPosition = std::min(CHUNK_SIZE * chunkNumToUpdate * (i + 1), fileSize); + long long fileEndPosition = std::min(CHUNK_SIZE * chunkNumToUpdate * (i + 1), contentsZipSize); HapFileDataSource hapDataChunk(hapFile, fileBeginPosition, fileEndPosition - fileBeginPosition, 0); DigestParameter digestParam = GetDigestParameter(nId); int32_t digestOffset = offset + chunkNumToUpdate * digestParam.digestOutputSizeBytes * i; @@ -596,8 +596,8 @@ bool HapSigningBlockUtils::ComputeDigestsForDataSource(const DigestParameter& di return true; } -bool HapSigningBlockUtils::ComputeDigestsForEachChunk(const DigestParameter& digestParam, - DataSource* contents[], int32_t len, HapByteBuffer& result, int32_t& offset) +bool HapSigningBlockUtils::ComputeDigestsForDataSourceArray(const DigestParameter& digestParam, + DataSource* contents[], int32_t len, HapByteBuffer& result, int32_t offset) { for (int32_t i = 0; i < len; i++) { if (!ComputeDigestsForDataSource(digestParam, contents[i], result, offset)) { -- Gitee From 0f557f147ec19397f53436384dbf859c905b8e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=9B=E6=99=93=E5=AE=87?= Date: Mon, 19 May 2025 15:58:24 +0800 Subject: [PATCH 3/5] add unit test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 丛晓宇 --- .../include/util/hap_signing_block_utils.h | 6 +-- .../src/util/hap_signing_block_utils.cpp | 32 +++++++------- .../include/hap_signing_block_utils_test.h | 2 +- .../test/unittest/include/test_const.h | 2 + .../src/hap_signing_block_utils_test.cpp | 42 +++++++++++++------ .../unittest/src/random_access_file_test.cpp | 4 +- 6 files changed, 54 insertions(+), 34 deletions(-) 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 69b0c1d..d5c44b0 100644 --- a/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h +++ b/interfaces/innerkits/appverify/include/util/hap_signing_block_utils.h @@ -100,13 +100,13 @@ private: DLL_EXPORT static bool ComputeDigestsWithOptionalBlock(const DigestParameter& digestParam, const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, HapByteBuffer& finalDigest); - static bool ComputeDigestsForEachChunk(const DigestParameter& digestParam, DataSource* contents[], - int32_t len, HapByteBuffer& result, int32_t& offset); + static bool ComputeDigestsForDataSourceArray(const DigestParameter& digestParam, DataSource* contents[], + int32_t len, HapByteBuffer& result, const 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 bool VerifySignInfo(const DigestParameter& digestParam, int32_t nId, + static bool VerifyDigest(const DigestParameter& digestParam, const int32_t nId, const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, Pkcs7Context& digestInfo); static int32_t GetChunkCount(long long inputSize, long long chunkSize); static bool InitDigestPrefix(const DigestParameter& digestParam, 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 d7b1c7b..319919a 100644 --- a/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp +++ b/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp @@ -431,9 +431,9 @@ bool HapSigningBlockUtils::VerifyHapIntegrity( return false; } - long long fileSize = signInfo.hapSigningBlockOffset; + long long contentsZipSize = signInfo.hapSigningBlockOffset; long long centralDirSize = signInfo.hapEocdOffset - signInfo.hapCentralDirOffset; - HapFileDataSource contentsZip(hapFile, 0, fileSize, 0); + HapFileDataSource contentsZip(hapFile, 0, contentsZipSize, 0); HapFileDataSource centralDir(hapFile, signInfo.hapCentralDirOffset, centralDirSize, 0); HapByteBufferDataSource eocd(signInfo.hapEocd); DataSource* content[ZIP_BLOCKS_NUM_NEED_DIGEST] = { &contentsZip, ¢ralDir, &eocd }; @@ -450,33 +450,33 @@ bool HapSigningBlockUtils::VerifyHapIntegrity( chunkDigest.SetCapacity(sumOfChunksLen); chunkDigest.PutByte(0, ZIP_FIRST_LEVEL_CHUNK_PREFIX); chunkDigest.PutInt32(1, chunkCount); - if (fileSize <= SMALL_FILE_SIZE) { + if (contentsZipSize <= 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)) { + if (!ComputeDigestsForDataSourceArray(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)) { + int32_t contentsZipChunkCount = GetChunkCount(contentsZipSize, CHUNK_SIZE); + if (!ComputeDigestsForContentsZip(nId, hapFile, contentsZipChunkCount, contentsZipSize, 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)) { + if (!ComputeDigestsForDataSourceArray(digestParam, content + 1, + ZIP_BLOCKS_NUM_NEED_DIGEST - 1, chunkDigest, offset)) { HAPVERIFY_LOG_ERROR("Compute Content Digests failed, alg: %{public}d", nId); return false; } } - return VerifySignInfo(digestParam, nId, signInfo.optionBlocks, chunkDigest, digestInfo); + return VerifyDigest(digestParam, nId, signInfo.optionBlocks, chunkDigest, digestInfo); } -bool HapSigningBlockUtils::VerifySignInfo(const DigestParameter& digestParam, int32_t nId, +bool HapSigningBlockUtils::VerifyDigest(const DigestParameter& digestParam, const int32_t nId, const std::vector& optionalBlocks, const HapByteBuffer& chunkDigest, Pkcs7Context& digestInfo) { HapByteBuffer actualDigest; @@ -536,16 +536,16 @@ bool HapSigningBlockUtils::GetSumOfChunkDigestLen(DataSource* contents[], int32_ } bool HapSigningBlockUtils::ComputeDigestsForContentsZip(int32_t nId, RandomAccessFile& hapFile, int32_t chunkNum, - long long fileSize, HapByteBuffer& digestsBuffer) + long long contentsZipSize, HapByteBuffer& digestsBuffer) { 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]() { + for (int32_t i = 0; i < ZIP_UPDATE_DIGEST_THREADS_NUM; i++) { + threads.emplace_back([&, i, chunkNumToUpdate, contentsZipSize]() { long long fileBeginPosition = CHUNK_SIZE * chunkNumToUpdate * i; - long long fileEndPosition = std::min(CHUNK_SIZE * chunkNumToUpdate * (i + 1), fileSize); + long long fileEndPosition = std::min(CHUNK_SIZE * chunkNumToUpdate * (i + 1), contentsZipSize); HapFileDataSource hapDataChunk(hapFile, fileBeginPosition, fileEndPosition - fileBeginPosition, 0); DigestParameter digestParam = GetDigestParameter(nId); int32_t digestOffset = offset + chunkNumToUpdate * digestParam.digestOutputSizeBytes * i; @@ -596,8 +596,8 @@ bool HapSigningBlockUtils::ComputeDigestsForDataSource(const DigestParameter& di return true; } -bool HapSigningBlockUtils::ComputeDigestsForEachChunk(const DigestParameter& digestParam, - DataSource* contents[], int32_t len, HapByteBuffer& result, int32_t& offset) +bool HapSigningBlockUtils::ComputeDigestsForDataSourceArray(const DigestParameter& digestParam, + DataSource* contents[], int32_t len, HapByteBuffer& result, int32_t offset) { for (int32_t i = 0; i < len; i++) { if (!ComputeDigestsForDataSource(digestParam, contents[i], result, offset)) { diff --git a/interfaces/innerkits/appverify/test/unittest/include/hap_signing_block_utils_test.h b/interfaces/innerkits/appverify/test/unittest/include/hap_signing_block_utils_test.h index 74b60c3..9b4a77c 100644 --- a/interfaces/innerkits/appverify/test/unittest/include/hap_signing_block_utils_test.h +++ b/interfaces/innerkits/appverify/test/unittest/include/hap_signing_block_utils_test.h @@ -26,7 +26,7 @@ namespace OHOS { namespace Security { namespace Verify { -long long CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo); +long long CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo, const int32_t fileSize); } } } diff --git a/interfaces/innerkits/appverify/test/unittest/include/test_const.h b/interfaces/innerkits/appverify/test/unittest/include/test_const.h index f033fcb..c2eebc1 100644 --- a/interfaces/innerkits/appverify/test/unittest/include/test_const.h +++ b/interfaces/innerkits/appverify/test/unittest/include/test_const.h @@ -40,6 +40,8 @@ constexpr int32_t TEST_HAPBYTEBUFFER_POSITION = 10; constexpr int32_t TEST_HAPBYTEBUFFER_UINT16_LENGTH = 2; constexpr int32_t TEST_HAPBYTEBUFFER_INT64_LENGTH = 8; +// large file size 3MB +constexpr int32_t TEST_LARGE_FILE_BLOCK_LENGTH = 3 * 1048576; constexpr int32_t TEST_FILE_BLOCK_LENGTH = 50; constexpr int32_t TEST_FILE_BLOCK_COUNT = 3; diff --git a/interfaces/innerkits/appverify/test/unittest/src/hap_signing_block_utils_test.cpp b/interfaces/innerkits/appverify/test/unittest/src/hap_signing_block_utils_test.cpp index 6bf6dc0..c4daa81 100644 --- a/interfaces/innerkits/appverify/test/unittest/src/hap_signing_block_utils_test.cpp +++ b/interfaces/innerkits/appverify/test/unittest/src/hap_signing_block_utils_test.cpp @@ -19,6 +19,7 @@ #include #include +#include #include "common/hap_byte_buffer_data_source.h" #include "common/random_access_file.h" @@ -30,27 +31,31 @@ using namespace OHOS::Security::Verify; namespace OHOS { namespace Security { namespace Verify { -void CreateHapSubSignBlockHead(HapSubSignBlockHead& signBlob, HapSubSignBlockHead& profileBlob, - HapSubSignBlockHead& propertyBlob) +void CreateHapSubSignBlockHead(HapSubSignBlockHead& signBlob, HapSubSignBlockHead& profileBlob, + HapSubSignBlockHead& propertyBlob, const int32_t fileSize) { signBlob.type = HAP_SIGN_BLOB; - signBlob.length = TEST_FILE_BLOCK_LENGTH; + signBlob.length = fileSize; signBlob.offset = sizeof(HapSubSignBlockHead) * TEST_FILE_BLOCK_COUNT; profileBlob.type = PROFILE_BLOB; - profileBlob.length = TEST_FILE_BLOCK_LENGTH; + profileBlob.length = fileSize; profileBlob.offset = signBlob.offset + signBlob.length; propertyBlob.type = PROPERTY_BLOB; - propertyBlob.length = TEST_FILE_BLOCK_LENGTH; + propertyBlob.length = fileSize; propertyBlob.offset = profileBlob.offset + profileBlob.length; } -long long CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo) +long long CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo, const int32_t fileSize) { std::ofstream hapFile(pathFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); if (!hapFile.is_open()) { return 0; } - char block[TEST_FILE_BLOCK_LENGTH] = {0}; + + char block[fileSize]; + if(memset_s(block, fileSize, 0, fileSize) != 0) { + return 0; + } /* input contents of ZIP entries */ hapFile.seekp(0, std::ios_base::beg); hapFile.write(block, sizeof(block)); @@ -58,7 +63,7 @@ long long CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo) HapSubSignBlockHead signBlob; HapSubSignBlockHead profileBlob; HapSubSignBlockHead propertyBlob; - CreateHapSubSignBlockHead(signBlob, profileBlob, propertyBlob); + CreateHapSubSignBlockHead(signBlob, profileBlob, propertyBlob, fileSize); hapFile.write(reinterpret_cast(&signBlob), sizeof(signBlob)); hapFile.write(reinterpret_cast(&profileBlob), sizeof(profileBlob)); hapFile.write(reinterpret_cast(&propertyBlob), sizeof(propertyBlob)); @@ -84,14 +89,14 @@ long long CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo) hapFile.write(reinterpret_cast(&magic), sizeof(magic)); uint32_t centralDirLen = sizeof(block); hapFile.write(reinterpret_cast(¢ralDirLen), sizeof(centralDirLen)); - uint32_t centralDirOffset = TEST_FILE_BLOCK_LENGTH + signBlockSize; + uint32_t centralDirOffset = fileSize + signBlockSize; hapFile.write(reinterpret_cast(¢ralDirOffset), sizeof(centralDirOffset)); short eocdCommentLen = 0; hapFile.write(reinterpret_cast(&eocdCommentLen), sizeof(eocdCommentLen)); hapFile.close(); signInfo.hapCentralDirOffset = centralDirOffset; signInfo.hapEocdOffset = centralDirOffset + centralDirLen; - signInfo.hapSignatureBlock.SetCapacity(TEST_FILE_BLOCK_LENGTH); + signInfo.hapSignatureBlock.SetCapacity(fileSize); signInfo.hapSignatureBlock.PutData(0, block, sizeof(block)); long long sumLen = signInfo.hapEocdOffset + sizeof(zidEocdSign) + sizeof(centralDirLen) + sizeof(centralDirOffset) + sizeof(magic) + sizeof(eocdCommentLen); @@ -145,7 +150,7 @@ HWTEST_F(HapSigningBlockUtilsTest, FindHapSignatureTest001, TestSize.Level1) */ std::string pathFile = "./test_hapverify.hap"; SignatureInfo signInfo; - int32_t sumLen = CreatTestZipFile(pathFile, signInfo); + int32_t sumLen = CreatTestZipFile(pathFile, signInfo, TEST_FILE_BLOCK_LENGTH); /* * @tc.steps: step2. test FindHapSignature function * @tc.expected: step2. the return will be true. @@ -204,7 +209,7 @@ HWTEST_F(HapSigningBlockUtilsTest, VerifyHapIntegrityTest001, TestSize.Level1) */ std::string pathFile = "./test_hapverify.hap"; SignatureInfo signInfo; - CreatTestZipFile(pathFile, signInfo); + CreatTestZipFile(pathFile, signInfo, TEST_FILE_BLOCK_LENGTH); /* * @tc.steps: step2. create an error digest to test VerifyHapIntegrity function * @tc.expected: step2. the return will be false. @@ -222,6 +227,19 @@ HWTEST_F(HapSigningBlockUtilsTest, VerifyHapIntegrityTest001, TestSize.Level1) RandomAccessFile hapTestFile1; hapTestFile.Init(pathFile); ASSERT_FALSE(hapSignBlockUtils.VerifyHapIntegrity(digestInfo1, hapTestFile1, signInfo)); + + /* + * @tc.steps: step3. create a larger file and an error digest to test VerifyHapIntegrity + * @tc.expected: step3. the return will be false. + */ + std::string pathFile2 = "./test_hapverify2.hap"; + SignatureInfo signInfo2; + CreatTestZipFile(pathFile2, signInfo2, TEST_LARGE_FILE_BLOCK_LENGTH); + Pkcs7Context digestInfo2; + digestInfo2.content.SetCapacity(TEST_LARGE_FILE_BLOCK_LENGTH); + RandomAccessFile hapTestFile2; + hapTestFile2.Init(pathFile2); + ASSERT_FALSE(hapSignBlockUtils.VerifyHapIntegrity(digestInfo2, hapTestFile2, signInfo2)); } /** diff --git a/interfaces/innerkits/appverify/test/unittest/src/random_access_file_test.cpp b/interfaces/innerkits/appverify/test/unittest/src/random_access_file_test.cpp index d62afc0..eab705c 100644 --- a/interfaces/innerkits/appverify/test/unittest/src/random_access_file_test.cpp +++ b/interfaces/innerkits/appverify/test/unittest/src/random_access_file_test.cpp @@ -72,7 +72,7 @@ HWTEST_F(RandomAccessFileTest, ReadFileFullyFromOffsetTest001, TestSize.Level1) */ std::string filePath = "./test_hapverify.zip"; SignatureInfo si0; - int32_t sumLen = CreatTestZipFile(filePath, si0); + int32_t sumLen = CreatTestZipFile(filePath, si0, TEST_FILE_BLOCK_LENGTH); RandomAccessFile hapTestFile1; bool initRet = hapTestFile1.Init(filePath); ASSERT_TRUE(initRet); @@ -101,7 +101,7 @@ HWTEST_F(RandomAccessFileTest, ReadFileFullyFromOffsetTest001, TestSize.Level1) */ std::string testFile = "./test_hapverify.txt"; SignatureInfo si; - sumLen = CreatTestZipFile(testFile, si); + sumLen = CreatTestZipFile(testFile, si, TEST_FILE_BLOCK_LENGTH); RandomAccessFile hapTestFile2; initRet = hapTestFile2.Init(testFile); ASSERT_TRUE(initRet); -- Gitee From 45275eb48608e3d9a66bbe72cd61c79644756bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=9B=E6=99=93=E5=AE=87?= Date: Tue, 20 May 2025 10:08:01 +0800 Subject: [PATCH 4/5] add minus check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 丛晓宇 --- .../appverify/src/util/hap_signing_block_utils.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 319919a..541f7a8 100644 --- a/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp +++ b/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp @@ -546,7 +546,12 @@ bool HapSigningBlockUtils::ComputeDigestsForContentsZip(int32_t nId, RandomAcces threads.emplace_back([&, i, chunkNumToUpdate, contentsZipSize]() { long long fileBeginPosition = CHUNK_SIZE * chunkNumToUpdate * i; long long fileEndPosition = std::min(CHUNK_SIZE * chunkNumToUpdate * (i + 1), contentsZipSize); - HapFileDataSource hapDataChunk(hapFile, fileBeginPosition, fileEndPosition - fileBeginPosition, 0); + long long fileSize = fileEndPosition - fileEndPosition; + if(fileSize < 0) { + results[i] = true; + return; + } + HapFileDataSource hapDataChunk(hapFile, fileBeginPosition, fileSize, 0); DigestParameter digestParam = GetDigestParameter(nId); int32_t digestOffset = offset + chunkNumToUpdate * digestParam.digestOutputSizeBytes * i; results[i] = ComputeDigestsForDataSource(digestParam, &hapDataChunk, digestsBuffer, digestOffset); -- Gitee From 0044717a2c8e1998e4a95cbd7386e0a6c87a2510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=9B=E6=99=93=E5=AE=87?= Date: Wed, 21 May 2025 10:00:59 +0800 Subject: [PATCH 5/5] update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 丛晓宇 --- .../innerkits/appverify/src/util/hap_signing_block_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 541f7a8..150ac7a 100644 --- a/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp +++ b/interfaces/innerkits/appverify/src/util/hap_signing_block_utils.cpp @@ -546,7 +546,7 @@ bool HapSigningBlockUtils::ComputeDigestsForContentsZip(int32_t nId, RandomAcces threads.emplace_back([&, i, chunkNumToUpdate, contentsZipSize]() { long long fileBeginPosition = CHUNK_SIZE * chunkNumToUpdate * i; long long fileEndPosition = std::min(CHUNK_SIZE * chunkNumToUpdate * (i + 1), contentsZipSize); - long long fileSize = fileEndPosition - fileEndPosition; + long long fileSize = fileEndPosition - fileBeginPosition; if(fileSize < 0) { results[i] = true; return; -- Gitee