From 406622da2f9fc2b1070dd0ab732ee5e9a4bc2e37 Mon Sep 17 00:00:00 2001 From: Zhou Shihui Date: Mon, 23 Jun 2025 15:06:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=A0=A1=E9=AA=8Cp7b?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Zhou Shihui --- .../appverify/include/interfaces/hap_verify.h | 1 + .../appverify/include/verify/hap_verify_v2.h | 7 +- .../appverify/src/interfaces/hap_verify.cpp | 9 +++ .../appverify/src/verify/hap_verify_v2.cpp | 81 +++++++++++++++++++ .../test/unittest/src/hap_verify_test.cpp | 16 ++++ 5 files changed, 111 insertions(+), 3 deletions(-) diff --git a/interfaces/innerkits/appverify/include/interfaces/hap_verify.h b/interfaces/innerkits/appverify/include/interfaces/hap_verify.h index 69ae333..17bc128 100644 --- a/interfaces/innerkits/appverify/include/interfaces/hap_verify.h +++ b/interfaces/innerkits/appverify/include/interfaces/hap_verify.h @@ -34,6 +34,7 @@ extern "C" DLL_EXPORT int32_t ParseBundleNameAndAppIdentifier(const int32_t file std::string &appIdentifier); DLL_EXPORT void SetDevMode(DevMode devMode); DLL_EXPORT std::string GenerateUuidByKey(const std::string &key); +DLL_EXPORT int32_t VerifyProfile(const std::string& filePath, ProvisionInfo& provisionInfo); } // namespace Verify } // namespace Security } // namespace OHOS diff --git a/interfaces/innerkits/appverify/include/verify/hap_verify_v2.h b/interfaces/innerkits/appverify/include/verify/hap_verify_v2.h index ba84cb1..451cf47 100644 --- a/interfaces/innerkits/appverify/include/verify/hap_verify_v2.h +++ b/interfaces/innerkits/appverify/include/verify/hap_verify_v2.h @@ -33,17 +33,16 @@ public: int32_t Verify(const int32_t fileFd, HapVerifyResult& hapVerifyV1Result); int32_t ParseHapProfile(const std::string& filePath, HapVerifyResult& hapVerifyV1Result, bool readFile = false); int32_t ParseHapSignatureInfo(const std::string& filePath, SignatureInfo &hapSignInfo); + int32_t VerifyProfile(const std::string& filePath, ProvisionInfo& provisionInfo); private: int32_t Verify(RandomAccessFile& hapFile, HapVerifyResult& hapVerifyV1Result); - bool VerifyAppPkc7AndParseProfile(Pkcs7Context& pkcs7Context, HapByteBuffer& hapProfileBlock, - HapVerifyResult& hapVerifyV1Result); int32_t VerifyAppSourceAndParseProfile(Pkcs7Context& pkcs7Context, const HapByteBuffer& hapProfileBlock, HapVerifyResult& hapVerifyV1Result, bool& profileNeadWriteCrl); bool VerifyAppPkcs7(Pkcs7Context& pkcs7Context, const HapByteBuffer& hapSignatureBlock); - bool VerifyAppSource(Pkcs7Context& pkcs7Context, Pkcs7Context& profileContext); DLL_EXPORT bool GetDigestAndAlgorithm(Pkcs7Context& digest); DLL_EXPORT bool CheckFilePath(const std::string& filePath, std::string& standardFilePath); + bool CheckP7bPath(const std::string& filePath, std::string& standardFilePath); void WriteCrlIfNeed(const Pkcs7Context& pkcs7Context, const bool& profileNeedWriteCrl); DLL_EXPORT AppProvisionVerifyResult ParseAndVerifyProfileIfNeed(const std::string& profile, ProvisionInfo& provisionInfo, bool isCallParseAndVerify); @@ -57,6 +56,7 @@ private: void SetProfileBlockData(const Pkcs7Context& pkcs7Context, const HapByteBuffer& hapProfileBlock, ProvisionInfo& provisionInfo); void SetOrganization(ProvisionInfo& provisionInfo); + bool ParseProfileFromP7b(const std::string& p7bFilePath, Pkcs7Context& pkcs7Context); private: static const int32_t HEX_PRINT_LENGTH; @@ -67,6 +67,7 @@ private: static const std::string HAP_APP_PATTERN; static const std::string HQF_APP_PATTERN; static const std::string HSP_APP_PATTERN; + static const std::string P7B_PATTERN; }; } // namespace Verify } // namespace Security diff --git a/interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp b/interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp index b0d54c5..ea10873 100644 --- a/interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp +++ b/interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp @@ -139,6 +139,15 @@ std::string GenerateUuidByKey(const std::string &key) { return StringHash::GenerateUuidByKey(key); } + +int32_t VerifyProfile(const std::string& filePath, ProvisionInfo& provisionInfo) +{ + if (!g_isInit && !HapVerifyInit()) { + return VERIFY_SOURCE_INIT_FAIL; + } + HapVerifyV2 hapVerifyV2; + return hapVerifyV2.VerifyProfile(filePath, provisionInfo); +} } // namespace Verify } // namespace Security } // namespace OHOS diff --git a/interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp b/interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp index c4bdce0..7ca5675 100644 --- a/interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp +++ b/interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp @@ -17,7 +17,10 @@ #include #include +#include #include +#include +#include #include "securec.h" @@ -40,6 +43,7 @@ const int32_t HapVerifyV2::DIGEST_OFFSET_IN_CONTENT = 20; const std::string HapVerifyV2::HAP_APP_PATTERN = "[^]*.hap$"; const std::string HapVerifyV2::HQF_APP_PATTERN = "[^]*.hqf$"; const std::string HapVerifyV2::HSP_APP_PATTERN = "[^]*.hsp$"; +const std::string HapVerifyV2::P7B_PATTERN = "[^]*\\.p7b$"; const std::string OPENHARMONY_CERT = "C=CN, O=OpenHarmony, OU=OpenHarmony Team, CN=OpenHarmony Application Root CA"; int32_t HapVerifyV2::Verify(const std::string& filePath, HapVerifyResult& hapVerifyV1Result, bool readFile) @@ -94,6 +98,26 @@ bool HapVerifyV2::CheckFilePath(const std::string& filePath, std::string& standa return true; } +bool HapVerifyV2::CheckP7bPath(const std::string& filePath, std::string& standardFilePath) +{ + char path[PATH_MAX + 1] = { 0x00 }; + if (filePath.size() > PATH_MAX || realpath(filePath.c_str(), path) == nullptr) { + HAPVERIFY_LOG_ERROR("filePath is not a standard path"); + return false; + } + standardFilePath = std::string(path); + try { + if (!std::regex_match(standardFilePath, std::regex(P7B_PATTERN))) { + HAPVERIFY_LOG_ERROR("file is not p7b"); + return false; + } + } catch(const std::regex_error& e) { + HAPVERIFY_LOG_ERROR("regex match error"); + return false; + } + return true; +} + int32_t HapVerifyV2::Verify(RandomAccessFile& hapFile, HapVerifyResult& hapVerifyV1Result) { SignatureInfo hapSignInfo; @@ -530,6 +554,63 @@ void HapVerifyV2::SetOrganization(ProvisionInfo& provisionInfo) } provisionInfo.organization = organization; } + +int32_t HapVerifyV2::VerifyProfile(const std::string& filePath, ProvisionInfo& provisionInfo) +{ + HAPVERIFY_LOG_INFO("start to VerifyProfile"); + std::string standardFilePath; + if (!CheckP7bPath(filePath, standardFilePath)) { + return FILE_PATH_INVALID; + } + Pkcs7Context pkcs7Context; + if (!ParseProfileFromP7b(filePath, pkcs7Context)) { + return PROFILE_PARSE_FAIL; + } + std::string profile = std::string(pkcs7Context.content.GetBufferPtr(), pkcs7Context.content.GetCapacity()); + if (!HapProfileVerifyUtils::VerifyProfile(pkcs7Context)) { + HAPVERIFY_LOG_ERROR("profile verify failed"); + return APP_SOURCE_NOT_TRUSTED; + } + AppProvisionVerifyResult profileRet = ParseAndVerify(profile, provisionInfo); + if (profileRet != PROVISION_OK) { + HAPVERIFY_LOG_ERROR("profile parsing failed, error: %{public}d", static_cast(profileRet)); + if (profileRet == PROVISION_DEVICE_UNAUTHORIZED) { + return DEVICE_UNAUTHORIZED; + } + return APP_SOURCE_NOT_TRUSTED; + } + return VERIFY_SUCCESS; +} + +bool HapVerifyV2::ParseProfileFromP7b(const std::string& p7bFilePath, Pkcs7Context& pkcs7Context) +{ + int32_t fd = open(p7bFilePath.c_str(), O_RDONLY); + if (fd < 0) { + HAPVERIFY_LOG_ERROR("open p7b file failed, path: %{public}s", p7bFilePath.c_str()); + return false; + } + struct stat st; + if (fstat(fd, &st) < 0 || st.st_size <= 0) { + HAPVERIFY_LOG_ERROR("fstat p7b file failed, path: %{public}s", p7bFilePath.c_str()); + close(fd); + return false; + } + std::vector buffer(st.st_size); + ssize_t readSize = pread(fd, buffer.data(), st.st_size, 0); + if (readSize < 0 || static_cast(readSize) != buffer.size()) { + HAPVERIFY_LOG_ERROR("pread p7b file failed, path: %{public}s, error: %{public}d", p7bFilePath.c_str(), errno); + close(fd); + return false; + } + close(fd); + const unsigned char* p7bData = buffer.data(); + uint32_t p7bLen = static_cast(buffer.size()); + if (!HapVerifyOpensslUtils::ParsePkcs7Package(p7bData, p7bLen, pkcs7Context)) { + HAPVERIFY_LOG_ERROR("parse p7b failed, path: %{public}s", p7bFilePath.c_str()); + return false; + } + return true; +} } // namespace Verify } // namespace Security } // namespace OHOS diff --git a/interfaces/innerkits/appverify/test/unittest/src/hap_verify_test.cpp b/interfaces/innerkits/appverify/test/unittest/src/hap_verify_test.cpp index 170d69f..0eb69cc 100644 --- a/interfaces/innerkits/appverify/test/unittest/src/hap_verify_test.cpp +++ b/interfaces/innerkits/appverify/test/unittest/src/hap_verify_test.cpp @@ -326,4 +326,20 @@ HWTEST_F(HapVerifyTest, StringHash001, TestSize.Level1) EXPECT_EQ(uuid1, uuid2); EXPECT_NE(uuid1, uuid3); } + +/** + * @tc.name: HapVerifyTest.VerifyProfile001 + * @tc.desc: The static function will return verify result of p7b file; + * @tc.type: FUNC + */ +HWTEST_F(HapVerifyTest, VerifyProfile001, TestSize.Level1) +{ + ProvisionInfo provisionInfo; + int32_t ret = VerifyProfile("/data/test.p7b", provisionInfo); + EXPECT_NE(ret, VERIFY_SUCCESS); + ret = VerifyProfile("/data/update/ticket/verify_test.p7b", provisionInfo); + EXPECT_EQ(ret, VERIFY_SUCCESS); + ret = VerifyProfile("/data/update/ticket/verify_err.p7b", provisionInfo); + EXPECT_NE(ret, VERIFY_SUCCESS); +} } -- Gitee