diff --git a/hapsigntool_cpp/bundle.json b/hapsigntool_cpp/bundle.json index decf68af895587a4a21559bb48f55ac9368a1ac9..00fdd4978af1b155939f83da07d22d3666adca86 100644 --- a/hapsigntool_cpp/bundle.json +++ b/hapsigntool_cpp/bundle.json @@ -47,6 +47,7 @@ ], "inner_kits": [], "test": [ + "//developtools/hapsigner/hapsigntool_cpp/test/unittest:hapsigntool_pc_unittest" ] } } diff --git a/hapsigntool_cpp/test/.gitignore b/hapsigntool_cpp/test/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..259148fa18f9fb7ef58563f4ff15fc7b172339fb --- /dev/null +++ b/hapsigntool_cpp/test/.gitignore @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/hapsigntool_cpp/test/BUILD.gn b/hapsigntool_cpp/test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..50515f9f2aec04e0d621cf54c9f43f570e7dd377 --- /dev/null +++ b/hapsigntool_cpp/test/BUILD.gn @@ -0,0 +1,97 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("../cmd/signature_tools_cmd.gni") +import("../codesigning/signature_tools_codesigning.gni") +import("../common/signature_tools_common.gni") +import("../hap/signature_tools_hap.gni") +import("../profile/signature_tools_profile.gni") +import("../utils/signature_tools_utils.gni") +import("../zip/signature_tools_zip.gni") +import("../signature_tools.gni") + +import("//build/ohos.gni") + +config("service_include") { + visibility = [ "*" ] + + include_dirs = [ + "//third_party/openssl/include", + "//third_party/openssl/crypto/pkcs12", + "${signature_tools_api}/include", + "${signature_tools_signer}/include", + "${signature_tools_test}/packetUtils", + ] + + include_dirs += signature_tools_utils_include + include_dirs += signature_tools_zip_include + include_dirs += signature_tools_codesigning_include + include_dirs += signature_tools_common_include + include_dirs += signature_tools_hap_include + include_dirs += signature_tools_profile_include + include_dirs += signature_tools_cmd_include + + defines = [] + + cflags = [ "--coverage" ] + + cflags_cc = [ + "-std=c++17", + "--coverage", + ] + + ldflags = [ + "-fPIC", + "-Wl,-E", + "--coverage", + ] +} + +ohos_source_set("service_target") { + sources_obj = [ + "${signature_tools_api}/src/sign_tool_service_impl.cpp", + "${signature_tools_api}/src/localization_adapter.cpp", + "${signature_tools_api}/src/cert_tools.cpp", + "${signature_tools_signer}/src/signer_factory.cpp", + "${signature_tools_signer}/src/local_signer.cpp", + ] + + sources_obj += signature_tools_utils_src + sources_obj += signature_tools_zip_src + sources_obj += signature_tools_codesigning_src + sources_obj += signature_tools_common_src + sources_obj += signature_tools_hap_src + sources_obj += signature_tools_profile_src + sources_obj += signature_tools_cmd_src + + sources = sources_obj + + configs = [ ":service_include" ] + + remove_configs = [ "//build/config/compiler:no_exceptions" ] + + public_deps = [ + "//third_party/bzip2:libbz2", + "//third_party/openssl:libcrypto_shared", + "//third_party/openssl:libssl_shared", + "//third_party/zlib:shared_libz", + ] + + public_external_deps = [ + "c_utils:utils", + "json:nlohmann_json_static", + ] + + part_name = "hapsigner" + subsystem_name = "developtools" +} diff --git a/hapsigntool_cpp/test/unittest/.gitignore b/hapsigntool_cpp/test/unittest/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..259148fa18f9fb7ef58563f4ff15fc7b172339fb --- /dev/null +++ b/hapsigntool_cpp/test/unittest/.gitignore @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/hapsigntool_cpp/test/unittest/BUILD.gn b/hapsigntool_cpp/test/unittest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..c9ddb95d7412a5af541e2f77aeae9e725f5ba331 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/BUILD.gn @@ -0,0 +1,43 @@ +# Copyright (c) 2024-2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/test.gni") +import("../../signature_tools.gni") + +module_out_path = "developtools/hapsigner/hapsigner_pc" + +ohos_unittest("hapsigntool_pc_unittest") { + testonly = true + module_out_path = module_out_path + resource_config_file = "ohos_test.xml" + + configs = [ "${signature_tools_test}:service_include" ] + + sources = [ + "./hapVerify/hap_signer_block_utils_test.cpp", + "./hapVerify/hap_verify_result_test.cpp", + "./hapVerify/hap_verify_test.cpp", + "./hapVerify/provision_verify_test.cpp", + "./hapVerify/random_access_file_test.cpp", + ] + + remove_configs = [ "//build/config/compiler:no_exceptions" ] + + deps = [ "${signature_tools_test}:service_target" ] + + install_images = [ "system" ] + install_enable = true + part_name = "hapsigner" + subsystem_name = "developtools" +} diff --git a/hapsigntool_cpp/test/unittest/hapVerify/hap_cert_verify_openssl_utils_test.cpp b/hapsigntool_cpp/test/unittest/hapVerify/hap_cert_verify_openssl_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb95ea94bdb3a5d4dd593fcc793e3e35be1dc961 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/hap_cert_verify_openssl_utils_test.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hap_cert_verify_openssl_utils_test.h" + +#include +#include + +#include "openssl/asn1.h" +#include "openssl/x509.h" +#include "verify_hap.h" +#include "verify_cert_openssl_utils.h" + +using namespace testing::ext; +using namespace OHOS::SignatureTools; + +namespace OHOS { + namespace SignatureTools { + bool Base64StringDecode(const std::string& base64String, ByteBuffer& output) + { + std::unique_ptr decodeBuffer = std::make_unique(base64String.size()); + if (decodeBuffer == nullptr) { + return false; + } + + const unsigned char* input = reinterpret_cast(base64String.c_str()); + int32_t len = EVP_DecodeBlock(reinterpret_cast(decodeBuffer.get()), + input, base64String.size()); + if (len <= 0) { + return false; + } + + output.SetCapacity(len); + output.PutData(0, decodeBuffer.get(), len); + decodeBuffer.reset(nullptr); + return true; + } + } // namespace SignatureTools +} // namespace OHOS + +namespace { + class VerifyCertOpensslUtilsTest : public testing::Test { + public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp(); + + void TearDown(); + }; + + void VerifyCertOpensslUtilsTest::SetUpTestCase(void) + { + } + + void VerifyCertOpensslUtilsTest::TearDownTestCase(void) + { + } + void VerifyCertOpensslUtilsTest::SetUp() + { + } + + void VerifyCertOpensslUtilsTest::TearDown() + { + } + + /** + * @tc.name: Test CertVerify function + * @tc.desc: Check whether the CertVerify function can be used to verify a certificate. + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, CertVerify001, TestSize.Level1) + { + /* + * @tc.steps: step1. Input an ECC self signed cert with PEM encoded. + * @tc.expected: step1. The return is an X509 object. + */ + X509* certX509 = VerifyCertOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT); + ASSERT_TRUE(certX509 != nullptr); + /* + * @tc.steps: step2. Use all possible input to test CertVerify. + * @tc.expected: step2. The return is verify result. + */ + ASSERT_FALSE(VerifyCertOpensslUtils::CertVerify(nullptr, certX509)); + ASSERT_FALSE(VerifyCertOpensslUtils::CertVerify(certX509, nullptr)); + ASSERT_TRUE(VerifyCertOpensslUtils::CertVerify(certX509, certX509)); + X509_free(certX509); + } + + /** + * @tc.name: Test GetX509CertFromBase64String function + * @tc.desc: Verify whether the GetX509CertFromBase64String function can get an X509 cert from a Base64S string. + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, Base64NotUrlSafeCertTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. Input string of ECC cert with base64 decode + * @tc.expected: step1. The return is an X509 object. + */ + X509* certX509 = VerifyCertOpensslUtils::GetX509CertFromBase64String(BASE64_NOT_URL_SAFE_CERT); + ASSERT_TRUE(certX509 != nullptr); + std::string subject; + ASSERT_TRUE(VerifyCertOpensslUtils::GetSubjectFromX509(certX509, subject)); + X509_free(certX509); + certX509 = nullptr; + /* + * @tc.steps: step2. Use the subject as an error input. + * @tc.expected: step2. The return is nullptr. + */ + certX509 = VerifyCertOpensslUtils::GetX509CertFromBase64String(subject); + ASSERT_TRUE(certX509 == nullptr); + } + + /** + * @tc.name: Test GetX509CrlFromDerBuffer function + * @tc.desc: Verify whether the GetX509CrlFromDerBuffer function can get an X509 Crl from DerData. + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, GetX509CrlFromDerBufferTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. Input invalid data. + * @tc.expected: step1. The return is nullptr. + */ + ByteBuffer crlBuffer; + X509_CRL* crlX509 = VerifyCertOpensslUtils::GetX509CrlFromDerBuffer(crlBuffer, 0, 0); + ASSERT_TRUE(crlX509 == nullptr); + crlBuffer.SetCapacity(TEST_HAPBYTEBUFFER_LENGTH); + crlX509 = VerifyCertOpensslUtils::GetX509CrlFromDerBuffer(crlBuffer, 0, 0); + ASSERT_TRUE(crlX509 == nullptr); + /* + * @tc.steps: step2. Input a string of crl encoded by base64. + * @tc.expected: step2. Ihe return is a crl object. + */ + ASSERT_TRUE(Base64StringDecode(BASE64_CRL, crlBuffer)); + crlX509 = VerifyCertOpensslUtils::GetX509CrlFromDerBuffer(crlBuffer, 0, crlBuffer.GetCapacity()); + std::string crlIssuer; + ASSERT_FALSE(VerifyCertOpensslUtils::GetIssuerFromX509Crl(nullptr, crlIssuer)); + ASSERT_TRUE(VerifyCertOpensslUtils::GetIssuerFromX509Crl(crlX509, crlIssuer)); + ASSERT_TRUE(crlX509 != nullptr); + X509_CRL_free(crlX509); + } + + /** + * @tc.name: Test GetCertsChain function + * @tc.desc: Verify whether the GetCertsChain function can get a trusted cert chain from certs. + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, GetCertsChainTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. Use a certVisitSign included a self signed cert and an empty certsChain as input. + * @tc.expected: step1. The return is false due to invalid input. + */ + X509* certX509 = VerifyCertOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT); + ASSERT_TRUE(certX509 != nullptr); + CertChain certsChain; + CertSign certVisitSign; + certVisitSign[certX509] = false; + ASSERT_FALSE(VerifyCertOpensslUtils::GetCertsChain(certsChain, certVisitSign)); + } + + /** + * @tc.name: Test GetSubjectFromX509 and GetIssuerFromX509 functions. + * @tc.desc: The static function will return false due to invalid input; + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, GetIssuerAndSubjectTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. Use nullptr as input to test GetSubjectFromX509. + * @tc.expected: step1. The return is false. + */ + std::string subject; + ASSERT_FALSE(VerifyCertOpensslUtils::GetSubjectFromX509(nullptr, subject)); + /* + * @tc.steps: step2. Use nullptr as input to test GetIssuerFromX509. + * @tc.expected: step2. The return is false. + */ + std::string issuer; + ASSERT_FALSE(VerifyCertOpensslUtils::GetIssuerFromX509(nullptr, issuer)); + } + + /** + * @tc.name: Test GetSerialNumberFromX509 function. + * @tc.desc: Verify whether the GetSerialNumberFromX509 function can get the SerialNumber from an X509 certificate. + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, GetSerialNumberFromX509Test001, TestSize.Level1) + { + /* + * @tc.steps: step1. Use nullptr as input to test GetSerialNumberFromX509. + * @tc.expected: step1. The return is false. + */ + long long certSerialNumber; + ASSERT_FALSE(VerifyCertOpensslUtils::GetSerialNumberFromX509(nullptr, certSerialNumber)); + /* + * @tc.steps: step2. Use real cert to test GetX509CertFromPemString. + * @tc.expected: step2. the return is true. + */ + X509* certX509 = VerifyCertOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT); + ASSERT_TRUE(certX509 != nullptr); + ASSERT_TRUE(VerifyCertOpensslUtils::GetSerialNumberFromX509(certX509, certSerialNumber)); + X509_free(certX509); + } + + /** + * @tc.name: Test VerifyCertChainPeriodOfValidity function. + * @tc.desc: Verify whether the VerifyCertChainPeriodOfValidity function can verify validity + * period of a certificate chain. + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, VerifyCertChainPeriodOfValidityTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. Input an empty certChain. + * @tc.expected: step1. The return is false. + */ + CertChain certsChain; + ASSERT_FALSE(VerifyCertOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, nullptr)); + /* + * @tc.steps: step2. Input a nullptr signTime and a certChain with two cert. + * @tc.expected: step2. The return is false. + */ + X509* certX509 = VerifyCertOpensslUtils::GetX509CertFromBase64String(BASE64_NOT_URL_SAFE_CERT); + ASSERT_TRUE(certX509 != nullptr); + certsChain.push_back(certX509); + certsChain.push_back(certX509); + ASSERT_FALSE(VerifyCertOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, nullptr)); + /* + * @tc.steps: step3. Input a signTime which out of period of validity. + * @tc.expected: step3. The return is false. + */ + ASN1_OCTET_STRING* asnString = ASN1_OCTET_STRING_new(); + ASSERT_TRUE(asnString != nullptr); + ASSERT_TRUE(ASN1_OCTET_STRING_set(asnString, reinterpret_cast(TEST_ANS_TIME.c_str()), + static_cast(TEST_ANS_TIME.size()))); + ASN1_TYPE* time = ASN1_TYPE_new(); + ASSERT_TRUE(time != nullptr); + ASN1_TYPE_set(time, V_ASN1_UTCTIME, asnString); + ASSERT_FALSE(VerifyCertOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, time)); + /* + * @tc.steps: step4. Input a certChain with two nullptr. + * @tc.expected: step4. The return iis false. + */ + certsChain.clear(); + certsChain.push_back(nullptr); + certsChain.push_back(nullptr); + ASSERT_FALSE(VerifyCertOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, time)); + X509_free(certX509); + ASN1_TYPE_free(time); + } + + /** + * @tc.name: Test VerifyCrl function. + * @tc.desc: Verify whether the VerifyCrl function can verify a crl. + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, VerifyCrlTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. Input an empty certChain. + * @tc.expected: step1. The return is false. + */ + CertChain certsChain; + Pkcs7Context pkcs7Context; + ASSERT_FALSE(VerifyCertOpensslUtils::VerifyCrl(certsChain, nullptr, pkcs7Context)); + /* + * @tc.steps: step2. Input a certChain with two nullptr. + * @tc.expected: step2. the return is false. + */ + STACK_OF(X509_CRL)* crls = sk_X509_CRL_new_null(); + ASSERT_TRUE(crls != nullptr); + certsChain.push_back(nullptr); + certsChain.push_back(nullptr); + ASSERT_FALSE(VerifyCertOpensslUtils::VerifyCrl(certsChain, crls, pkcs7Context)); + /* + * @tc.steps: step3. Input valid certChain and null. + * @tc.expected: step3. The return is true due to crl is optional. + */ + certsChain.clear(); + X509* certX509 = VerifyCertOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT); + ASSERT_TRUE(certX509 != nullptr); + certsChain.push_back(certX509); + certsChain.push_back(certX509); + ASSERT_TRUE(VerifyCertOpensslUtils::VerifyCrl(certsChain, crls, pkcs7Context)); + /* + * @tc.steps: step4. Input error certChain and crls. + * @tc.expected: step4. The return is false. + */ + certsChain.clear(); + X509* root = VerifyCertOpensslUtils::GetX509CertFromPemString(ROOTCERT); + ASSERT_TRUE(root != nullptr); + certsChain.push_back(root); + certsChain.push_back(certX509); + ByteBuffer crlBuffer; + ASSERT_TRUE(Base64StringDecode(BASE64_CRL, crlBuffer)); + X509_CRL* crlX509 = VerifyCertOpensslUtils::GetX509CrlFromDerBuffer(crlBuffer, 0, crlBuffer.GetCapacity()); + ASSERT_TRUE(crlX509 != nullptr); + sk_X509_CRL_push(crls, crlX509); + ASSERT_FALSE(VerifyCertOpensslUtils::VerifyCrl(certsChain, crls, pkcs7Context)); + /* + * @tc.steps: step5. Input right certChain and crls. + * @tc.expected: step5. The return is true. + */ + certsChain.clear(); + certsChain.push_back(root); + certsChain.push_back(root); + ASSERT_TRUE(VerifyCertOpensslUtils::VerifyCrl(certsChain, crls, pkcs7Context)); + X509_free(certX509); + X509_free(root); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + } + + /** + * @tc.name: Test CompareX509Cert function + * @tc.desc: Verify whether the CompareX509Cert function can compare two certificates. + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, CompareX509CertTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. Use nullptr as input to test CompareX509Cert. + * @tc.expected: step1. The return is false. + */ + ASSERT_FALSE(VerifyCertOpensslUtils::CompareX509Cert(nullptr, ECC_TEST_KEY)); + /* + * @tc.steps: step2. The second cert is not a cert string. + * @tc.expected: step2. the return is false. + */ + X509* certX509 = VerifyCertOpensslUtils::GetX509CertFromPemString(ECC_TEST_CERT); + ASSERT_TRUE(certX509 != nullptr); + ASSERT_FALSE(VerifyCertOpensslUtils::CompareX509Cert(certX509, ECC_TEST_KEY)); + /* + * @tc.steps: step3. Input two same cert. + * @tc.expected: step3. The return is true. + */ + ASSERT_TRUE(VerifyCertOpensslUtils::CompareX509Cert(certX509, ECC_TEST_CERT)); + X509_free(certX509); + } + + /** + * @tc.name: Test WriteX509CrlToStream function. + * @tc.desc: Verify whether the WriteX509CrlToStream function can write crl to a file. + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, WriteX509CrlToStreamTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. Use invalid input. + * @tc.expected: step1. The file length is zero. + */ + std::ofstream crlFile; + VerifyCertOpensslUtils::WriteX509CrlToStream(crlFile, nullptr); + std::string filePath = "./hapVerify/test_crl"; + crlFile.open(filePath, std::ofstream::out | std::ofstream::trunc | std::ofstream::binary); + VerifyCertOpensslUtils::WriteX509CrlToStream(crlFile, nullptr); + ASSERT_TRUE(crlFile.tellp() == 0); + if (crlFile.is_open()) { + crlFile.close(); + } + } + + /** + * @tc.name: Test private function + * @tc.desc: The static function will return result of invalid input; + * @tc.type: FUNC + */ + HWTEST_F(VerifyCertOpensslUtilsTest, PrivateFuncInvalidInputTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. Use invalid input. + * @tc.expected: step1. The return is false. + */ + CertSign certVisitSign; + VerifyCertOpensslUtils::GenerateCertSignFromCertStack(nullptr, certVisitSign); + ASSERT_TRUE(VerifyCertOpensslUtils::FindCertOfIssuer(nullptr, certVisitSign) == nullptr); + std::string str = VerifyCertOpensslUtils::GetDnToString(nullptr); + ASSERT_FALSE(str.size() > 0); + ASSERT_TRUE(VerifyCertOpensslUtils::GetCrlBySignedCertIssuer(nullptr, nullptr) == nullptr); + ASSERT_FALSE(VerifyCertOpensslUtils::X509NameCompare(nullptr, nullptr)); + ASSERT_FALSE(VerifyCertOpensslUtils::CheckSignTimeInValidPeriod(nullptr, nullptr, nullptr)); + ASSERT_FALSE(VerifyCertOpensslUtils::CheckAsn1TimeIsValid(nullptr)); + ASSERT_FALSE(VerifyCertOpensslUtils::CheckAsn1TypeIsValid(nullptr)); + } +} diff --git a/hapsigntool_cpp/test/unittest/hapVerify/hap_cert_verify_openssl_utils_test.h b/hapsigntool_cpp/test/unittest/hapVerify/hap_cert_verify_openssl_utils_test.h new file mode 100644 index 0000000000000000000000000000000000000000..b7ae2ebfe3a4d68dfecbf02358713398ee9be95f --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/hap_cert_verify_openssl_utils_test.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAP_CERT_VERIFY_OPENSSL_UTILS_TEST_H +#define HAP_CERT_VERIFY_OPENSSL_UTILS_TEST_H + +#include +#include + +#include "byte_buffer.h" + +#include "test_const.h" + +namespace OHOS { + namespace SignatureTools { + bool Base64StringDecode(const std::string& base64String, SignatureTools::ByteBuffer& output); + } +} + +int32_t GetCertInfo001(void); +int32_t CertVerify001(void); +int32_t Base64NotUrlSafeCertTest001(void); +int32_t GetX509CrlFromDerBufferTest001(void); +int32_t GetIssuerAndSubjectTest001(void); +int32_t GetSerialNumberFromX509Test001(void); +int32_t VerifyCertChainPeriodOfValidityTest001(void); +int32_t VerifyCrlTest001(void); +int32_t CompareX509CertTest001(void); +int32_t WriteX509CrlToStreamTest001(void); +int32_t PrivateFuncInvalidInputTest001(void); +#endif // HAP_CERT_VERIFY_OPENSSL_UTILS_TEST_H diff --git a/hapsigntool_cpp/test/unittest/hapVerify/hap_signer_block_utils_test.cpp b/hapsigntool_cpp/test/unittest/hapVerify/hap_signer_block_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d1904620ff0988041dc604bfe376cac176d9413 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/hap_signer_block_utils_test.cpp @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include + +#include "byte_buffer_data_source.h" +#include "random_access_file.h" +#include "hap_signer_block_utils.h" +#include "hap_signer_block_utils_test.h" + +using namespace testing::ext; +using namespace OHOS::SignatureTools; +namespace OHOS { +namespace SignatureTools { +void CreateHapSubSignBlockHead(HapSubSignBlockHead& signBlob, HapSubSignBlockHead& profileBlob, + HapSubSignBlockHead& propertyBlob) +{ + signBlob.type = HAP_SIGN_BLOB; + signBlob.length = TEST_FILE_BLOCK_LENGTH; + signBlob.offset = sizeof(HapSubSignBlockHead) * TEST_FILE_BLOCK_COUNT; + profileBlob.type = PROFILE_BLOB; + profileBlob.length = TEST_FILE_BLOCK_LENGTH; + profileBlob.offset = signBlob.offset + signBlob.length; + propertyBlob.type = PROPERTY_BLOB; + propertyBlob.length = TEST_FILE_BLOCK_LENGTH; + propertyBlob.offset = profileBlob.offset + profileBlob.length; +} + +long long CreatTestZipFile(const std::string& pathFile, SignatureInfo& signInfo) +{ + 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 }; + /* input contents of ZIP entries */ + hapFile.seekp(0, std::ios_base::beg); + hapFile.write(block, sizeof(block)); + /* input sign block */ + HapSubSignBlockHead signBlob; + HapSubSignBlockHead profileBlob; + HapSubSignBlockHead propertyBlob; + CreateHapSubSignBlockHead(signBlob, profileBlob, propertyBlob); + hapFile.write(reinterpret_cast(&signBlob), sizeof(signBlob)); + hapFile.write(reinterpret_cast(&profileBlob), sizeof(profileBlob)); + hapFile.write(reinterpret_cast(&propertyBlob), sizeof(propertyBlob)); + for (int32_t i = 0; i < TEST_FILE_BLOCK_COUNT; i++) { + hapFile.write(block, sizeof(block)); + } + int32_t blockCount = TEST_FILE_BLOCK_COUNT; + hapFile.write(reinterpret_cast(&blockCount), sizeof(blockCount)); + long long signBlockSize = (sizeof(HapSubSignBlockHead) + sizeof(block)) * + TEST_FILE_BLOCK_COUNT + + HapSignerBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH; + hapFile.write(reinterpret_cast(&signBlockSize), sizeof(signBlockSize)); + long long magic = HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW_OLD; + hapFile.write(reinterpret_cast(&magic), sizeof(magic)); + magic = HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH_OLD; + hapFile.write(reinterpret_cast(&magic), sizeof(magic)); + int32_t version = 1; + hapFile.write(reinterpret_cast(&version), sizeof(version)); + /* input central direction */ + hapFile.write(block, sizeof(block)); + /* input end of central direction */ + int32_t zidEocdSign = HapSignerBlockUtils::ZIP_EOCD_SEGMENT_FLAG; + hapFile.write(reinterpret_cast(&zidEocdSign), sizeof(zidEocdSign)); + 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; + 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.PutData(0, block, sizeof(block)); + long long sumLen = signInfo.hapEocdOffset + sizeof(zidEocdSign) + sizeof(centralDirLen) + + sizeof(centralDirOffset) + sizeof(magic) + sizeof(eocdCommentLen); + return sumLen; +} +} // namespace SignatureTools +} // namespace OHOS + +namespace { +const std::string HAP_VERIFY_V2_PATH = "./hapVerify/hap_verify_v2.hap"; +const std::string HAP_VERIFY_V3_PATH = "./hapVerify/hap_verify_v3.hap"; +class HapSignerBlockUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp(); + + void TearDown(); + + static const int32_t TEST_ZIP_BLOCKS_NUM_NEED_DIGEST; +}; + +const int32_t HapSignerBlockUtilsTest::TEST_ZIP_BLOCKS_NUM_NEED_DIGEST = 3; + +void HapSignerBlockUtilsTest::SetUpTestCase(void) +{ +} + +void HapSignerBlockUtilsTest::TearDownTestCase(void) +{ + +} + +void HapSignerBlockUtilsTest::SetUp() +{ +} + +void HapSignerBlockUtilsTest::TearDown() +{ +} + +/** + * @tc.name: Test FindHapSignature function + * @tc.desc: input one right file and some error files, The static function will return correct result; + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, FindHapSignatureTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. create a test zip file. + */ + std::string pathFile = "./hapVerify/test_hap_verify.hap"; + SignatureInfo signInfo; + int32_t sumLen = CreatTestZipFile(pathFile, signInfo); + /* + * @tc.steps: step2. test FindHapSignature function + * @tc.expected: step2. the return will be true. + */ + RandomAccessFile hapTestFile; + ASSERT_TRUE(hapTestFile.Init(pathFile)); + ASSERT_EQ(hapTestFile.GetLength(), sumLen); + SignatureInfo hapSignInfo; + ASSERT_TRUE(HapSignerBlockUtils::FindHapSignature(hapTestFile, hapSignInfo)); + /* + * @tc.steps: step3. make central offset error, and test FindHapSignature function + * @tc.expected: step3. can not find central directory, the return will be false. + */ + ByteBuffer eocd(TEST_ZIP_EOCD_SIZE); + EXPECT_GT(hapTestFile.ReadFileFullyFromOffset(eocd, sumLen - TEST_ZIP_EOCD_SIZE), 0); + ByteBuffer buff(eocd); + buff.PutInt32(TEST_ZIP_ECD_OFFSET_FIELD_OFFSET, TEST_HAPBYTEBUFFER_INT32_DATA); + EXPECT_GT(hapTestFile.WriteToFile(buff, sumLen - TEST_ZIP_EOCD_SIZE, buff.GetCapacity()), 0); + ASSERT_FALSE(HapSignerBlockUtils::FindHapSignature(hapTestFile, hapSignInfo)); + /* + * @tc.steps: step4. make eocd comment error, and test FindHapSignature function + * @tc.expected: step4. can not find eocd, the return will be false. + */ + ByteBuffer buff2(eocd); + buff2.PutInt16(TEST_ZIP_EOCD_COMMENT_OFFSET, TEST_HAPBYTEBUFFER_UINT16_DATA); + EXPECT_GT(hapTestFile.WriteToFile(buff2, sumLen - TEST_ZIP_EOCD_SIZE, buff2.GetCapacity()), 0); + ASSERT_FALSE(HapSignerBlockUtils::FindHapSignature(hapTestFile, hapSignInfo)); + /* + * @tc.steps: step5. make hap signing block error, and test FindHapSignature function + * @tc.expected: step4. can not find hap signing block, the return will be false. + */ + RandomAccessFile hapTestFile2; + ASSERT_TRUE(hapTestFile2.Init(HAP_VERIFY_V2_PATH)); + ASSERT_FALSE(HapSignerBlockUtils::FindHapSignature(hapTestFile2, hapSignInfo)); +} + +/** + * @tc.name: Test FindEocdInHap function + * @tc.desc: create a file with invalid length, The function will return false; + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, FindEocdInHapTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. create a test file with invalid length. + */ + std::string pathFile = "./hapVerify/test_hap_verify.hap"; + std::ofstream hapFile; + hapFile.open(pathFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(hapFile.is_open()); + uint32_t centralDirLen = TEST_HAPBYTEBUFFER_UINT32_DATA; + hapFile.write(reinterpret_cast(¢ralDirLen), sizeof(centralDirLen)); + hapFile.close(); + /* + * @tc.steps: step2. test FindEocdInHap function + * @tc.expected: step2. the return will be false. + */ + RandomAccessFile hapTestFile; + hapTestFile.Init(pathFile); + std::pair eocd; + ASSERT_FALSE(HapSignerBlockUtils::FindEocdInHap(hapTestFile, eocd)); + /* + * @tc.steps: step3. test FindEocdInHap function + * @tc.expected: step3. make the file length is right, but the comment size is wrong, the return will be false. + */ + ByteBuffer fileLen(TEST_FILE_BLOCK_LENGTH); + EXPECT_GT(hapTestFile.WriteToFile(fileLen, 0, fileLen.GetCapacity()), 0); + int32_t maxCommentSize = TEST_INVALID_MAX_COMMENT_SIZE; + ASSERT_FALSE(HapSignerBlockUtils::FindEocdInHap(hapTestFile, maxCommentSize, eocd)); + maxCommentSize = TEST_MAX_COMMENT_SIZE; + ASSERT_FALSE(HapSignerBlockUtils::FindEocdInHap(hapTestFile, maxCommentSize, eocd)); + /* + * @tc.steps: step4. test FindEocdInSearchBuffer function + * @tc.expected: step4. make the searchBuffer is wrong, the return will be false. + */ + ByteBuffer testHapBuffer(TEST_HAPBYTEBUFFER_LENGTH); + int32_t offset = 0; + ASSERT_FALSE(HapSignerBlockUtils::FindEocdInSearchBuffer(testHapBuffer, offset)); + ByteBuffer eocdBuff(TEST_ZIP_EOCD_SIZE); + eocdBuff.PutInt32(HapSignerBlockUtils::ZIP_EOCD_SEGMENT_FLAG); + eocdBuff.Flip(); + ASSERT_FALSE(HapSignerBlockUtils::FindEocdInSearchBuffer(eocdBuff, offset)); +} + +/** + * @tc.name: Test GetCentralDirectoryOffset function + * @tc.desc: create an ecod with invalid central offset and length, + * The function will return TEST_NOT_FIND_TARGET_OFFSET; + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, GetCentralDirectoryOffsetTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. create a test eocd with invalid central offset and length. + */ + ByteBuffer testEocd(TEST_ZIP_EOCD_SIZE); + int32_t centralDirLen = TEST_FILE_BLOCK_LENGTH; + testEocd.PutInt32(TEST_ZIP_ECD_SIZE_FIELD_OFFSET, centralDirLen); + int32_t centralDirOffset = TEST_FILE_BLOCK_LENGTH; + testEocd.PutInt32(TEST_ZIP_ECD_OFFSET_FIELD_OFFSET, centralDirOffset); + ASSERT_FALSE(HapSignerBlockUtils::SetUnsignedInt32(testEocd, 0, TEST_INVALID_MAX_COMMENT_SIZE)); + ByteBuffer emptyEocd; + /* + * @tc.steps: step2. run function with error eocdoffset + * @tc.expected: step2. the return will be NOT_FIND_TARGET_OFFSET. + */ + long long offset; + ASSERT_FALSE(HapSignerBlockUtils::GetCentralDirectoryOffset(emptyEocd, 0, offset)); + ASSERT_FALSE(HapSignerBlockUtils::GetCentralDirectoryOffset(testEocd, 0, offset)); + ASSERT_FALSE(HapSignerBlockUtils::GetCentralDirectoryOffset(testEocd, TEST_FILE_BLOCK_LENGTH, offset)); +} + +/** + * @tc.name: Test GetCentralDirectorySize function + * @tc.desc: create an wrong eocd, the function will return false; + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, GetCentralDirectorySizeTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. create a test eocd with invalid length; + * @tc.expected: step1. the return will be false. + */ + ByteBuffer testEocd(TEST_HAPBYTEBUFFER_LENGTH); + long centralDirectorySize; + ASSERT_FALSE(HapSignerBlockUtils::GetCentralDirectorySize(testEocd, centralDirectorySize)); +} + +/** + * @tc.name: Test FindHapSigningBlock function + * @tc.desc: input one right file and some error files, The static function will return correct result; + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, FindHapSigningBlockTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. create a test zip file. + */ + std::string pathFile = "./hapVerify/test_hap_verify.hap"; + SignatureInfo signInfo; + int32_t sumLen = CreatTestZipFile(pathFile, signInfo); + /* + * @tc.steps: step2. test FindHapSigningBlock function + * @tc.expected: step2. the return will be true. + */ + RandomAccessFile hapTestFile; + ASSERT_TRUE(hapTestFile.Init(pathFile)); + ASSERT_EQ(hapTestFile.GetLength(), sumLen); + SignatureInfo hapSignInfo; + ASSERT_TRUE(HapSignerBlockUtils::FindHapSigningBlock(hapTestFile, signInfo.hapCentralDirOffset, hapSignInfo)); + /* + * @tc.steps: step3. test FindHapSigningBlock function + * @tc.expected: step3. can not find cd offset, the return will be false. + */ + ASSERT_FALSE(HapSignerBlockUtils::FindHapSigningBlock(hapTestFile, 0, hapSignInfo)); + /* + * @tc.steps: step4. test FindHapSigningBlock function + * @tc.expected: step4. cd offset is out of range, the return will be false. + */ + ASSERT_FALSE(HapSignerBlockUtils::FindHapSigningBlock(hapTestFile, TEST_HAPBYTEBUFFER_INT32_DATA, hapSignInfo)); + /* + * @tc.steps: step5. test CheckSignBlockHead function + * @tc.expected: step5. make hapSignBlockMagic is wrong, the return will be false. + */ + RandomAccessFile hapTestFile2; + ASSERT_TRUE(hapTestFile2.Init(HAP_VERIFY_V2_PATH)); + int64_t fileLength = hapTestFile2.GetLength(); + ByteBuffer eocd(TEST_ZIP_EOCD_SIZE); + int32_t centralDirOffset; + EXPECT_GT(hapTestFile2.ReadFileFullyFromOffset(eocd, fileLength - TEST_ZIP_EOCD_SIZE), 0); + ASSERT_TRUE(eocd.GetInt32(TEST_ZIP_ECD_OFFSET_FIELD_OFFSET, centralDirOffset)); + ASSERT_FALSE(HapSignerBlockUtils::FindHapSigningBlock(hapTestFile2, centralDirOffset, hapSignInfo)); + /* + * @tc.steps: step6. test CheckSignBlockHead function + * @tc.expected: step6. make hapSignBlockOffset is wrong, the return will be false. + */ + RandomAccessFile hapTestFile3; + ASSERT_TRUE(hapTestFile3.Init(HAP_VERIFY_V3_PATH)); + fileLength = hapTestFile3.GetLength(); + ByteBuffer eocd2(TEST_ZIP_EOCD_SIZE); + EXPECT_GT(hapTestFile3.ReadFileFullyFromOffset(eocd2, fileLength - TEST_ZIP_EOCD_SIZE), 0); + ASSERT_TRUE(eocd2.GetInt32(TEST_ZIP_ECD_OFFSET_FIELD_OFFSET, centralDirOffset)); + ASSERT_FALSE(HapSignerBlockUtils::FindHapSigningBlock(hapTestFile3, centralDirOffset, hapSignInfo)); +} + +/** + * @tc.name: Test CheckSignBlockHead function + * @tc.desc: input one right file and some error files, The static function will return correct result; + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, CheckSignBlockHeadTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. test CheckSignBlockHead function + * @tc.expected: step1. check the hapSignBlockMagicHi is wrong, the return will be false. + */ + HapSignBlockHead hapSignBlockHead{ + .version = 3, + .blockCount = 0, + .hapSignBlockSize = 0, + .hapSignBlockMagicLo = HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_LOW, + .hapSignBlockMagicHi = 0, + }; + ASSERT_FALSE(HapSignerBlockUtils::CheckSignBlockHead(hapSignBlockHead)); + /* + * @tc.steps: step2. test CheckSignBlockHead function + * @tc.expected: step2. check the hapSignBlockSize is less than ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH, + * the return will be false. + */ + hapSignBlockHead.hapSignBlockMagicHi = HapSignerBlockUtils::HAP_SIG_BLOCK_MAGIC_HIGH; + ASSERT_FALSE(HapSignerBlockUtils::CheckSignBlockHead(hapSignBlockHead)); + /* + * @tc.steps: step3. test CheckSignBlockHead function + * @tc.expected: step3. check the hapSignBlockSize is greater than MAX_HAP_SIGN_BLOCK_SIZE, + * the return will be false. + */ + hapSignBlockHead.hapSignBlockSize = INT_MAX; + ASSERT_FALSE(HapSignerBlockUtils::CheckSignBlockHead(hapSignBlockHead)); + /* + * @tc.steps: step4. test CheckSignBlockHead function + * @tc.expected: step4. check the blockCount is greater than MAX_BLOCK_COUNT, the return will be false. + */ + hapSignBlockHead.hapSignBlockSize = HapSignerBlockUtils::ZIP_HEAD_OF_SIGNING_BLOCK_LENGTH; + hapSignBlockHead.blockCount = INT_MAX; + ASSERT_FALSE(HapSignerBlockUtils::CheckSignBlockHead(hapSignBlockHead)); +} + +/** + * @tc.name: Test FindHapSubSigningBlock function + * @tc.desc: input one right file and some error files, The static function will return correct result; + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, FindHapSubSigningBlockTest001, TestSize.Level1) +{ + RandomAccessFile hapTestFile; + ASSERT_TRUE(hapTestFile.Init(HAP_VERIFY_V2_PATH)); + ByteBuffer hapSignatureBlock(1); + ByteBuffer hapEocd(1); + ByteBuffer optionalBlockValue(1); + std::vector optionalBlocks{ + { + .optionalType = 0, + .optionalBlockValue = optionalBlockValue + } + }; + SignatureInfo signatureInfo{ + .hapSignatureBlock = hapSignatureBlock, + .hapSigningBlockOffset = 0, + .hapCentralDirOffset = 0, + .hapEocdOffset = 0, + .hapEocd = hapEocd, + .optionBlocks = optionalBlocks, + .version = 0 + }; + + ASSERT_FALSE(HapSignerBlockUtils::FindHapSubSigningBlock(hapTestFile, 0, INT_MAX, 0, signatureInfo)); + + ASSERT_FALSE(HapSignerBlockUtils::FindHapSubSigningBlock(hapTestFile, 1, 0, INT_MAX, signatureInfo)); + + ASSERT_FALSE(HapSignerBlockUtils::FindHapSubSigningBlock(hapTestFile, 1, 0, 0, signatureInfo)); + + ASSERT_FALSE(HapSignerBlockUtils::FindHapSubSigningBlock(hapTestFile, 1, 128, 128, signatureInfo)); +} + +/** + * @tc.name: Test ClassifyHapSubSigningBlock function + * @tc.desc: test function of classify optional block + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, ClassifyHapSubSigningBlock001, TestSize.Level1) +{ + /* + * @tc.steps: step1. run function with input of property block + * @tc.expected: step1. the return signInfo.optionBlocks has property block which inputed. + */ + SignatureInfo signInfo; + ByteBuffer subBlock; + uint32_t type = PROPERTY_BLOB; + HapSignerBlockUtils::ClassifyHapSubSigningBlock(signInfo, subBlock, type); + ASSERT_FALSE(signInfo.optionBlocks.empty()); + ASSERT_TRUE(signInfo.optionBlocks[0].optionalType == PROPERTY_BLOB); +} + +/** + * @tc.name: Test ComputeDigestsWithOptionalBlock function + * @tc.desc: use an error nid and a right nid to compute digest + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, ComputeDigestsWithOptionalBlock001, TestSize.Level1) +{ + /* + * @tc.steps: step1. run function with an error nid and a right nid + * @tc.expected: step1. the return will be false and right respectively. + */ + OptionalBlock testOptionalBlock; + testOptionalBlock.optionalType = PROPERTY_BLOB; + testOptionalBlock.optionalBlockValue.SetCapacity(TEST_HAPBYTEBUFFER_LENGTH); + std::vector optionalBlocks; + optionalBlocks.push_back(testOptionalBlock); + ByteBuffer chunkDigest(TEST_HAPBYTEBUFFER_LENGTH); + ByteBuffer finalDigest; + int32_t nid = TEST_NULL_NID; + DigestParameter errorParam = HapSignerBlockUtils::GetDigestParameter(nid); + int32_t ret = HapSignerBlockUtils::ComputeDigestsWithOptionalBlock( + errorParam, optionalBlocks, chunkDigest, finalDigest); + ASSERT_FALSE(ret); + nid = TEST_SHA256_NID; + DigestParameter digestParam = HapSignerBlockUtils::GetDigestParameter(nid); + ret = HapSignerBlockUtils::ComputeDigestsWithOptionalBlock(digestParam, optionalBlocks, chunkDigest, finalDigest); + ASSERT_TRUE(ret); +} + +/** + * @tc.name: Test GetSumOfChunkDigestLen function + * @tc.desc: Test GetSumOfChunkDigestLen with some error inputs + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, GetSumOfChunkDigestLenTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. input some error input to test GetSumOfChunkDigestLen + * @tc.expected: step1. the return will be false. + */ + int32_t chunkCount = 0; + int32_t sumOfChunkDigestLen = 0; + DataSource* contents[TEST_ZIP_BLOCKS_NUM_NEED_DIGEST] = { nullptr, nullptr, nullptr }; + bool ret = HapSignerBlockUtils::GetSumOfChunkDigestLen(contents, 0, 0, chunkCount, sumOfChunkDigestLen); + ASSERT_FALSE(ret); + ret = HapSignerBlockUtils::GetSumOfChunkDigestLen(contents, + TEST_ZIP_BLOCKS_NUM_NEED_DIGEST, 0, + chunkCount, sumOfChunkDigestLen); + ASSERT_FALSE(ret); + ByteBuffer testBuffer(TEST_ZIP_EOCD_SIZE); + ByteBufferDataSource testSource(testBuffer); + for (int32_t i = 0; i < TEST_ZIP_BLOCKS_NUM_NEED_DIGEST; i++) { + contents[i] = &testSource; + } + ret = HapSignerBlockUtils::GetSumOfChunkDigestLen(contents, + TEST_ZIP_BLOCKS_NUM_NEED_DIGEST, + INT_MAX, chunkCount, + sumOfChunkDigestLen); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: Test VerifyHapIntegrity function + * @tc.desc: create a file and input error digest, The static function will return false; + * @tc.type: FUNC + */ +HWTEST_F(HapSignerBlockUtilsTest, VerifyHapIntegrityTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. create a test zip file without eocd. + */ + std::string pathFile = "./hapVerify/test_hap_verify.hap"; + SignatureInfo signInfo; + CreatTestZipFile(pathFile, signInfo); + /* + * @tc.steps: step2. create an error digest to test VerifyHapIntegrity function + * @tc.expected: step2. the return will be false. + */ + Pkcs7Context digestInfo; + digestInfo.content.SetCapacity(TEST_FILE_BLOCK_LENGTH); + RandomAccessFile hapTestFile; + hapTestFile.Init(pathFile); + ASSERT_FALSE(HapSignerBlockUtils::VerifyHapIntegrity(digestInfo, hapTestFile, signInfo)); +} +} // namespace \ No newline at end of file diff --git a/hapsigntool_cpp/test/unittest/hapVerify/hap_signer_block_utils_test.h b/hapsigntool_cpp/test/unittest/hapVerify/hap_signer_block_utils_test.h new file mode 100644 index 0000000000000000000000000000000000000000..be434ad442f23335fde6ea4b7480096ad55cb647 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/hap_signer_block_utils_test.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAP_SIGNING_BLOCK_UTILS_TEST_H +#define HAP_SIGNING_BLOCK_UTILS_TEST_H + +#include +#include + +#include "signature_info.h" + +#include "test_const.h" + +int32_t FindHapSignatureTest001(void); +int32_t VerifyHapIntegrityTest001(void); +int32_t FindEocdInHapTest001(void); +int32_t GetCentralDirectoryOffsetTest001(void); +int32_t ClassifyHapSubSigningBlock001(void); +int32_t ComputeDigestsWithOptionalBlock001(void); +int32_t GetSumOfChunkDigestLenTest001(void); +#endif // HAP_SIGNING_BLOCK_UTILS_TEST_H diff --git a/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_result_test.cpp b/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_result_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..874658f9bfa397332490bdaf061b21c635635d98 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_result_test.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hap_verify_result_test.h" + +#include +#include + +#include + +#include "hap_verify_result.h" +#include "hap_signer_block_utils.h" + +using namespace testing::ext; +using namespace OHOS::SignatureTools; +namespace { + class HapVerifyResultTest : public testing::Test { + public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp(); + + void TearDown(); + }; + + void HapVerifyResultTest::SetUpTestCase(void) + { + } + + void HapVerifyResultTest::TearDownTestCase(void) + { + } + + void HapVerifyResultTest::SetUp() + { + } + + void HapVerifyResultTest::TearDown() + { + } + + /** + * @tc.name: Test GetPublicKey and GetSignature function + * @tc.desc: The static function return publickey and signature will be null; + * @tc.type: FUNC + */ + HWTEST_F(HapVerifyResultTest, GetPublicKeyAndSignature001, TestSize.Level1) + { + /* + * @tc.steps: step1. set a null buffer to HapVerifyResult as data package of pkcs7, + * and do GetPublicKey and GetSignature. + * @tc.expected: step1. the return vector of string is null. + */ + ByteBuffer testBuffer; + HapVerifyResult hapVerifyResult; + hapVerifyResult.SetPkcs7SignBlock(testBuffer); + std::vector publicKeys = hapVerifyResult.GetPublicKey(); + ASSERT_TRUE(publicKeys.empty()); + std::vector signatures = hapVerifyResult.GetSignature(); + ASSERT_TRUE(signatures.empty()); + } + + /** + * @tc.name: Test SetOptionalBlocks and GetProfile GetProperty function + * @tc.desc: The static function will return no profile and have a property; + * @tc.type: FUNC + */ + HWTEST_F(HapVerifyResultTest, GetProfileAndProperty001, TestSize.Level1) + { + /* + * @tc.steps: step1. set an option with property to HapVerifyResult + */ + std::vector option; + HapVerifyResult hapVerifyResult; + OptionalBlock testblock; + testblock.optionalType = PROPERTY_BLOB; + testblock.optionalBlockValue.SetCapacity(TEST_HAPBYTEBUFFER_LENGTH); + option.push_back(testblock); + hapVerifyResult.SetOptionalBlocks(option); + /* + * @tc.steps: step2. GetProfile and detect it right. + * @tc.expected: step2. the return code will be NO_THIS_BLOCK_IN_PACKAGE. + */ + std::string getProfile; + GetOptionalBlockResultCode targetResult = NO_THIS_BLOCK_IN_PACKAGE; + int32_t ret = hapVerifyResult.GetBlockFromOptionalBlocks(PROFILE_BLOB, getProfile); + ASSERT_TRUE(ret == targetResult); + /* + * @tc.steps: step3. GetProperty. + * @tc.expected: step3. the return code will be GET_SUCCESS. + */ + std::string getProperty; + ASSERT_TRUE(hapVerifyResult.GetProperty(getProperty) == GET_SUCCESS); + } + + /** + * @tc.name: Test SetVersion and GetVersion function + * @tc.desc: The static function return Version which is set; + * @tc.type: FUNC + */ + HWTEST_F(HapVerifyResultTest, SetVersionAndGetVersion001, TestSize.Level1) + { + /* + * @tc.steps: step1. set a target version to HapVerifyResult. + * @tc.expected: step1. the return version is the value we set. + */ + int32_t targetVersion = TEST_HAP_SIGN_VERSION; + HapVerifyResult hapVerifyResult; + hapVerifyResult.SetVersion(targetVersion); + int32_t version = hapVerifyResult.GetVersion(); + ASSERT_TRUE(version == targetVersion); + } +} diff --git a/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_result_test.h b/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_result_test.h new file mode 100644 index 0000000000000000000000000000000000000000..f103d926e6b0cb65e027eb45f07e17bcfabe59a1 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_result_test.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAP_VERIFY_RESULT_TEST_H +#define HAP_VERIFY_RESULT_TEST_H + +#include + +#include "test_const.h" + +int32_t GetPublicKeyAndSignature001(void); +int32_t GetProfileAndProperty001(void); +int32_t SetVersionAndGetVersion001(void); +#endif // HAP_VERIFY_RESULT_TEST_H diff --git a/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_test.cpp b/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b0efa7bfd71e4e7887343d52c9c6c9cc2ea1be3 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_test.cpp @@ -0,0 +1,1222 @@ + +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hap_verify_test.h" +#include +#include +#include +#include "profile_info.h" +#include "verify_hap.h" +#include "test_hap_file_data.h" +#include "hap_cert_verify_openssl_utils_test.h" +#include "test_const.h" +#include "test_hap_file_data.h" +#include "file_utils.h" +#include "random_access_file.h" +#include "signature_tools_log.h" +#include "verify_hap.h" +#include "hap_signer_block_utils.h" +#include "hap_verify_result.h" +#include "openssl/pem.h" +#include "options.h" + +using namespace testing::ext; + + +namespace OHOS { +namespace SignatureTools { +const std::string ERROR_CERTIFICATE = "errorCertificate"; +const std::string TEST_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n\ +MIICMzCCAbegAwIBAgIEaOC/zDAMBggqhkjOPQQDAwUAMGMxCzAJBgNVBAYTAkNO\n\ +MRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\n\ +bTEjMCEGA1UEAxMaT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gQ0EwHhcNMjEwMjAy\n\ +MTIxOTMxWhcNNDkxMjMxMTIxOTMxWjBoMQswCQYDVQQGEwJDTjEUMBIGA1UEChML\n\ +T3Blbkhhcm1vbnkxGTAXBgNVBAsTEE9wZW5IYXJtb255IFRlYW0xKDAmBgNVBAMT\n\ +H09wZW5IYXJtb255IEFwcGxpY2F0aW9uIFJlbGVhc2UwWTATBgcqhkjOPQIBBggq\n\ +hkjOPQMBBwNCAATbYOCQQpW5fdkYHN45v0X3AHax12jPBdEDosFRIZ1eXmxOYzSG\n\ +JwMfsHhUU90E8lI0TXYZnNmgM1sovubeQqATo1IwUDAfBgNVHSMEGDAWgBTbhrci\n\ +FtULoUu33SV7ufEFfaItRzAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFPtxruhl\n\ +cRBQsJdwcZqLu9oNUVgaMAwGCCqGSM49BAMDBQADaAAwZQIxAJta0PQ2p4DIu/ps\n\ +LMdLCDgQ5UH1l0B4PGhBlMgdi2zf8nk9spazEQI/0XNwpft8QAIwHSuA2WelVi/o\n\ +zAlF08DnbJrOOtOnQq5wHOPlDYB4OtUzOYJk9scotrEnJxJzGsh/\n\ +-----END CERTIFICATE-----\n"; + +class VerifyHapTest : public testing::Test { +public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp(); + + void TearDown(); +}; + +void VerifyHapTest::SetUpTestCase(void) +{ + (void)rename("./hapVerify/test.txt", "./hapVerify/test.hap"); + (void)rename("./hapVerify/test1.txt", "./hapVerify/test1.hap"); + (void)rename("./hapVerify/test2.txt", "./hapVerify/test2.hap"); + (void)rename("./hapVerify/test3.txt", "./hapVerify/test3.hap"); + (void)rename("./hapVerify/test4.txt", "./hapVerify/test4.hap"); + (void)rename("./hapVerify/test5.txt", "./hapVerify/test5.hap"); +} + +void VerifyHapTest::TearDownTestCase(void) +{ + (void)remove("./hapVerify/unvaild.app"); + (void)remove("./hapVerify/unvaild.hap"); + (void)remove("./hapVerify/unvaild.hqf"); + (void)remove("./hapVerify/unvaild.hsp"); + (void)remove("./hapVerify/unvaild.txt"); + (void)remove("./hapVerify/phone-default-signed.hap"); +} + +void VerifyHapTest::SetUp() +{ +} + +void VerifyHapTest::TearDown() +{ +} + +/** + * @tc.name: Test CheckFilePath function + * @tc.desc: The static function test whether input is a valid filepath; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, CheckFilePathTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. input an too long filepath. + * @tc.expected: step1. the return will be false. + */ + VerifyHap v2; + std::string filePath = HAP_FILE_ECC_SIGN_BASE64; + std::string standardFilePath; + ASSERT_FALSE(v2.CheckFilePath(filePath, standardFilePath)); +} + +/** + * @tc.name: Test GenerateAppId function + * @tc.desc: The static function will return whether generate appid successfully; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, GenerateAppIdTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. input a null ProvisionInfo. + * @tc.expected: step1. the return will be false. + */ + VerifyHap v2; + ProfileInfo provisionInfo; + ASSERT_FALSE(v2.GenerateAppId(provisionInfo)); +} + +/** + * @tc.name: Test GenerateFingerprint function + * @tc.desc: The static function will return whether generate fingerprint successfully; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, GenerateFingerprintTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. input a null ProvisionInfo. + * @tc.expected: step1. the return will be false. + */ + VerifyHap v2; + ProfileInfo provisionInfo; + ASSERT_FALSE(v2.GenerateFingerprint(provisionInfo)); +} + +/** + * @tc.name: Test GenerateFingerprint function + * @tc.desc: The static function will return whether generate fingerprint successfully; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, GenerateFingerprintTest002, TestSize.Level1) +{ + /* + * @tc.steps: step1. input ProvisionInfo with error distributionCertificate. + * @tc.expected: step1. the return will be false. + */ + VerifyHap v2; + ProfileInfo provisionInfo; + provisionInfo.bundleInfo.distributionCertificate = ERROR_CERTIFICATE; + ASSERT_FALSE(v2.GenerateFingerprint(provisionInfo)); +} + +/** + * @tc.name: Test GenerateFingerprint function + * @tc.desc: The static function will return whether generate fingerprint successfully; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, GenerateFingerprintTest003, TestSize.Level1) +{ + /* + * @tc.steps: step1. input ProvisionInfo with error distributionCertificate. + * @tc.expected: step1. the return will be false. + */ + VerifyHap v2; + ProfileInfo provisionInfo; + provisionInfo.bundleInfo.developmentCertificate = ERROR_CERTIFICATE; + ASSERT_FALSE(v2.GenerateFingerprint(provisionInfo)); +} + +/** + * @tc.name: Test GenerateFingerprint function + * @tc.desc: The static function will return whether generate fingerprint successfully; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, GenerateFingerprintTest004, TestSize.Level1) +{ + /* + * @tc.steps: step1. input ProvisionInfo with error distributionCertificate. + * @tc.expected: step1. the return will be false. + */ + VerifyHap v2; + ProfileInfo provisionInfo; + provisionInfo.bundleInfo.distributionCertificate = TEST_CERTIFICATE; + ASSERT_TRUE(v2.GenerateFingerprint(provisionInfo)); +} + +/** + * @tc.name: Test GenerateFingerprint function + * @tc.desc: The static function will return whether generate fingerprint successfully; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, GenerateFingerprintTest005, TestSize.Level1) +{ + /* + * @tc.steps: step1. input ProvisionInfo with correct distributionCertificate. + * @tc.expected: step1. the return will be true. + */ + VerifyHap v2; + ProfileInfo provisionInfo; + provisionInfo.bundleInfo.developmentCertificate = TEST_CERTIFICATE; + ASSERT_TRUE(v2.GenerateFingerprint(provisionInfo)); +} + +/** + * @tc.name: Test VerifyProfileInfo function + * @tc.desc: The static function will return result of verify profile info; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyProfileInfoTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. profile match with debug and profile type is release. + * @tc.expected: step1. the return will be false. + */ + VerifyHap v2; + Pkcs7Context pkcs7Context; + Pkcs7Context profileContext; + ProfileInfo provisionInfo; + profileContext.matchResult.matchState = MATCH_WITH_PROFILE_DEBUG; + provisionInfo.type = ProvisionType::RELEASE; + ASSERT_FALSE(v2.VerifyProfileInfo(pkcs7Context, profileContext, provisionInfo)); +} + +/** + * @tc.name: Test ParseAndVerifyProfileIfNeed function + * @tc.desc: The static function will return result of ParseAndVerifyProfileIfNeed; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, ParseAndVerifyProfileIfNeedTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. input a null profile. + * @tc.expected: step1. the return will be false. + */ + VerifyHap v2; + std::string profile; + ProfileInfo provisionInfo; + ASSERT_FALSE(v2.ParseAndVerifyProfileIfNeed(profile, provisionInfo, false)); + /* + * @tc.steps: step1. input no need parse and verify profile. + * @tc.expected: step1. the return will be true. + */ + ASSERT_TRUE(v2.ParseAndVerifyProfileIfNeed(profile, provisionInfo, true)); +} + +/** + * @tc.name: Test GetDigestAndAlgorithm function + * @tc.desc: The static function will return result of GetDigestAndAlgorithm; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, GetDigestAndAlgorithmTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. input an error pkcs7 content. + * @tc.expected: step1. the return will be false. + */ + VerifyHap v2; + Pkcs7Context digest; + digest.content.SetCapacity(TEST_FILE_BLOCK_LENGTH); + ASSERT_FALSE(v2.GetDigestAndAlgorithm(digest)); +} + + +/** + * @tc.name: VerifyHapTest.Verify001 + * @tc.desc: The static function will return verify result; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify001, TestSize.Level0) +{ + /* + * @tc.steps: step1. input a invalid path to function of HapVerify. + * @tc.expected: step1. the return will be FILE_PATH_INVALID. + */ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/signed_test.app"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + OHOS::SignatureTools::HapVerifyResultCode targetResult = OHOS::SignatureTools::VERIFY_SUCCESS; + ASSERT_TRUE(resultCode != targetResult); + std::ofstream appFile; + appFile.open(errorFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(appFile.is_open()); + appFile.close(); + resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + ASSERT_TRUE(resultCode != targetResult); +} + + +/** + * @tc.name: VerifyHapTest.HapVerifyOsApp001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, HapVerifyOsApp001, TestSize.Level0) +{ + /* + * @tc.steps: step1. input a signed file to verify. + * @tc.expected: step1. the return will be VERIFY_SUCCESS. + */ + + std::string filePath = "./hapVerify/phone-default-signed.hap"; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + + VerifyHap verify; + int32_t ret = verify.Verify(filePath, hapVerifyResult, &options); + ASSERT_EQ(ret, OHOS::SignatureTools::VERIFY_SUCCESS); +} + +/** + * @tc.name: VerifyHapTest.Verify002 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify002, TestSize.Level0) +{ + std::string filePath = "./hapVerify/phone-default-signed.hap"; + std::string errorfilePath = "./hapVerify/phone-default-signed_error.hap"; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + OHOS::SignatureTools::ByteBuffer byteBuffer; + std::ifstream hapFile; + hapFile.open(filePath, std::ifstream::binary); + ASSERT_TRUE(hapFile.is_open()); + std::stringstream hapFileStr; + hapFileStr << hapFile.rdbuf(); + size_t strSize = hapFileStr.str().size(); + byteBuffer.SetCapacity(strSize); + byteBuffer.PutData(hapFileStr.str().c_str(), hapFileStr.str().size()); + hapFile.close(); + /* + * @tc.steps: step1. input a signed file to verify. + * @tc.expected: step1. the return will be VERIFY_SUCCESS. + */ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + VerifyHap verify; + ASSERT_TRUE(verify.Verify(filePath, hapVerifyResult, &options) == OHOS::SignatureTools::VERIFY_SUCCESS); + // /* + // * @tc.steps: step2. check verify result. + // * @tc.expected: step2. cert version is 1, certChains Len is 3. + // */ + OHOS::SignatureTools::ProfileInfo profile = hapVerifyResult.GetProvisionInfo(); + std::vector publicKeys = hapVerifyResult.GetPublicKey(); + ASSERT_TRUE(static_cast(publicKeys.size()) == TEST_CERT_CHAIN_LEN); + std::vector signatures = hapVerifyResult.GetSignature(); + ASSERT_TRUE(static_cast(signatures.size()) == TEST_CERT_CHAIN_LEN); + /* + * @tc.steps: step3. change comment data. + * @tc.expected: step3. the return will be VERIFY_INTEGRITY_FAIL. + */ + OHOS::SignatureTools::ByteBuffer errorCommentFile = byteBuffer; + char tmp = TEST_HAPBYTEBUFFER_CHAR_DATA; + errorCommentFile.PutByte(0, tmp); + std::ofstream errorFile; + errorFile.open(errorfilePath.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(errorFile.is_open()); + errorFile.seekp(0, std::ios_base::beg); + errorFile.write(errorCommentFile.GetBufferPtr(), errorCommentFile.GetCapacity()); + errorFile.close(); + OHOS::SignatureTools::HapVerifyResult verifyRet; + ASSERT_NE(verify.Verify(errorfilePath, verifyRet, &options), OHOS::SignatureTools::VERIFY_SUCCESS); + /* + * @tc.steps: step4. change profile pkcs7 data. + * @tc.expected: step4. the return will be APP_SOURCE_NOT_TRUSTED. + */ + errorCommentFile.PutByte(TEST_PFOFILE_PKCS7_DATA_INDEX, tmp); + errorFile.open(errorfilePath.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(errorFile.is_open()); + errorFile.seekp(0, std::ios_base::beg); + errorFile.write(errorCommentFile.GetBufferPtr(), errorCommentFile.GetCapacity()); + errorFile.close(); + ASSERT_NE(verify.Verify(errorfilePath, verifyRet, &options), OHOS::SignatureTools::VERIFY_SUCCESS); + /* + * @tc.steps: step5. change app pkcs7 data. + * @tc.expected: step5. the return will be VERIFY_APP_PKCS7_FAIL. + */ + errorCommentFile.PutByte(TEST_APP_PKCS7_DATA_INDEX, tmp); + errorFile.open(errorfilePath.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(errorFile.is_open()); + errorFile.seekp(0, std::ios_base::beg); + errorFile.write(errorCommentFile.GetBufferPtr(), errorCommentFile.GetCapacity()); + errorFile.close(); + ASSERT_NE(verify.Verify(errorfilePath, verifyRet, &options), OHOS::SignatureTools::VERIFY_SUCCESS); +} + +/** + * @tc.name: VerifyHapTest.Verify003 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ + +HWTEST_F(VerifyHapTest, Verify004, TestSize.Level0) +{ + /* + * @tc.steps: step1. input a invalid path to function of HapVerify. + * @tc.expected: step1. the return will be FILE_PATH_INVALID. + */ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + VerifyHap verify; + /* + * @tc.steps: step2. create a hapfile and run HapVerify. + * @tc.expected: step2. the return will be SIGNATURE_NOT_FOUND. + */ + std::string rightFile = "./hapVerify/signed.hap"; + std::ofstream hapFile; + hapFile.open(rightFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(hapFile.is_open()); + hapFile.seekp(0, std::ios_base::beg); + hapFile.write(MINIHAPFILE, TEST_MINI_HAP_FILE_LENGTH); + hapFile.close(); + int32_t resultCode = verify.Verify(rightFile, hapVerifyResult, &options); + ASSERT_TRUE(resultCode == OHOS::SignatureTools::SIGNATURE_NOT_FOUND); + + /* + * @tc.steps: step3. create an error hapfile and run HapVerify. + * @tc.expected: step3. the return will be SIGNATURE_NOT_FOUND. + */ + std::string rightFile1 = "./hapVerify/signed1.hap"; + std::ofstream hapFile1; + hapFile1.open(rightFile1.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(hapFile1.is_open()); + hapFile1.seekp(0, std::ios_base::beg); + hapFile1.write(MINIHAPFILE, sizeof(MINIHAPFILE)); + hapFile1.seekp(TEST_MINI_HAP_FILE_LENGTH - sizeof(short), std::ios_base::beg); + hapFile1.close(); + resultCode = verify.Verify(rightFile1, hapVerifyResult, &options); + ASSERT_TRUE(resultCode == OHOS::SignatureTools::SIGNATURE_NOT_FOUND); + + /* + * @tc.steps: step4. use an empty file to run HapVerify. + * @tc.expected: step4. the return will be SIGNATURE_NOT_FOUND. + */ + std::string invalidFile = "./hapVerify/signed2.hap"; + std::ofstream hapFile2; + hapFile2.open(invalidFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(hapFile2.is_open()); + hapFile2.close(); + resultCode = verify.Verify(invalidFile, hapVerifyResult, &options); + ASSERT_TRUE(resultCode == OHOS::SignatureTools::SIGNATURE_NOT_FOUND); +} +/** + * @tc.name: VerifyHapTest.Verify007 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify007, TestSize.Level0) +{ + std::string outPutPath = "./test.log"; + PKCS7* p7 = nullptr; + VerifyHap verify; + bool ret = verify.HapOutPutPkcs7(p7, outPutPath); + EXPECT_EQ(ret, false); +} +/** +* @tc.name: VerifyHapTest.Verify008 +* @tc.desc: The static function will return verify result of signed file; +* @tc.type: FUNC +*/ +HWTEST_F(VerifyHapTest, Verify008, TestSize.Level0) +{ + std::string profile = ""; + std::string ret = "111"; + VerifyHap verify; + int rets = verify.GetProfileContent(profile, ret); + EXPECT_EQ(rets, -1); +} +/** + * @tc.name: VerifyHapTest.Verify009 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify009, TestSize.Level0) +{ + VerifyHap verify; + std::string profile = "{version-name: 1.0.0,version-code: 1,uuid: fe686e1b-3770-4824-a938-961b140a7c98}"; + std::string ret = "111"; + int rets = verify.GetProfileContent(profile, ret); + EXPECT_EQ(rets, -1); +} +/** + * @tc.name: VerifyHapTest.Verify010 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify010, TestSize.Level0) +{ + VerifyHap verify; + Pkcs7Context pkcs7Context; + ByteBuffer hapSignatureBlock; + bool ret = verify.VerifyAppPkcs7(pkcs7Context, hapSignatureBlock); + EXPECT_EQ(ret, false); +} + +/** + * @tc.name: VerifyHapTest.Verify013 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify013, TestSize.Level0) +{ + VerifyHap verify; + ProfileInfo provisionInfo; + verify.SetOrganization(provisionInfo); +} +/** + * @tc.name: VerifyHapTest.Verify014 + * @tc.desc: The static function will return verify result; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify014, TestSize.Level0) +{ + /* + * @tc.steps: step1. input a invalid path to function of HapVerify. + * @tc.expected: step1. the return will be FILE_PATH_INVALID. + */ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/signed_test.app"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + OHOS::SignatureTools::HapVerifyResultCode targetResult = OHOS::SignatureTools::VERIFY_SUCCESS; + ASSERT_TRUE(resultCode != targetResult); + std::ofstream appFile; + appFile.open(errorFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(appFile.is_open()); + appFile.close(); + resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + ASSERT_TRUE(resultCode != targetResult); + /* + * @tc.steps: step2. create a hapfile and run HapVerify. + * @tc.expected: step2. the return will be SIGNATURE_NOT_FOUND. + */ + std::string rightFile = "./hapVerify/signed.hap"; + std::ofstream hapFile; + hapFile.open(rightFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(hapFile.is_open()); + hapFile.seekp(0, std::ios_base::beg); + hapFile.write(MINIHAPFILE, TEST_MINI_HAP_FILE_LENGTH); + hapFile.close(); + resultCode = verify.Verify(rightFile, hapVerifyResult, &options); + ASSERT_TRUE(resultCode == OHOS::SignatureTools::SIGNATURE_NOT_FOUND); + + /* + * @tc.steps: step3. create an error hapfile and run HapVerify. + * @tc.expected: step3. the return will be SIGNATURE_NOT_FOUND. + */ + std::string rightFile1 = "./hapVerify/signed1.hap"; + std::ofstream hapFile1; + hapFile1.open(rightFile1.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(hapFile1.is_open()); + hapFile1.seekp(0, std::ios_base::beg); + hapFile1.write(MINIHAPFILE, sizeof(MINIHAPFILE)); + hapFile1.seekp(TEST_MINI_HAP_FILE_LENGTH - sizeof(short), std::ios_base::beg); + hapFile1.close(); + resultCode = verify.Verify(rightFile1, hapVerifyResult, &options); + ASSERT_TRUE(resultCode == OHOS::SignatureTools::SIGNATURE_NOT_FOUND); + + /* + * @tc.steps: step4. use an empty file to run HapVerify. + * @tc.expected: step4. the return will be SIGNATURE_NOT_FOUND. + */ + std::string invalidFile = "./hapVerify/signed2.hap"; + std::ofstream hapFile2; + hapFile2.open(invalidFile.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(hapFile2.is_open()); + hapFile2.close(); + resultCode = verify.Verify(invalidFile, hapVerifyResult, &options); + ASSERT_TRUE(resultCode == OHOS::SignatureTools::SIGNATURE_NOT_FOUND); +} + + +/** + * @tc.name: VerifyHapTest.Verify015 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify015, TestSize.Level0) +{ + /* + * @tc.steps: step1. input a signed file to verify. + * @tc.expected: step1. the return will be VERIFY_SUCCESS. + */ + + std::string filePath = "./hapVerify/phone-default-signed.hap"; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + + VerifyHap verify; + int32_t ret = verify.Verify(filePath, hapVerifyResult, &options); + ASSERT_EQ(ret, OHOS::SignatureTools::VERIFY_SUCCESS); +} + +/** + * @tc.name: VerifyHapTest.Verify016 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify016, TestSize.Level0) +{ + std::string filePath = "./hapVerify/phone-default-signed.hap"; + std::string errorfilePath = "./hapVerify/phone-default-signed_error.hap"; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + OHOS::SignatureTools::ByteBuffer byteBuffer; + std::ifstream hapFile; + hapFile.open(filePath, std::ifstream::binary); + ASSERT_TRUE(hapFile.is_open()); + std::stringstream hapFileStr; + hapFileStr << hapFile.rdbuf(); + size_t strSize = hapFileStr.str().size(); + byteBuffer.SetCapacity(strSize); + byteBuffer.PutData(hapFileStr.str().c_str(), hapFileStr.str().size()); + hapFile.close(); + /* + * @tc.steps: step1. input a signed file to verify. + * @tc.expected: step1. the return will be VERIFY_SUCCESS. + */ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + VerifyHap verify; + ASSERT_TRUE(verify.Verify(filePath, hapVerifyResult, &options) == OHOS::SignatureTools::VERIFY_SUCCESS); + // /* + // * @tc.steps: step2. check verify result. + // * @tc.expected: step2. cert version is 1, certChains Len is 3. + // */ + OHOS::SignatureTools::ProfileInfo profile = hapVerifyResult.GetProvisionInfo(); + std::vector publicKeys = hapVerifyResult.GetPublicKey(); + ASSERT_TRUE(static_cast(publicKeys.size()) == TEST_CERT_CHAIN_LEN); + std::vector signatures = hapVerifyResult.GetSignature(); + ASSERT_TRUE(static_cast(signatures.size()) == TEST_CERT_CHAIN_LEN); + /* + * @tc.steps: step3. change comment data. + * @tc.expected: step3. the return will be VERIFY_INTEGRITY_FAIL. + */ + OHOS::SignatureTools::ByteBuffer errorCommentFile = byteBuffer; + char tmp = TEST_HAPBYTEBUFFER_CHAR_DATA; + errorCommentFile.PutByte(0, tmp); + std::ofstream errorFile; + errorFile.open(errorfilePath.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(errorFile.is_open()); + errorFile.seekp(0, std::ios_base::beg); + errorFile.write(errorCommentFile.GetBufferPtr(), errorCommentFile.GetCapacity()); + errorFile.close(); + OHOS::SignatureTools::HapVerifyResult verifyRet; + ASSERT_NE(verify.Verify(errorfilePath, verifyRet, &options), OHOS::SignatureTools::VERIFY_SUCCESS); + /* + * @tc.steps: step4. change profile pkcs7 data. + * @tc.expected: step4. the return will be APP_SOURCE_NOT_TRUSTED. + */ + errorCommentFile.PutByte(TEST_PFOFILE_PKCS7_DATA_INDEX, tmp); + errorFile.open(errorfilePath.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(errorFile.is_open()); + errorFile.seekp(0, std::ios_base::beg); + errorFile.write(errorCommentFile.GetBufferPtr(), errorCommentFile.GetCapacity()); + errorFile.close(); + ASSERT_NE(verify.Verify(errorfilePath, verifyRet, &options), OHOS::SignatureTools::VERIFY_SUCCESS); + /* + * @tc.steps: step5. change app pkcs7 data. + * @tc.expected: step5. the return will be VERIFY_APP_PKCS7_FAIL. + */ + errorCommentFile.PutByte(TEST_APP_PKCS7_DATA_INDEX, tmp); + errorFile.open(errorfilePath.c_str(), std::ios::binary | std::ios::out | std::ios::trunc); + ASSERT_TRUE(errorFile.is_open()); + errorFile.seekp(0, std::ios_base::beg); + errorFile.write(errorCommentFile.GetBufferPtr(), errorCommentFile.GetCapacity()); + errorFile.close(); + ASSERT_NE(verify.Verify(errorfilePath, verifyRet, &options), OHOS::SignatureTools::VERIFY_SUCCESS); +} + +/** + * @tc.name: VerifyHapTest.Verify021 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify021, TestSize.Level0) +{ + std::string outPutPath = "./test.log"; + PKCS7* p7 = nullptr; + VerifyHap verify; + bool ret = verify.HapOutPutPkcs7(p7, outPutPath); + EXPECT_EQ(ret, false); +} +/** +* @tc.name: VerifyHapTest.Verify022 +* @tc.desc: The static function will return verify result of signed file; +* @tc.type: FUNC +*/ +HWTEST_F(VerifyHapTest, Verify022, TestSize.Level0) +{ + std::string profile = ""; + std::string ret = "111"; + VerifyHap verify; + int rets = verify.GetProfileContent(profile, ret); + EXPECT_EQ(rets, -1); +} +/** + * @tc.name: VerifyHapTest.Verify023 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify023, TestSize.Level0) +{ + VerifyHap verify; + std::string profile = "{version-name: 1.0.0,version-code: 1,uuid: fe686e1b-3770-4824-a938-961b140a7c98}"; + std::string ret = "111"; + int rets = verify.GetProfileContent(profile, ret); + EXPECT_EQ(rets, -1); +} +/** + * @tc.name: VerifyHapTest.Verify024 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify024, TestSize.Level0) +{ + VerifyHap verify; + Pkcs7Context pkcs7Context; + ByteBuffer hapSignatureBlock; + bool ret = verify.VerifyAppPkcs7(pkcs7Context, hapSignatureBlock); + EXPECT_EQ(ret, false); +} + +/** + * @tc.name: VerifyHapTest.Verify027 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, Verify027, TestSize.Level0) +{ + VerifyHap verify; + ProfileInfo provisionInfo; + verify.SetOrganization(provisionInfo); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError001, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/unvaild.hqf"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError002, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/unvaild.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError003, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/unvaild.app"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError004, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/unvaild.hsp"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError005, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/unvaild.txt"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError006, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify_nohave/certchain.pem"; + options[Options::OUT_PROFILE] = "./hapVerify_nohava/profile.p7b"; + + std::string errorFile = "./hapVerify/phone-default-signed.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError007, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + std::shared_ptr params = std::make_shared(); + + std::string outCertChain = "./hapVerify_nohave/certchain.pem"; + std::string outProfile = "./hapVerify/profile.p7b"; + (*params)["outCertChain"] = outCertChain; + (*params)["outProfile"] = outProfile; + + + std::string errorFile = "./hapVerify/phone-default-signed.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, params.get()); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError008, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + std::shared_ptr params = std::make_shared(); + + std::string outCertChain = "./hapVerify/certchain.pem"; + std::string outProfile = "./hapVerify_nohave/profile.p7b"; + (*params)["outCertChain"] = outCertChain; + (*params)["outProfile"] = outProfile; + + + std::string errorFile = "./hapVerify/phone-default-signed.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, params.get()); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError009, TestSize.Level0) +{ + Pkcs7Context pkcs7Context_t; + MatchingResult t; + t.matchState = MATCH_WITH_SIGN; + t.source = APP_THIRD_PARTY_PRELOAD; + pkcs7Context_t.matchResult = t; + VerifyHap verify; + bool ret = verify.VerifyProfileSignature(pkcs7Context_t, pkcs7Context_t); + EXPECT_NE(ret, true); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError010, TestSize.Level0) +{ + AppDistType type = APP_GALLERY; + ProfileInfo provisionInfo; + VerifyHap verify; + bool ret = verify.IsAppDistributedTypeAllowInstall(type, provisionInfo); + EXPECT_EQ(ret, true); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError011, TestSize.Level0) +{ + AppDistType type = NONE_TYPE; + ProfileInfo provisionInfo; + VerifyHap verify; + bool ret = verify.IsAppDistributedTypeAllowInstall(type, provisionInfo); + EXPECT_EQ(ret, false); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError012, TestSize.Level0) +{ + VerifyHap verify; + Pkcs7Context digest; + ByteBuffer content("1", 1); + digest.content = content; + bool ret = verify.GetDigestAndAlgorithm(digest); + EXPECT_EQ(ret, false); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError013, TestSize.Level0) +{ + VerifyHap verify; + Pkcs7Context digest; + ByteBuffer content("12345678912345", 14); + digest.content = content; + bool ret = verify.GetDigestAndAlgorithm(digest); + EXPECT_EQ(ret, false); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError014, TestSize.Level0) +{ + VerifyHap verify; + Pkcs7Context digest; + ByteBuffer content("123456789123456789123456789", 27); + digest.content = content; + bool ret = verify.GetDigestAndAlgorithm(digest); + EXPECT_EQ(ret, false); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError015, TestSize.Level0) +{ + VerifyHap verify; + Pkcs7Context digest; + ByteBuffer content("123456789123456789123456789", 19); + digest.content = content; + bool ret = verify.GetDigestAndAlgorithm(digest); + EXPECT_EQ(ret, false); +} + +/** +* @tc.name: VerifyHapTest.VerifyHapError001 +* @tc.desc: The static function will return verify result of signed file; +* @tc.type: FUNC +*/ +HWTEST_F(VerifyHapTest, VerifyHapError016, TestSize.Level0) +{ + bool ret = false; + VerifyHap verify; + Pkcs7Context pkcs7Context; + MatchingResult t; + t.matchState = MATCH_WITH_SIGN; + t.source = APP_GALLARY; + pkcs7Context.matchResult = t; + ByteBuffer hapProfileBlock; + ProfileInfo provisionInfo; + verify.SetProfileBlockData(pkcs7Context, hapProfileBlock, provisionInfo); + EXPECT_EQ(ret, false); +} + +/** +* @tc.name: VerifyHapTest.VerifyHapError001 +* @tc.desc: The static function will return verify result of signed file; +* @tc.type: FUNC +*/ +HWTEST_F(VerifyHapTest, VerifyHapError017, TestSize.Level0) +{ + bool ret = false; + VerifyHap verify; + Pkcs7Context pkcs7Context; + MatchingResult t; + t.matchState = MATCH_WITH_SIGN; + t.source = APP_THIRD_PARTY_PRELOAD; + pkcs7Context.matchResult = t; + ByteBuffer hapProfileBlock; + ProfileInfo provisionInfo; + verify.SetProfileBlockData(pkcs7Context, hapProfileBlock, provisionInfo); + EXPECT_EQ(ret, false); +} + +/** +* @tc.name: VerifyHapTest.VerifyHapError001 +* @tc.desc: The static function will return verify result of signed file; +* @tc.type: FUNC +*/ +HWTEST_F(VerifyHapTest, VerifyHapError018, TestSize.Level0) +{ + bool ret = false; + VerifyHap verify; + Pkcs7Context pkcs7Context; + MatchingResult t; + t.matchState = MATCH_WITH_SIGN; + t.source = APP_THIRD_PARTY_PRELOAD; + pkcs7Context.matchResult = t; + ByteBuffer hapProfileBlock; + ProfileInfo provisionInfo; + verify.SetProfileBlockData(pkcs7Context, hapProfileBlock, provisionInfo); + EXPECT_EQ(ret, false); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError019, TestSize.Level0) +{ + bool ret = false; + VerifyHap verify; + Pkcs7Context pkcs7Context; + Pkcs7Context profileContext; + ProfileInfo provisionInfo; + provisionInfo.type = ProvisionType::RELEASE; + provisionInfo.distributionType = APP_GALLERY; + ret = verify.VerifyProfileInfo(pkcs7Context, profileContext, provisionInfo); + EXPECT_EQ(ret, true); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError024, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.cer"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/test.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError025, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.cer"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/test1.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError026, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.cer"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/test2.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError027, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.cer"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/test3.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError028, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.cer"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/test4.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} + +/** + * @tc.name: VerifyHapTest.VerifyHapError001 + * @tc.desc: The static function will return verify result of signed file; + * @tc.type: FUNC + */ +HWTEST_F(VerifyHapTest, VerifyHapError029, TestSize.Level0) +{ + OHOS::SignatureTools::HapVerifyResult hapVerifyResult; + Options options; + options[Options::OUT_CERT_CHAIN] = "./hapVerify/certchain.cer"; + options[Options::OUT_PROFILE] = "./hapVerify/profile.p7b"; + + std::string errorFile = "./hapVerify/test5.hap"; + + VerifyHap verify; + int32_t resultCode = verify.Verify(errorFile, hapVerifyResult, &options); + EXPECT_NE(resultCode, 0); +} +} +} diff --git a/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_test.h b/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_test.h new file mode 100644 index 0000000000000000000000000000000000000000..00a95757e39599edebf2b1f6a3c711dce31c4a57 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/hap_verify_test.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAP_VERIFY_V2_TEST_H +#define HAP_VERIFY_V2_TEST_H + +#include + +#include "test_const.h" + +int32_t CheckFilePathTest001(void); +int32_t GenerateAppIdTest001(void); +int32_t ParseAndVerifyProfileIfNeedTest001(void); +int32_t GetDigestAndAlgorithmTest001(void); +#endif // HAP_VERIFY_V2_TEST_H diff --git a/hapsigntool_cpp/test/unittest/hapVerify/packets/test.txt b/hapsigntool_cpp/test/unittest/hapVerify/packets/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..e726e0857d0cc219f473b0d499b0383662acfcfe Binary files /dev/null and b/hapsigntool_cpp/test/unittest/hapVerify/packets/test.txt differ diff --git a/hapsigntool_cpp/test/unittest/hapVerify/packets/test1.txt b/hapsigntool_cpp/test/unittest/hapVerify/packets/test1.txt new file mode 100644 index 0000000000000000000000000000000000000000..72f32a26b19f14e04f721f182f5718a78c9ea1f0 Binary files /dev/null and b/hapsigntool_cpp/test/unittest/hapVerify/packets/test1.txt differ diff --git a/hapsigntool_cpp/test/unittest/hapVerify/packets/test2.txt b/hapsigntool_cpp/test/unittest/hapVerify/packets/test2.txt new file mode 100644 index 0000000000000000000000000000000000000000..e9623cdf94b4adb1959814ecc9a59bcc87b56964 Binary files /dev/null and b/hapsigntool_cpp/test/unittest/hapVerify/packets/test2.txt differ diff --git a/hapsigntool_cpp/test/unittest/hapVerify/packets/test3.txt b/hapsigntool_cpp/test/unittest/hapVerify/packets/test3.txt new file mode 100644 index 0000000000000000000000000000000000000000..6f589912b605642da31c538bd0ab082730327fc8 Binary files /dev/null and b/hapsigntool_cpp/test/unittest/hapVerify/packets/test3.txt differ diff --git a/hapsigntool_cpp/test/unittest/hapVerify/packets/test4.txt b/hapsigntool_cpp/test/unittest/hapVerify/packets/test4.txt new file mode 100644 index 0000000000000000000000000000000000000000..f65d71e299f9f358519d2459769d7c0333efec54 Binary files /dev/null and b/hapsigntool_cpp/test/unittest/hapVerify/packets/test4.txt differ diff --git a/hapsigntool_cpp/test/unittest/hapVerify/packets/test5.txt b/hapsigntool_cpp/test/unittest/hapVerify/packets/test5.txt new file mode 100644 index 0000000000000000000000000000000000000000..702e4ab11ab7107aa856d5a744243947fd3bb113 Binary files /dev/null and b/hapsigntool_cpp/test/unittest/hapVerify/packets/test5.txt differ diff --git a/hapsigntool_cpp/test/unittest/hapVerify/provision_verify_test.cpp b/hapsigntool_cpp/test/unittest/hapVerify/provision_verify_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e33169db8e893d4a98b62a59d31073ab4b677cf --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/provision_verify_test.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "provision_verify_test.h" + +#include +#include "profile_verify.h" + +using namespace testing::ext; +using namespace OHOS::SignatureTools; + +namespace { + const std::string INVALID_PROVISION_1 = R"( + { + "version-name": "1.0.0", + "issuer": "App Gallery" + })"; + const std::string INVALID_PROVISION_2 = R"( + { + "version-code": 2, + "version-name": "1.1.0", + "uuid": "uuid_1_1", + "type": "release", + "app-distribution-type": "os_integration", + "validity": { + "not-before": 1262275201, + "not-after": 2524579301 + }, + "bundle-info": { + "developer-id": "developer_id_1_1", + "development-certificate": "ABCD", + "distribution-certificate": "1234", + "bundle-name": "com.test1_1", + "apl": "normal", + "app-feature": "hos_normal_app" + } + }})"; // brackets mismatching + const std::string INVALID_PROVISION_3 = R"( + { + "version-code": 2, + "version-name": "2.0.0", + "uuid": "uuid_2", + "type": "release", + "app-distribution-type": "os_integration", + "validity": { + "not-before": 1262275200, + "not-after": 2524579300 + }, + "bundle-info": { + "developer-id": "developer_id_2", + "development-certificate": "ABCDEFG", + "distribution-certificate": "123456789", + "bundle-name": "com.test2", + "app-feature": "hos_normal_app" + } + })"; // apl not exist + /* validity: 2010 - 2030 */ + const std::string VALID_PROVISION = R"( + { + "version-code": 2, + "version-name": "2.0.0", + "uuid": "uuid_2", + "type": "release", + "app-distribution-type": "os_integration", + "validity": { + "not-before": 1262275200, + "not-after": 2524579300 + }, + "bundle-info": { + "developer-id": "developer_id_2", + "development-certificate": "ABCDEFG", + "distribution-certificate": "123456789", + "bundle-name": "com.test2", + "apl": "normal", + "app-feature": "hos_normal_app" + } + })"; + const std::string VALID_PROVISION_PERMISSION = R"( + { + "version-code": 3, + "version-name": "3.0.0", + "uuid": "uuid_3", + "type": "release", + "app-distribution-type": "app_gallery", + "validity": { + "not-before": 1262275300, + "not-after": 2524579300 + }, + "bundle-info": { + "developer-id": "developer_id_3", + "development-certificate": "ABCDEFGH", + "distribution-certificate": "1234567890", + "bundle-name": "com.test3", + "apl": "normal", + "app-feature": "hos_normal_app" + }, + "permissions" : { + "restricted-permissions" : ["ohos.permission.GET_PHONE_STATE", + "ohos.permission.GET_APP_ACCOUNTS"], + "restricted-capabilities" : ["ohos.permission.test"] + }, + "issuer": "App Gallery" + })"; + const std::string UNAUTHORIZED_DEVICE_EMPTY_DEVICE_LIST_PROVISION = R"( + { + "version-code": 6, + "version-name": "6.0.0", + "uuid": "uuid_6", + "type": "debug", + "validity": { + "not-before": 1262275600, + "not-after": 2524579300 + }, + "bundle-info": { + "developer-id": "developer_id_6", + "development-certificate": "ABCDEFGHIJ", + "distribution-certificate": "1234567890123", + "bundle-name": "com.test6", + "apl": "normal", + "app-feature": "hos_normal_app" + }, + "debug-info": { + "device-id-type": "udid" + }, + "issuer": "App Gallery" + })"; + const std::string UNSUPPORTED_DEVICE_TYPE_PROVISION = R"( + { + "version-code": 7, + "version-name": "7.0.0", + "uuid": "uuid_7", + "type": "debug", + "validity": { + "not-before": 1262275600, + "not-after": 2524579300 + }, + "bundle-info": { + "developer-id": "developer_id_7", + "development-certificate": "ABCDEFGHIJM", + "distribution-certificate": "12345678901231", + "bundle-name": "com.test7", + "apl": "normal", + "app-feature": "hos_normal_app" + }, + "debug-info": { + "device-id-type": "unknownType", + "device-ids" : ["1234ABCD"] + }, + "issuer": "App Gallery" + })"; + const std::string DEVICE_UNAUTH_PROVISION = R"( + { + "version-code": 8, + "version-name": "8.0.0", + "uuid": "uuid_8", + "type": "debug", + "validity": { + "not-before": 1262275700, + "not-after": 2524579300 + }, + "bundle-info": { + "developer-id": "developer_id_8", + "development-certificate": "ABCDEFGHIJK", + "distribution-certificate": "12345678901234", + "bundle-name": "com.test8", + "apl": "normal", + "app-feature": "hos_normal_app" + }, + "debug-info": { + "device-id-type": "udid", + "device-ids" : ["1234ABCD"] + }, + "issuer": "App Gallery" + })"; + + class ProvisionVerifyTest : public testing::Test { + public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp(); + + void TearDown(); + }; + + void ProvisionVerifyTest::SetUpTestCase(void) + { + } + + void ProvisionVerifyTest::TearDownTestCase(void) + { + } + + void ProvisionVerifyTest::SetUp() + { + } + + void ProvisionVerifyTest::TearDown() + { + } + + /** + * @tc.name: Test HarmonyAppProvision ProvisionVerify001 function + * @tc.desc: The static function will return verify result; + * @tc.type: FUNC + */ + HWTEST_F(ProvisionVerifyTest, ProvisionVerify001, TestSize.Level1) + { + /* + * @tc.steps: step1. input a invalid HarmonyAppProvision + * and run ParseAndVerify function. + * @tc.expected: step1. return code will be PROVISION_INVALID. + */ + ProfileInfo info; + int32_t ret = ParseAndVerify(INVALID_PROVISION_1, info); + ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_INVALID); + ret = ParseAndVerify(INVALID_PROVISION_2, info); + ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_INVALID); + ret = ParseAndVerify(INVALID_PROVISION_3, info); + ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_INVALID); + } + + /** + * @tc.name: Test HarmonyAppProvision ProvisionVerify002 function + * @tc.desc: The static function will return verify result; + * @tc.type: FUNC + */ + HWTEST_F(ProvisionVerifyTest, ProvisionVerify002, TestSize.Level1) + { + /* + * @tc.steps: step2. input a valid HarmonyAppProvision (without permission info) + * and run ParseAndVerify function. + * @tc.expected: step2. return code will be PROVISION_OK. + */ + ProfileInfo info; + int32_t ret = ParseAndVerify(VALID_PROVISION, info); + ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_OK); + ASSERT_EQ(info.versionCode, 2); // version code is 2 + ASSERT_EQ(info.versionName, "2.0.0"); + ASSERT_EQ(info.uuid, "uuid_2"); + ASSERT_EQ(info.type, ProvisionType::RELEASE); + ASSERT_TRUE(info.permissions.restrictedPermissions.empty()); + ASSERT_TRUE(info.permissions.restrictedCapabilities.empty()); + } + + /** + * @tc.name: Test HarmonyAppProvision ProvisionVerify003 function + * @tc.desc: The static function will return verify result; + * @tc.type: FUNC + */ + HWTEST_F(ProvisionVerifyTest, ProvisionVerify003, TestSize.Level1) + { + /* + * @tc.steps: step3. input a valid HarmonyAppProvision (with permission info) + * and run ParseAndVerify function. + * @tc.expected: step3. return code will be PROVISION_OK. + */ + ProfileInfo info; + int32_t ret = ParseAndVerify(VALID_PROVISION_PERMISSION, info); + ASSERT_EQ(ret, AppProvisionVerifyResult::PROVISION_OK); + ASSERT_EQ(info.versionCode, 3); // version code is 3 + ASSERT_EQ(info.versionName, "3.0.0"); + ASSERT_EQ(info.uuid, "uuid_3"); + ASSERT_EQ(info.type, ProvisionType::RELEASE); + ASSERT_EQ(info.distributionType, AppDistType::APP_GALLERY); + ASSERT_TRUE(info.permissions.restrictedPermissions.size() == 2); // 2 restricted permissions + ASSERT_EQ(info.permissions.restrictedPermissions[0], "ohos.permission.GET_PHONE_STATE"); + ASSERT_TRUE(info.permissions.restrictedCapabilities.size() == 1); // 1 restricted capabilities + ASSERT_EQ(info.permissions.restrictedCapabilities[0], "ohos.permission.test"); + } + +} // namespace diff --git a/hapsigntool_cpp/test/unittest/hapVerify/provision_verify_test.h b/hapsigntool_cpp/test/unittest/hapVerify/provision_verify_test.h new file mode 100644 index 0000000000000000000000000000000000000000..f4cc3755b02fe86523790322d20b8058d6c9a887 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/provision_verify_test.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PROVISION_VERIFY_TEST_H +#define PROVISION_VERIFY_TEST_H + +#include + +int32_t ProvisionVerify001(void); +int32_t ProvisionVerify002(void); +int32_t ProvisionVerify003(void); +int32_t ProvisionVerify004(void); +int32_t ProvisionVerify005(void); +int32_t ProvisionVerify006(void); +int32_t ProvisionVerify007(void); +int32_t ProvisionVerify008(void); +#endif // PROVISION_VERIFY_TEST_H diff --git a/hapsigntool_cpp/test/unittest/hapVerify/random_access_file_test.cpp b/hapsigntool_cpp/test/unittest/hapVerify/random_access_file_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09d45cbb7e8beffaa53bf4d21532ffaab1dfdaf7 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/random_access_file_test.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "random_access_file_test.h" + +#include + +#include + +#include "byte_buffer.h" +#include "random_access_file.h" +#include "hap_verify_result.h" + +#include "hap_signer_block_utils.h" +#include "hap_signer_block_utils_test.h" +#include "test_const.h" + +using namespace testing::ext; +using namespace OHOS::SignatureTools; + +namespace { + class RandomAccessFileTest : public testing::Test { + public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp(); + + void TearDown(); + }; + + void RandomAccessFileTest::SetUpTestCase(void) + { + } + + void RandomAccessFileTest::TearDownTestCase(void) + { + } + + void RandomAccessFileTest::SetUp() + { + } + + void RandomAccessFileTest::TearDown() + { + } + + /** + * @tc.name: Test ReadFileFullyFromOffset function + * @tc.desc: The static function will return each reading result; + * @tc.type: FUNC + */ + HWTEST_F(RandomAccessFileTest, ReadFileFullyFromOffsetTest001, TestSize.Level1) + { + /* + * @tc.steps: step1. use null buffer to ReadFileFullyFromOffset . + * @tc.expected: step1. the return will be DEST_BUFFER_IS_NULL. + */ + std::string filePath = "./hapVerify/test_hapverify.zip"; + SignatureInfo si0; + int32_t sumLen = HapSignerBlockUtils::CreatTestZipFile(filePath, si0); + RandomAccessFile hapTestFile1; + bool initRet = hapTestFile1.Init(filePath); + ASSERT_TRUE(initRet); + ASSERT_TRUE(hapTestFile1.GetLength() == sumLen); + ReadFileErrorCode targetCode = DEST_BUFFER_IS_NULL; + long long ret = hapTestFile1.ReadFileFullyFromOffset(nullptr, 0, 0); + ASSERT_TRUE(ret == targetCode); + ByteBuffer nullBuffer; + ret = hapTestFile1.ReadFileFullyFromOffset(nullBuffer, 0); + ASSERT_TRUE(ret == targetCode); + /* + * @tc.steps: step2. use a buffer to read a null file. + * @tc.expected: step2. the return will be FILE_IS_CLOSE. + */ + filePath = "./hapVerify/test_hapverify1.zip"; + RandomAccessFile nullTestFile; + initRet = nullTestFile.Init(filePath); + ASSERT_FALSE(initRet); + std::unique_ptr buffer = std::make_unique(TEST_RANDOMREAD_LENGTH); + ASSERT_TRUE(buffer != nullptr); + ret = nullTestFile.ReadFileFullyFromOffset(buffer.get(), 0, TEST_RANDOMREAD_LENGTH); + ASSERT_EQ(ret, FILE_IS_CLOSE); + /* + * @tc.steps: step3. use a large buffer to read a mini file. + * @tc.expected: step3. the return will be READ_DATA_NOT_ENOUGH. + */ + std::string testFile = "./hapVerify/test_hapverify.txt"; + SignatureInfo si; + sumLen = HapSignerBlockUtils::CreatTestZipFile(testFile, si); + RandomAccessFile hapTestFile2; + initRet = hapTestFile2.Init(testFile); + ASSERT_TRUE(initRet); + ASSERT_TRUE(hapTestFile2.GetLength() == sumLen); + ret = hapTestFile2.ReadFileFullyFromOffset(buffer.get(), 0, TEST_RANDOMREAD_LENGTH); + ASSERT_EQ(ret, READ_OFFSET_OUT_OF_RANGE); + ByteBuffer hapBuffer(TEST_RANDOMREAD_LENGTH); + ret = hapTestFile2.ReadFileFullyFromOffset(hapBuffer, 0); + ASSERT_EQ(ret, READ_OFFSET_OUT_OF_RANGE); + /* + * @tc.steps: step4. use a negative offset to read a file. + * @tc.expected: step4. the return will be READ_OFFSET_OUT_OF_RANGE. + */ + ret = hapTestFile2.ReadFileFullyFromOffset(hapBuffer, -1); + ASSERT_TRUE(ret == READ_OFFSET_OUT_OF_RANGE); + ret = hapTestFile2.ReadFileFullyFromOffset(buffer.get(), -1, TEST_RANDOMREAD_LENGTH); + ASSERT_TRUE(ret == READ_OFFSET_OUT_OF_RANGE); + buffer.reset(nullptr); + } +} diff --git a/hapsigntool_cpp/test/unittest/hapVerify/random_access_file_test.h b/hapsigntool_cpp/test/unittest/hapVerify/random_access_file_test.h new file mode 100644 index 0000000000000000000000000000000000000000..6ef57b10a252087f51c22584386927e646c5b2b3 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/random_access_file_test.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RANDOM_ACCESS_FILE_TEST_H +#define RANDOM_ACCESS_FILE_TEST_H + +#include + +int32_t ReadFileFullyFromOffsetTest001(void); +#endif // RANDOM_ACCESS_FILE_TEST_H diff --git a/hapsigntool_cpp/test/unittest/hapVerify/test_const.h b/hapsigntool_cpp/test/unittest/hapVerify/test_const.h new file mode 100644 index 0000000000000000000000000000000000000000..0643f2667eb8c5a6e9c458a163c6b332be39a7e9 --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/test_const.h @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAPVERIFY_TEST_CONST_H +#define HAPVERIFY_TEST_CONST_H + +#include +#include + +namespace OHOS { + namespace SignatureTools { + constexpr char TEST_HAPBYTEBUFFER_CHAR_DATA = 0xff; + constexpr unsigned short TEST_HAPBYTEBUFFER_UINT16_DATA = 0xffff; + constexpr uint32_t TEST_HAPBYTEBUFFER_UINT32_DATA = 0xffffffff; + constexpr int32_t TEST_HAPBYTEBUFFER_INT32_DATA = 0xffffffff; + constexpr long long TEST_HAPBYTEBUFFER_INT64_DATA = 0xffffffffffffffff; + constexpr int32_t TEST_HAPBYTEBUFFER_INT32_DATA_2 = 100000; + constexpr int32_t TEST_HAPBYTEBUFFER_INVALID_INDEX = -1; + + constexpr int32_t TEST_RANDOMREAD_LENGTH = 150000; + constexpr int32_t TEST_HAPBYTEBUFFER_LENGTH = 15; + constexpr int32_t TEST_HAPBYTEBUFFER_LENGTH_2 = 8; + constexpr int32_t TEST_HAPBYTEBUFFER_POSITION = 10; + + constexpr int32_t TEST_HAPBYTEBUFFER_UINT16_LENGTH = 2; + constexpr int32_t TEST_HAPBYTEBUFFER_INT64_LENGTH = 8; + + constexpr int32_t TEST_FILE_BLOCK_LENGTH = 50; + constexpr int32_t TEST_FILE_BLOCK_COUNT = 3; + + constexpr int32_t TEST_FILE_CD_OFFSET_POSITION = 6; + + constexpr int32_t TEST_HAP_SIGN_VERSION = 1; + + constexpr int32_t TEST_MAX_COMMENT_SIZE = 4; + constexpr int32_t TEST_INVALID_MAX_COMMENT_SIZE = -1; + + constexpr int32_t TEST_ZIP_EOCD_SIZE = 22; + constexpr int32_t TEST_ZIP_ECD_OFFSET_FIELD_OFFSET = 16; + constexpr int32_t TEST_ZIP_ECD_SIZE_FIELD_OFFSET = 12; + constexpr int32_t TEST_ZIP_EOCD_COMMENT_OFFSET = 20; + + constexpr int32_t TEST_NULL_NID = 118; + constexpr int32_t TEST_SHA256_NID = 672; + constexpr int32_t TEST_SHA384_NID = 673; + constexpr int32_t TEST_SHA512_NID = 674; + + constexpr int32_t TEST_MINI_HAP_FILE_LENGTH = 2619; + + constexpr int32_t TEST_SIGN_VERSION = 2; + constexpr int32_t TEST_CERT_CHAIN_LEN = 3; + + constexpr int32_t TEST_FILE_NUM = 2; + constexpr int32_t TEST_PFOFILE_PKCS7_DATA_INDEX = 5110; + constexpr int32_t TEST_APP_PKCS7_DATA_INDEX = 7000; + constexpr int32_t TEST_VERSION_CODE = 1; + + const std::string TEST_ANS_TIME = "000000000000Z"; + const std::string TEST_FINGERPRINT = "7A1B38212FE86369DECE606D901CB66C7199CC1BDC4EFF52A86EFBFFB1B99A19"; + const std::string TEST_VERSION_NAME = "1.0.0"; + + constexpr char MINIHAPFILE[] = { + 80, 75, 3, 4, 10, 0, 0, 8, 0, 0, 0, 0, 33, + 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 18, 0, + 49, 46, 116, 120, 116, 85, 84, 9, 0, 6, 49, 40, 41, + 94, 49, 40, 41, 94, -2, -54, 0, 0, 0, 0, 0, + 0, 32, -117, 9, 0, 0, 48, -126, 9, -121, 6, + 9, 42, -122, 72, -122, -9, 13, 1, 7, 2, -96, -126, 9, + 120, 48, -126, 9, 116, 2, 1, 1, 49, 15, 48, + 13, 6, 9, 96, -122, 72, 1, 101, 3, 4, 2, 1, 5, 0, 48, + -126, 3, -6, 6, 9, 42, -122, 72, -122, -9, + 13, 1, 7, 1, -96, -126, 3, -21, 4, -126, 3, -25, 44, 0, + 0, 0, 40, 0, 0, 0, 1, 1, 0, 0, 32, 0, 0, 0, + -9, 111, -2, 4, -40, -83, -50, -26, 50, -78, -26, 18, + 101, 6, -30, -100, -26, -96, 17, -84, 15, 112, + 74, -114, -67, 67, -81, -49, 19, -28, -110, 48, -77, + 3, 0, 0, -81, 3, 0, 0, 48, -126, 3, -85, 48, + -126, 2, -109, -96, 3, 2, 1, 2, 2, 20, 122, 93, -87, + 110, 73, 90, -84, 41, -27, -29, -93, 93, 59, + 56, -105, -122, -20, -75, 10, -99, 48, 13, 6, 9, 42, + -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 48, + 101, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 78, 49, + 17, 48, 15, 6, 3, 85, 4, 8, 12, 8, 83, 104, + 101, 110, 122, 104, 101, 110, 49, 17, 48, 15, 6, 3, 85, + 4, 7, 12, 8, 83, 104, 101, 110, 122, 104, 101, + 110, 49, 15, 48, 13, 6, 3, 85, 4, 10, 12, 6, 72, 117, + 97, 119, 101, 105, 49, 15, 48, 13, 6, 3, 85, + 4, 11, 12, 6, 72, 117, 97, 119, 101, 105, 49, 14, 48, 12, + 6, 3, 85, 4, 3, 12, 5, 67, 104, 105, 110, 97, + 48, 30, 23, 13, 50, 48, 48, 49, 49, 48, 48, 55, 51, 54, + 53, 57, 90, 23, 13, 52, 55, 48, 53, 50, 56, + 48, 55, 51, 54, 53, 57, 90, 48, 101, 49, 11, 48, 9, 6, 3, + 85, 4, 6, 19, 2, 67, 78, 49, 17, 48, 15, 6, + 3, 85, 4, 8, 12, 8, 83, 104, 101, 110, 122, 104, 101, 110, + 49, 17, 48, 15, 6, 3, 85, 4, 7, 12, 8, 83, 104, + 101, 110, 122, 104, 101, 110, 49, 15, 48, 13, 6, 3, 85, + 4, 10, 12, 6, 72, 117, 97, 119, 101, 105, 49, + 15, 48, 13, 6, 3, 85, 4, 11, 12, 6, 72, 117, 97, 119, 101, + 105, 49, 14, 48, 12, 6, 3, 85, 4, 3, 12, 5, 67, + 104, 105, 110, 97, 48, -126, 1, 34, 48, 13, 6, 9, 42, + -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, + 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -17, -107, + -66, -22, 68, -42, -13, 116, 108, -23, 84, -30, + -19, 127, -45, -40, -60, -67, -53, -33, -114, 26, -11, + 104, 46, 103, 105, -78, -42, -32, 89, -70, 87, + 67, 32, 81, 35, 61, -121, 114, -83, 71, 8, -100, -35, 82, + -91, -3, 44, 95, -55, -118, 118, 19, 1, -50, 35, + -3, -123, 29, 103, 54, -16, -3, 36, -67, 54, 51, 2, 107, + 112, -9, -23, 40, -117, -84, -72, -7, 112, -92, + -127, 97, 122, -86, -126, 93, -37, -55, 17, 35, 118, -110, + -40, 27, -123, 2, 123, 102, 39, 117, -48, -71, + 103, -84, -105, -81, 28, -86, 118, -95, 63, 59, 107, 4, -71, + -30, 83, 39, 105, -112, -35, -15, 112, -52, -58, + -118, -114, 127, -54, -125, 46, 70, -95, -70, -11, 125, 49, + 116, -54, 34, 93, 34, 113, 119, -33, -26, -21, 13, + 69, -69, -33, -54, 87, 95, 62, -64, -125, -108, 4, -80, + -86, -11, 103, -121, 97, 122, -114, -88, -83, 59, + 119, 56, 22, 72, 35, -67, -67, -83, -60, 112, 105, 117, + 50, -19, 16, -53, 83, 103, -110, -107, 45, 5, 17, + -28, -97, -90, 59, 117, -88, 47, -86, -32, 17, -96, 111, + 88, -103, -60, -55, 20, -80, 44, 64, -48, 104, 94, + -118, 49, 72, -68, 42, 2, -9, 87, 17, -127, -43, -82, 85, + 70, 13, -98, 24, -55, -90, -51, 103, -65, -58, -97, + 52, -71, -85, -3, -118, -99, -84, 110, 2, 110, 56, -18, + -21, -109, -65, 67, 2, 3, 1, 0, 1, -93, 83, 48, 81, + 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 49, 59, -102, + -88, 25, -106, 97, 76, -15, -86, -88, -67, -85, -88, + -36, 8, -122, 3, 36, -51, 48, 31, 6, 3, 85, 29, 35, + 4, 24, 48, 22, -128, 20, 49, 59, -102, -88, 25, -106, + 97, 76, -15, -86, -88, -67, -85, -88, -36, 8, -122, + 3, 36, -51, 48, 15, 6, 3, 85, 29, 19, 1, 1, -1, 4, + 5, 48, 3, 1, 1, -1, 48, 13, 6, 9, 42, -122, 72, -122, + -9, 13, 1, 1, 11, 5, 0, 3, -126, 1, 1, 0, -33, 97, + 20, 104, -18, -45, -47, -109, 81, -55, -69, 34, -119, + -4, -78, 9, -101, 7, -42, 107, 41, -65, -115, -64, + -89, -38, 24, 103, -119, 22, -38, 60, 4, -2, 36, -94, + 103, 84, 89, 115, -93, -67, -2, -41, 124, 53, 6, 37, + 116, -30, 49, -78, 83, -110, 50, 26, 120, -58, -11, + 91, -119, -121, 87, 99, 74, -71, 23, -113, -63, -14, + -68, -44, 17, -109, 24, -94, -26, -60, 32, -8, 77, 29, + 113, 42, -94, -9, -92, -71, -57, -41, 24, -62, 2, -3, + 53, -98, -99, -32, -1, 120, -17, 26, 32, -2, -59, 85, + -22, 23, -79, 9, -72, 116, 67, 55, 118, 12, 7, 79, -83, + -103, -66, 123, -55, 5, -29, -53, 92, -95, 99, 4, -23, + 26, -121, -22, 69, 89, 7, -109, -54, -76, -59, 0, 54, + -24, -58, -42, 14, -51, -121, -14, 97, 68, -70, -122, -30, + -113, 43, -102, -34, 96, 38, -8, -14, 65, 83, -124, -104, + 27, 69, -42, -69, -30, -108, -76, -1, -47, -117, -2, + 108, 9, 61, 79, 59, 67, -18, -126, -117, 36, -14, -102, + 23, 55, -27, 97, -47, -24, 16, 102, 60, 88, 47, -59, 63, + -57, 46, -77, -112, -88, -93, -60, -120, 101, -3, 117, + -102, -113, -10, -61, -69, -122, 6, 96, -78, 28, -111, 1, + -88, -60, -123, -39, 28, -28, 40, -28, -59, -97, 77, + -45, -9, -113, 120, 84, 58, 105, 24, -35, -113, -97, 115, + -107, -3, 121, 56, -60, 75, -60, -96, -126, 3, -81, + 48, -126, 3, -85, 48, -126, 2, -109, -96, 3, 2, 1, 2, 2, + 20, 122, 93, -87, 110, 73, 90, -84, 41, -27, -29, -93, + 93, 59, 56, -105, -122, -20, -75, 10, -99, 48, 13, 6, + 9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 48, 101, + 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 78, 49, 17, + 48, 15, 6, 3, 85, 4, 8, 12, 8, 83, 104, 101, 110, 122, + 104, 101, 110, 49, 17, 48, 15, 6, 3, 85, 4, 7, 12, 8, + 83, 104, 101, 110, 122, 104, 101, 110, 49, 15, 48, 13, + 6, 3, 85, 4, 10, 12, 6, 72, 117, 97, 119, 101, 105, 49, + 15, 48, 13, 6, 3, 85, 4, 11, 12, 6, 72, 117, 97, 119, + 101, 105, 49, 14, 48, 12, 6, 3, 85, 4, 3, 12, 5, 67, 104, + 105, 110, 97, 48, 30, 23, 13, 50, 48, 48, 49, 49, 48, + 48, 55, 51, 54, 53, 57, 90, 23, 13, 52, 55, 48, 53, 50, + 56, 48, 55, 51, 54, 53, 57, 90, 48, 101, 49, 11, 48, + 9, 6, 3, 85, 4, 6, 19, 2, 67, 78, 49, 17, 48, 15, 6, 3, + 85, 4, 8, 12, 8, 83, 104, 101, 110, 122, 104, 101, 110, + 49, 17, 48, 15, 6, 3, 85, 4, 7, 12, 8, 83, 104, 101, + 110, 122, 104, 101, 110, 49, 15, 48, 13, 6, 3, 85, 4, + 10, 12, 6, 72, 117, 97, 119, 101, 105, 49, 15, 48, 13, + 6, 3, 85, 4, 11, 12, 6, 72, 117, 97, 119, 101, 105, 49, + 14, 48, 12, 6, 3, 85, 4, 3, 12, 5, 67, 104, 105, 110, + 97, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, + -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, + 10, 2, -126, 1, 1, 0, -17, -107, -66, -22, 68, -42, -13, + 116, 108, -23, 84, -30, -19, 127, -45, -40, -60, -67, + -53, -33, -114, 26, -11, 104, 46, 103, 105, -78, -42, + -32, 89, -70, 87, 67, 32, 81, 35, 61, -121, 114, -83, 71, + 8, -100, -35, 82, -91, -3, 44, 95, -55, -118, 118, 19, + 1, -50, 35, -3, -123, 29, 103, 54, -16, -3, 36, -67, 54, + 51, 2, 107, 112, -9, -23, 40, -117, -84, -72, -7, 112, + -92, -127, 97, 122, -86, -126, 93, -37, -55, 17, 35, 118, + -110, -40, 27, -123, 2, 123, 102, 39, 117, -48, -71, + 103, -84, -105, -81, 28, -86, 118, -95, 63, 59, 107, 4, + -71, -30, 83, 39, 105, -112, -35, -15, 112, -52, -58, + -118, -114, 127, -54, -125, 46, 70, -95, -70, -11, 125, + 49, 116, -54, 34, 93, 34, 113, 119, -33, -26, -21, 13, + 69, -69, -33, -54, 87, 95, 62, -64, -125, -108, 4, -80, + -86, -11, 103, -121, 97, 122, -114, -88, -83, 59, 119, 56, + 22, 72, 35, -67, -67, -83, -60, 112, 105, 117, 50, + -19, 16, -53, 83, 103, -110, -107, 45, 5, 17, -28, -97, + -90, 59, 117, -88, 47, -86, -32, 17, -96, 111, 88, + -103, -60, -55, 20, -80, 44, 64, -48, 104, 94, -118, 49, + 72, -68, 42, 2, -9, 87, 17, -127, -43, -82, 85, 70, + 13, -98, 24, -55, -90, -51, 103, -65, -58, -97, 52, -71, + -85, -3, -118, -99, -84, 110, 2, 110, 56, -18, -21, + -109, -65, 67, 2, 3, 1, 0, 1, -93, 83, 48, 81, 48, 29, 6, + 3, 85, 29, 14, 4, 22, 4, 20, 49, 59, -102, -88, 25, + -106, 97, 76, -15, -86, -88, -67, -85, -88, -36, 8, -122, + 3, 36, -51, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, + -128, 20, 49, 59, -102, -88, 25, -106, 97, 76, -15, -86, + -88, -67, -85, -88, -36, 8, -122, 3, 36, -51, 48, 15, + 6, 3, 85, 29, 19, 1, 1, -1, 4, 5, 48, 3, 1, 1, -1, 48, + 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 3, + -126, 1, 1, 0, -33, 97, 20, 104, -18, -45, -47, -109, + 81, -55, -69, 34, -119, -4, -78, 9, -101, 7, -42, 107, 41, + -65, -115, -64, -89, -38, 24, 103, -119, 22, -38, 60, + 4, -2, 36, -94, 103, 84, 89, 115, -93, -67, -2, -41, 124, + 53, 6, 37, 116, -30, 49, -78, 83, -110, 50, 26, 120, + -58, -11, 91, -119, -121, 87, 99, 74, -71, 23, -113, -63, + -14, -68, -44, 17, -109, 24, -94, -26, -60, 32, -8, 77, + 29, 113, 42, -94, -9, -92, -71, -57, -41, 24, -62, 2, + -3, 53, -98, -99, -32, -1, 120, -17, 26, 32, -2, -59, + 85, -22, 23, -79, 9, -72, 116, 67, 55, 118, 12, 7, 79, + -83, -103, -66, 123, -55, 5, -29, -53, 92, -95, 99, + 4, -23, 26, -121, -22, 69, 89, 7, -109, -54, -76, -59, 0, + 54, -24, -58, -42, 14, -51, -121, -14, 97, 68, -70, + -122, -30, -113, 43, -102, -34, 96, 38, -8, -14, 65, 83, + -124, -104, 27, 69, -42, -69, -30, -108, -76, -1, + -47, -117, -2, 108, 9, 61, 79, 59, 67, -18, -126, -117, 36, + -14, -102, 23, 55, -27, 97, -47, -24, 16, 102, 60, + 88, 47, -59, 63, -57, 46, -77, -112, -88, -93, -60, -120, + 101, -3, 117, -102, -113, -10, -61, -69, -122, 6, + 96, -78, 28, -111, 1, -88, -60, -123, -39, 28, -28, 40, -28, + -59, -97, 77, -45, -9, -113, 120, 84, 58, 105, 24, + -35, -113, -97, 115, -107, -3, 121, 56, -60, 75, -60, 49, + -126, 1, -85, 48, -126, 1, -89, 2, 1, 1, 48, 125, + 48, 101, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 78, 49, + 17, 48, 15, 6, 3, 85, 4, 8, 19, 8, 83, 104, 101, + 110, 122, 104, 101, 110, 49, 17, 48, 15, 6, 3, 85, 4, 7, 19, + 8, 83, 104, 101, 110, 122, 104, 101, 110, 49, 15, + 48, 13, 6, 3, 85, 4, 10, 19, 6, 72, 117, 97, 119, 101, 105, + 49, 15, 48, 13, 6, 3, 85, 4, 11, 19, 6, 72, 117, + 97, 119, 101, 105, 49, 14, 48, 12, 6, 3, 85, 4, 3, 19, 5, 67, + 104, 105, 110, 97, 2, 20, 122, 93, -87, 110, 73, + 90, -84, 41, -27, -29, -93, 93, 59, 56, -105, -122, -20, -75, + 10, -99, 48, 13, 6, 9, 96, -122, 72, 1, 101, 3, 4, + 2, 1, 5, 0, 48, 14, 6, 10, 42, -122, 72, -122, -9, 13, 1, 1, + -113, 95, 5, 0, 4, -126, 1, 0, 10, -19, -16, -126, + -10, -94, 59, 95, 83, 115, -33, 23, 97, -30, -91, -114, 59, + 93, 97, -15, -12, 60, 39, -53, 28, -25, -6, 32, + -48, 120, -97, 64, 125, 23, -9, 53, 104, -122, 18, -5, 122, 126, + 19, -80, 53, 14, 70, 21, 63, -99, -76, -52, -2, + 103, -114, 95, -21, -60, -49, -42, -81, 58, -16, -23, 19, 108, + -30, -32, -12, -103, -107, 25, 33, 85, 61, 2, 30, 17, 0, 117, + -63, -12, -112, 60, 12, 58, 114, 126, 24, -25, + -123, 32, 19, 99, 54, -2, -78, -23, 126, 61, 46, 61, 4, -114, + -36, 53, -1, -71, 22, -10, 127, 63, -10, -73, + 51, -74, -8, 80, -34, 63, 57, -17, 106, 100, -109, -27, -30, + 46, 35, -85, -91, -20, -72, -128, 22, -97, 107, + 101, 21, 63, -36, 50, -69, 99, -10, -88, 52, 19, -115, 67, 53, + 53, 30, -107, 122, -123, -118, -56, 80, -50, + -58, 30, 110, -109, -14, 50, 18, 2, -46, 102, 64, 6, -71, 25, + 71, -36, 95, -121, -7, -11, 90, 18, 20, 96, + -6, -61, 59, 90, -1, 64, -111, 73, 82, 50, -61, 111, 41, -29, + -102, 100, -100, -73, 42, -88, 21, -64, -122, + 8, 117, -65, 47, 86, -55, -37, -14, 20, 60, 91, -22, -101, 90, + -18, 10, -101, -40, 64, -110, -120, 119, -7, + -41, -109, 82, -2, -122, 72, 74, 44, 54, -48, -51, -52, -37, + -56, -10, -8, 78, 64, -105, 59, -71, 54, -25, + -9, 105, 29, -95, 0, 1, 0, 0, 0, -77, 9, 0, 0, 0, 0, 0, 0, 72, + 65, 80, 32, 83, 105, 103, 32, 66, 108, 111, + 99, 107, 32, 52, 50, 1, 0, 0, 0, 80, 75, 1, 2, 10, 0, 10, 0, + 0, 8, 0, 0, 0, 0, 33, 58, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 49, 46, 116, 120, 116, 85, 84, 1, 0, 6, + -2, -54, 0, 0, 0, 80, 75, 5, 6, 0, 0, 0, 0, 1, 0, 1, 0, 61, + 0, 0, 0, -24, 9, 0, 0, 0, 0, -33, -26, -21, 13, 69, + -69, -33, -54, 87, 95, 62, -64, -125, -108, 4, -80, -86, -11, + 103, -121, 97, 122, -114, -88, -83, 59, 119, 56, + 22, 72, 35, -67, -67, -83, -60, 112, 105, 117, 50, -19, 16, + -53, 83, 103, -110, -107, 45, 5, 17, -28, -97, -90, + 59, 117, -88, 47, -86, -32, 17, -96, 111, 88, -103, -60, -55, + 20, -80, 44, 64, -48, 104, 94, -118, 49, 72, -68, + 42, 2, -9, 87, 17, -127, -43, -82, 85, 70, 13, -98, 24, -55, + -90, -51, 103, -65, -58, -97, 52, -71, -85, -3, + -118, -99, -84, 110, 2, 110, 56, -18, -21, -109, -65, 67, 2, + 3, 1, 0, 1, -93, 83, 48, 81, 48, 29, 6, 3, 85, 29, + 14, 4, 22, 4, 20, 49, 59, -102, -88, 25, -106, 97, 76, -15, + -86, -88, -67, -85, -88, -36, 8, -122, 3, 36, -51, + 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, -128, 20, 49, 59, + -102, -88, 25, -106, 97, 76, -15, -86, -88, -67, -85, + -88, -36, 8, -122, 3, 36, -51, 48, 15, 6, 3, 85, 29, 19, 1, + 1, -1, 4, 5, 48, 3, 1, 1, -1, 48, 13, 6, 9, 42, -122, + 72, -122, -9, 13, 1, 1, 11, 5, 0, 3, -126, 1, 1, 0, -33, 97, + 20, 104, -18, -45, -47, -109, 81, -55, -69, 34, -119, + -4, -78, 9, -101, 7, -42, 107, 41, -65, -115, -64, -89, -38, + 24, 103, -119, 22, -38, 60, 4, -2, 36, -94, 103, 84, + 89, 115, -93, -67, -2, -41, 124, 53, 6, 37, 116, -30, 49, + -78, 83, -110, 50, 26, 120, -58, -11, 91, -119, -121, + 87, 99, 74, -71, 23, -113, -63, -14, -68, -44, 17, -109, 24, + -94, -26, -60, 32, -8, 77, 29, 113, 42, -94, -9, + -92, -71, -57, -41, 24, -62, 2, -3, 53, -98, -99, -32, -1, + 120, -17, 26, 32, -2, -59, 85, -22, 23, -79, 9, -72, + 116, 67, 55, 118, 12, 7, 79, -83, -103, -66, 123, -55, 5, + -29, -53, 92, -95, 99, 4, -23, 26, -121, -22, 69, 89, + 7, -109, -54, -76, -59, 0, 54, -24, -58, -42, 14, -51, -121, + -14, 97, 68, -70, -122, -30, -113, 43, -102, -34, + 96, 38, -8, -14, 65, 83, -124, -104, 27, 69, -42, -69, -30, + -108, -76, -1, -47, -117, -2, 108, 9, 61, 79, 59, + 67, -18, -126, -117, 36, -14, -102, 23, 55, -27, 97, -47, + -24, 16, 102, 60, 88, 47, -59, 63, -57, 46, -77, + -112, -88, -93, -60, -120, 101, -3, 117, -102, -113, -10, + -61, -69, -122, 6, 96, -78, 28, -111, 1, -88, -60, + -123, -39, 28 + }; + + const std::string ROOTCERT = "-----BEGIN CERTIFICATE-----\n" + "MIICGjCCAaGgAwIBAgIIShhpn519jNAwCgYIKoZIzj0EAwMwUzELMAkGA1UEBhMC\n" + "Q04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEeMBwGA1UE\n" + "AwwVSHVhd2VpIENCRyBSb290IENBIEcyMB4XDTIwMDMxNjAzMDQzOVoXDTQ5MDMx\n" + "NjAzMDQzOVowUzELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UE\n" + "CwwKSHVhd2VpIENCRzEeMBwGA1UEAwwVSHVhd2VpIENCRyBSb290IENBIEcyMHYw\n" + "EAYHKoZIzj0CAQYFK4EEACIDYgAEWidkGnDSOw3/HE2y2GHl+fpWBIa5S+IlnNrs\n" + "GUvwC1I2QWvtqCHWmwFlFK95zKXiM8s9yV3VVXh7ivN8ZJO3SC5N1TCrvB2lpHMB\n" + "wcz4DA0kgHCMm/wDec6kOHx1xvCRo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T\n" + "AQH/BAUwAwEB/zAdBgNVHQ4EFgQUo45a9Vq8cYwqaiVyfkiS4pLcIAAwCgYIKoZI\n" + "zj0EAwMDZwAwZAIwMypeB7P0IbY7c6gpWcClhRznOJFj8uavrNu2PIoz9KIqr3jn\n" + "BlBHJs0myI7ntYpEAjBbm8eDMZY5zq5iMZUC6H7UzYSix4Uy1YlsLVV738PtKP9h\n" + "FTjgDHctXJlC5L7+ZDY=\n-----END CERTIFICATE-----\n"; + + const std::string SOFT_CA_CERT = "-----BEGIN CERTIFICATE-----\n" + "MIIDADCCAoegAwIBAgIIJGDixWQS3MkwCgYIKoZIzj0EAwMwUzELMAkGA1UEBhMC\n" + "Q04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEeMBwGA1UE\n" + "AwwVSHVhd2VpIENCRyBSb290IENBIEcyMB4XDTIwMDMxNjEyMzIzOVoXDTQwMDMx\n" + "NjEyMzIzOVowZDELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UE\n" + "CwwKSHVhd2VpIENCRzEvMC0GA1UEAwwmSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWdu\n" + "aW5nIFNlcnZpY2UgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASsEz7cwYkzFh9b\n" + "xIwKfXx5qHGjl5WITy0teGnNWqv+jYCceeixHqErvK7YRn2hVPIqhRqKWeANHZUK\n" + "G0qxi+NIpmSmQS8/63CLz1QAcxfv2Xl3/V82dF0v9lm16ehMsN+jggEVMIIBETAf\n" + "BgNVHSMEGDAWgBSjjlr1WrxxjCpqJXJ+SJLiktwgADAdBgNVHQ4EFgQU+vX3viBW\n" + "XV3U2m3xFBU8HQnbsjQwDwYDVR0TAQH/BAUwAwEB/zBGBgNVHSAEPzA9MDsGBFUd\n" + "IAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9j\n" + "cGtpL2NwczAOBgNVHQ8BAf8EBAMCAQYwZgYDVR0fBF8wXTBboFmgV4ZVaHR0cDov\n" + "L2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24u\n" + "Y3JsP2NlcnR5cGU9MTAmL3Jvb3RfZzJfY3JsLmNybDAKBggqhkjOPQQDAwNnADBk\n" + "AjBrAQQxUlNgqhYkcEm5eksnPxDkPJSY/qNd2BDgbvEydiLwPSvB7Z9lipxz8ikZ\n" + "EeUCMGppWcaV//SIG1y5tEwthLwWeEaF613vUILWQLir8+CA3RZGsRBqtE8xSqfz\n" + "yafLYQ==\n-----END CERTIFICATE-----\n"; + + const std::string UAT_SOFT_SIGN_CA = "-----BEGIN CERTIFICATE-----\n" + "MIIDCjCCApGgAwIBAgIIWbEqGvOqT10wCgYIKoZIzj0EAwMwWDELMAkGA1UEBhMC\n" + "Q04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEjMCEGA1UE\n" + "AwwaSHVhd2VpIENCRyBSb290IENBIEcyIFRlc3QwHhcNMjAwMzEzMTE1ODI4WhcN\n" + "NDAwMzEzMTE1ODI4WjBpMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMw\n" + "EQYDVQQLDApIdWF3ZWkgQ0JHMTQwMgYDVQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJl\n" + "IFNpZ25pbmcgU2VydmljZSBDQSBUZXN0MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE\n" + "ukPDS3s0TpYa/lANCTc7eX8fdGGjMPUbvso3TtlBvzdm0XDNTdVtZq3XVOfefgpE\n" + "OaC/JSoXgiNHkeEQ4XSSm0d7MbeoYEyoEKWa1G2/SOQxbVNqKLexxlGMjMuOLdMb\n" + "o4IBFTCCAREwHwYDVR0jBBgwFoAUaV3AWPH1POb9CkDxHWBz3Bx4xsUwHQYDVR0O\n" + "BBYEFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMA8GA1UdEwEB/wQFMAMBAf8wRgYDVR0g\n" + "BD8wPTA7BgRVHSAAMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly9jcGtpLWNhd2ViLmh1\n" + "YXdlaS5jb20vY3BraS9jcHMwDgYDVR0PAQH/BAQDAgEGMGYGA1UdHwRfMF0wW6BZ\n" + "oFeGVWh0dHA6Ly9jcGtpLWNhd2ViLmh1YXdlaS5jb20vY3BraS9zZXJ2bGV0L2Ny\n" + "bEZpbGVEb3duLmNybD9jZXJ0eXBlPTEwJi9yb290X2cyX2NybC5jcmwwCgYIKoZI\n" + "zj0EAwMDZwAwZAIwF7PjIuOODhpDhzpw2cqV/xbLNJ5CExFJHxcy1D0bHljE5xTt\n" + "csIN40Ma6aEi3MJQAjAHQLfAzZvMmreYwKnc2bHXlS68roSRvNTvrUKp3Lcp92nK\n" + "MzieiyKHlWKEgrUjnKc=\n-----END CERTIFICATE-----\n"; + + const std::string ECC_TEST_KEY = "-----BEGIN EC PARAMETERS-----\n" + "BggqhkjOPQMBBw==\n-----END EC PARAMETERS-----\n" + "-----BEGIN EC PRIVATE KEY-----\n" + "MHcCAQEEIPPNgGEGZA97B5g54d0D8kDBIOYS1LDldMGRf1aifZauoAoGCCqGSM49\n" + "AwEHoUQDQgAE4BehGAUU+XDXxtlQ+7Ct4sILmYL7CligKCSWbRw0YsBp4F20626u\n" + "8+T9xNlH7pGc5moba0EKy003FH1sVbtEtg==\n-----END EC PRIVATE KEY-----\n"; + + const std::string ECC_TEST_CERT = "-----BEGIN CERTIFICATE-----\n" + "MIIBkjCCATgCCQCncuWaDED8pjAKBggqhkjOPQQDAjBQMQswCQYDVQQGEwJDTjEM\n" + "MAoGA1UECgwDQ0JHMRwwGgYDVQQLDBNDQkcgSE9TIHNpZ25lZCBUZWFtMRUwEwYD\n" + "VQQDDAxIT1MgdW5pdHRlc3QwIBcNMjAwNDI3MDQwNDQ2WhgPMjEyMDA0MDMwNDA0\n" + "NDZaMFAxCzAJBgNVBAYTAkNOMQwwCgYDVQQKDANDQkcxHDAaBgNVBAsME0NCRyBI\n" + "T1Mgc2lnbmVkIFRlYW0xFTATBgNVBAMMDEhPUyB1bml0dGVzdDBZMBMGByqGSM49\n" + "AgEGCCqGSM49AwEHA0IABOAXoRgFFPlw18bZUPuwreLCC5mC+wpYoCgklm0cNGLA\n" + "aeBdtOturvPk/cTZR+6RnOZqG2tBCstNNxR9bFW7RLYwCgYIKoZIzj0EAwIDSAAw\n" + "RQIhALYbUacS0XrpPzVatHMpHnCmYgsi28hf1UTBNk+iPG/9AiBGh25CpFoDmGqb\n" + "fz5ebYSvkSe1KNtVHUTprMBQeWaB0A==\n" + "-----END CERTIFICATE-----\n"; + + const std::string APP_SIGN_TEST = "-----BEGIN CERTIFICATE-----\n" + "MIIDHjCCAqWgAwIBAgIISwRVtFpC3o0wCgYIKoZIzj0EAwMwaTELMAkGA1UEBhMC\n" + "Q04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzE0MDIGA1UE\n" + "AwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0EgVGVzdDAe\n" + "Fw0yMDA0MjcxMjQyMjJaFw0yMzA0MjcxMjQyMjJaMGUxCzAJBgNVBAYTAkNOMRMw\n" + "EQYDVQQKDApIdWF3ZWkgQ0JHMR0wGwYDVQQLDBRIT1MgRGV2ZWxvcG1lbnQgVGVh\n" + "bTEiMCAGA1UEAwwZSE9TIEFwcGxpY2F0aW9uIFByb3Zpc2lvbjBZMBMGByqGSM49\n" + "AgEGCCqGSM49AwEHA0IABNrFL0TBoPUBcwLCT+jzlDatUBcxv8l4/3xirQkSgPq8\n" + "ZTsrVChJE51ZotHcDN8QOtLfEJZC92ev+hAqksltfDKjggE5MIIBNTAfBgNVHSME\n" + "GDAWgBR7uEdSp/HMWJ77VezhLXEOB5ovJjAdBgNVHQ4EFgQU80TcTfc+VizmL+/V\n" + "0fFAXwsh2vgwRgYDVR0gBD8wPTA7BgRVHSAAMDMwMQYIKwYBBQUHAgEWJWh0dHA6\n" + "Ly9jcGtpLWNhd2ViLmh1YXdlaS5jb20vY3BraS9jcHMwDgYDVR0PAQH/BAQDAgeA\n" + "MGwGA1UdHwRlMGMwYaBfoF2GW2h0dHA6Ly9jcGtpLWNhd2ViLmh1YXdlaS5jb20v\n" + "Y3BraS9zZXJ2bGV0L2NybEZpbGVEb3duLmNybD9jZXJ0eXBlPTE0Ji9zb2Z0X3Np\n" + "Z25fc3J2X2NybC5jcmwwEwYDVR0lBAwwCgYIKwYBBQUHAwMwGAYMKwYBBAGPWwKC\n" + "eAECBAgwBgIBAQoBADAKBggqhkjOPQQDAwNnADBkAjAqTxz2Z9F1HaPVoBD2e3fL\n" + "VXWASZx+YGFMpN0pyCGScDQr4zj+MXuNKewv13M+yaICMHCemT39agd/dHF+sorJ\n" + "Gz6qDn/r0hmkeHoCzUwA0Dwq/417Re81BbZvHHv7yPO7jw==\n" + "-----END CERTIFICATE-----\n"; + + const std::string BASE64_NOT_URL_SAFE_CERT = + "MIIDLDCCArOgAwIBAgIIRBvbxEi6hzwwCgYIKoZIzj0EAwMwaTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwK" + "SHVhd2VpIENCRzE0MDIGA1UEAwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0EgVGVzdDAeFw0yMDA0MjkxMTUw" + "NTlaFw0yMzA0MjkxMTUwNTlaMHMxCzAJBgNVBAYTAkNOMRMwEQYDVQQKDApIdWF3ZWkgQ0JHMR0wGwYDVQQLDBRIT1MgRGV2ZWxvcG1l" + "bnQgVGVhbTEwMC4GA1UEAwwnSE9TIEFwcGxpY2F0aW9uIFByb3Zpc2lvbiBQcm9maWxlIERlYnVnMFkwEwYHKoZIzj0CAQYIKoZIzj0D" + "AQcDQgAEcS/2lY4sb1EHegznTHYurPL4isgkq/AS4r8TqTnAkP2GI3N/e/+AX9MvdNQrCdNObSp/jXikxnU/Ng/m/pL0UaOCATkwggE1" + "MB8GA1UdIwQYMBaAFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMB0GA1UdDgQWBBSOm2cVJTbTlMJF+CJer6HVFCC1iDBGBgNVHSAEPzA9MDsG" + "BFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCB4AwbAYD" + "VR0fBGUwYzBhoF+gXYZbaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2NlcnR5" + "cGU9MTQmL3NvZnRfc2lnbl9zcnZfY3JsLmNybDATBgNVHSUEDDAKBggrBgEFBQcDAzAYBgwrBgEEAY9bAoJ4AQMECDAGAgEBCgEBMAoG" + "CCqGSM49BAMDA2cAMGQCMBs+JL4mtRpANjBvrv4zPQr/dE9Fk+eS/rj38qwkMM2CyDdoo0akI8HQ+fNGJP6JKwIwJqNjupjVsQ60b2tQ" + "AQSLisHmegx5s7USRD3dlpcUEGnepWMop1r8D4Ko8jHsKOX7"; + + const std::string BASE64_CRL = + "MIIBLTCBswIBATAKBggqhkjOPQQDAzBTMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMR4w" + "HAYDVQQDDBVIdWF3ZWkgQ0JHIFJvb3QgQ0EgRzIXDTIwMDMyNjE2NDkwNVoXDTMwMDMyNTAxMzgzM1qgLzAtMB8GA1UdIwQYMBaAFKOO" + "WvVavHGMKmolcn5IkuKS3CAAMAoGA1UdFAQDAgEAMAoGCCqGSM49BAMDA2kAMGYCMQCuQOz7IvwENw/Mf1ytoXT5AHiknrrOaw/dqTuZ" + "RR0wcxP5IJqI1I3Bg5WNbUmTomMCMQDIs23wc9iLgvuDOmMQia4srWunydbbslpFNfV3SIIhtyWDIPVch7RTf/s92HqnrVw="; + + } // SignatureTools +} // OHOS +#endif // HAPVERIFY_TEST_CONST_H diff --git a/hapsigntool_cpp/test/unittest/hapVerify/test_hap_file_data.h b/hapsigntool_cpp/test/unittest/hapVerify/test_hap_file_data.h new file mode 100644 index 0000000000000000000000000000000000000000..aa75bd15a25ab57d8ac81262d5e05b24003b0bad --- /dev/null +++ b/hapsigntool_cpp/test/unittest/hapVerify/test_hap_file_data.h @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef TEST_HAP_FILE_DATA_H +#define TEST_HAP_FILE_DATA_H + +#include + +namespace OHOS { + namespace SignatureTools { + + const std::string HAP_FILE_ECC_SIGN_BASE64 = + "UEsDBBQACAgIAAAAIToAAAAAAAAAAAAAAAAFAAQAMS50eHT+ygAAMzQEAFBLBwh3FVrWBAAAAAIAAAACAAAg2hMAABgAAAAAAAAgmA0AAP" + "ITAAAwghPWBgkqhkiG9w0BBwKgghPHMIITwwIBATEPMA0GCWCGSAFlAwQCAQUAMIIGhAYJKoZIhvcNAQcBoIIGdQSCBnF7InZlcnNpb24t" + "bmFtZSI6IjEuMC4wIiwidmVyc2lvbi1jb2RlIjoxLCJhcHAtZGlzdHJpYnV0aW9uLXR5cGUiOiJvc19pbnRlZ3JhdGlvbiIsInV1aWQiOi" + "I5OEE3Rjc3Mi01ODRCLTRFRDctOTczRC1CMDg4M0YwRjE5RUYiLCJ2YWxpZGl0eSI6eyJub3QtYmVmb3JlIjoxNTg2NDIyNzQzLCJub3Qt" + "YWZ0ZXIiOjI1MzU2OTk4NDN9LCJ0eXBlIjoicmVsZWFzZSIsImJ1bmRsZS1pbmZvIjp7ImRldmVsb3Blci1pZCI6Inpob25neGlhbmciLC" + "JkaXN0cmlidXRpb24tY2VydGlmaWNhdGUiOiItLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS1cbk1JSUREVENDQXBPZ0F3SUJBZ0lJYmZG" + "eTVTaXR3ME13Q2dZSUtvWkl6ajBFQXdNd2FURUxNQWtHQTFVRUJoTUNcblEwNHhEekFOQmdOVkJBb01Ca2gxWVhkbGFURVRNQkVHQTFVRU" + "N3d0tTSFZoZDJWcElFTkNSekUwTURJR0ExVUVcbkF3d3JTSFZoZDJWcElFTkNSeUJUYjJaMGQyRnlaU0JUYVdkdWFXNW5JRk5sY25acFky" + "VWdRMEVnVkdWemREQWVcbkZ3MHlNREEwTWpnd016SXlNRGRhRncwek1EQTBNamd3TXpJeU1EZGFNRkF4Q3pBSkJnTlZCQVlUQWtOT01ROH" + "dcbkRRWURWUVFLREFaSWRXRjNaV2t4RXpBUkJnTlZCQXNNQ2toMVlYZGxhU0JEUWtjeEd6QVpCZ05WQkFNTUVucG9cbmIyNW5lR2xoYm1k" + "ZmNtVnNaV0Z6WlRCMk1CQUdCeXFHU000OUFnRUdCU3VCQkFBaUEySUFCRzEzc1J3RjJVeXVcblVTdFpoblJLV3ZKMkxHZGdOTGxEMk54cj" + "RCRWtBUnVQVnB2aDBvMGV0UmpxSEFjZ1k3K0c1dmpobytLL01zSHlcbjVPeHJ3clBaenFmT2dsSjlvL2ZNakJNR2I2VUVzWS9ncE5xd1Vi" + "WjNEdU5uZmt6VFo2QldMcU9DQVI4d2dnRWJcbk1COEdBMVVkSXdRWU1CYUFGSHU0UjFLbjhjeFludnRWN09FdGNRNEhtaThtTUIwR0ExVW" + "REZ1FXQkJTcXAwa3Fcbi9UQ29tKzc2R2YrNzBGcjROYXAyNHpCR0JnTlZIU0FFUHpBOU1Ec0dCRlVkSUFBd016QXhCZ2dyQmdFRkJRY0Nc" + "bkFSWWxhSFIwY0RvdkwyTndhMmt0WTJGM1pXSXVhSFZoZDJWcExtTnZiUzlqY0d0cEwyTndjekFPQmdOVkhROEJcbkFmOEVCQU1DQjRBd2" + "JBWURWUjBmQkdVd1l6QmhvRitnWFlaYmFIUjBjRG92TDJOd2Eya3RZMkYzWldJdWFIVmhcbmQyVnBMbU52YlM5amNHdHBMM05sY25ac1pY" + "UXZZM0pzUm1sc1pVUnZkMjR1WTNKc1AyTmxjblI1Y0dVOU1UUW1cbkwzTnZablJmYzJsbmJsOXpjblpmWTNKc0xtTnliREFUQmdOVkhTVU" + "VEREFLQmdnckJnRUZCUWNEQXpBS0JnZ3Fcbmhrak9QUVFEQXdOb0FEQmxBakE1Y2VicEo2alQzL1A5b3N0S2V6UGl3cGRNODUvTnRneWp3" + "QU4wQi82SUZIYlZcblNDWllMcStZcXNQYUt2SXh4RkVDTVFESUgxeDZUTVdwZmJNV2M4N0R5OTZ4Q0hLbEtsU0tkalM2dXZML210N2Zcbk" + "YzT3o1QXIxZFhuVDRBSi9RYzFsUHNrPVxuLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLVxuIiwiYnVuZGxlLW5hbWUiOiJjb20uaHVhd2Vp" + "Lmhpd29ybGQuaGlkZW1vIiwiYXBwLWZlYXR1cmUiOiJob3Nfbm9ybWFsX2FwcCJ9LCJwZXJtaXNzaW9ucyI6eyJyZXN0cmljdGVkLXBlcm" + "1pc3Npb25zIjpbImhhcm1vbnlvcy5wZXJtaXNzaW9uLkFOU1dFUl9QSE9ORV9DQUxMIiwiQkJCIl0sInJlc3RyaWN0ZWQtY2FwYWJpbGl0" + "aWVzIjpbIkNDQyIsImRkZCJdfSwiaXNzdWVyIjoiSHVhd2VpIEFwcHMgU3RvcmUifaCCBj4wggMKMIICkaADAgECAghZsSoa86pPXTAKBg" + "gqhkjOPQQDAzBYMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMSMwIQYDVQQDDBpIdWF3ZWkg" + "Q0JHIFJvb3QgQ0EgRzIgVGVzdDAeFw0yMDAzMTMxMTU4MjhaFw00MDAzMTMxMTU4MjhaMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdW" + "F3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3Qw" + "djAQBgcqhkjOPQIBBgUrgQQAIgNiAAS6Q8NLezROlhr+UA0JNzt5fx90YaMw9Ru+yjdO2UG/N2bRcM1N1W1mrddU595+CkQ5oL8lKheCI0" + "eR4RDhdJKbR3sxt6hgTKgQpZrUbb9I5DFtU2oot7HGUYyMy44t0xujggEVMIIBETAfBgNVHSMEGDAWgBRpXcBY8fU85v0KQPEdYHPcHHjG" + "xTAdBgNVHQ4EFgQUe7hHUqfxzFie+1Xs4S1xDgeaLyYwDwYDVR0TAQH/BAUwAwEB/zBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQ" + "cCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCAQYwZgYDVR0fBF8wXTBboFmgV4ZVaHR0" + "cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2NlcnR5cGU9MTAmL3Jvb3RfZzJfY3JsLm" + "NybDAKBggqhkjOPQQDAwNnADBkAjAXs+Mi444OGkOHOnDZypX/Fss0nkITEUkfFzLUPRseWMTnFO1ywg3jQxrpoSLcwlACMAdAt8DNm8ya" + "t5jAqdzZsdeVLryuhJG81O+tQqnctyn3acozOJ6LIoeVYoSCtSOcpzCCAywwggKxoAMCAQICCC0zffQhq5r9MAoGCCqGSM49BAMDMGkxCz" + "AJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUg" + "U2lnbmluZyBTZXJ2aWNlIENBIFRlc3QwHhcNMjAwNTA2MDcwMDE5WhcNMjMwNTA2MDcwMDE5WjBxMQswCQYDVQQGEwJDTjETMBEGA1UECg" + "wKSHVhd2VpIENCRzEdMBsGA1UECwwUSE9TIERldmVsb3BtZW50IFRlYW0xLjAsBgNVBAMMJUhPUyBBcHBsaWNhdGlvbiBQcm92aXNpb24g" + "UHJvZmlsZSBEZXYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARn9+yWcHv7JRXSe4bPNE6jQnMaPwRAwJOXn3hGvMoPJPCQKg+hYIoxU/" + "XNOBxnfNbneRDaFToQGJuEAK8ljAWvo4IBOTCCATUwHwYDVR0jBBgwFoAUe7hHUqfxzFie+1Xs4S1xDgeaLyYwHQYDVR0OBBYEFH4PO+Wo" + "xfnSw6b2fU0tsRiDSeXuMEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEGCCsGAQUFBwIBFiVodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2" + "Nwa2kvY3BzMA4GA1UdDwEB/wQEAwIHgDBsBgNVHR8EZTBjMGGgX6BdhltodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvc2Vy" + "dmxldC9jcmxGaWxlRG93bi5jcmw/Y2VydHlwZT0xNCYvc29mdF9zaWduX3Nydl9jcmwuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBgGDC" + "sGAQQBj1sCgngBAwQIMAYCAQEKAQEwCgYIKoZIzj0EAwMDaQAwZgIxAOWOtWEhKZU2e11FBrOtaBnshDWzQJBi1RIB0uqicO/dGx7Vj7JA" + "RD8ayn/zGtUzewIxAKHSW0bh2OmR2Eg3JnwufW0UXomUkm21Q72Dg6pY33wl6pHsuh1dX8hHFb72ZZPvcKGCBY4wggWKMIIFEgIBATAJBg" + "cqhkjOPQQBMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBD" + "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" + "6RfHW0zQuwMzDSFUEEK6E4bUJMc7BikhRX4RcTq9oIIGHzCCAwowggKRoAMCAQICCFmxKhrzqk9dMAoGCCqGSM49BAMDMFgxCzAJBgNVBA" + "YTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxIzAhBgNVBAMMGkh1YXdlaSBDQkcgUm9vdCBDQSBHMiBUZXN0" + "MB4XDTIwMDMxMzExNTgyOFoXDTQwMDMxMzExNTgyOFowaTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2" + "VpIENCRzE0MDIGA1UEAwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0EgVGVzdDB2MBAGByqGSM49AgEGBSuBBAAi" + "A2IABLpDw0t7NE6WGv5QDQk3O3l/H3RhozD1G77KN07ZQb83ZtFwzU3VbWat11Tn3n4KRDmgvyUqF4IjR5HhEOF0kptHezG3qGBMqBClmt" + "Rtv0jkMW1Taii3scZRjIzLji3TG6OCARUwggERMB8GA1UdIwQYMBaAFGldwFjx9Tzm/QpA8R1gc9wceMbFMB0GA1UdDgQWBBR7uEdSp/HM" + "WJ77VezhLXEOB5ovJjAPBgNVHRMBAf8EBTADAQH/MEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEGCCsGAQUFBwIBFiVodHRwOi8vY3BraS1jYX" + "dlYi5odWF3ZWkuY29tL2Nwa2kvY3BzMA4GA1UdDwEB/wQEAwIBBjBmBgNVHR8EXzBdMFugWaBXhlVodHRwOi8vY3BraS1jYXdlYi5odWF3" + "ZWkuY29tL2Nwa2kvc2VydmxldC9jcmxGaWxlRG93bi5jcmw/Y2VydHlwZT0xMCYvcm9vdF9nMl9jcmwuY3JsMAoGCCqGSM49BAMDA2cAMG" + "QCMBez4yLjjg4aQ4c6cNnKlf8WyzSeQhMRSR8XMtQ9Gx5YxOcU7XLCDeNDGumhItzCUAIwB0C3wM2bzJq3mMCp3Nmx15UuvK6EkbzU761C" + "qdy3KfdpyjM4nosih5VihIK1I5ynMIIDDTCCApOgAwIBAgIIbfFy5Sitw0MwCgYIKoZIzj0EAwMwaTELMAkGA1UEBhMCQ04xDzANBgNVBA" + "oMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzE0MDIGA1UEAwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0Eg" + "VGVzdDAeFw0yMDA0MjgwMzIyMDdaFw0zMDA0MjgwMzIyMDdaMFAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCk" + "h1YXdlaSBDQkcxGzAZBgNVBAMMEnpob25neGlhbmdfcmVsZWFzZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABG13sRwF2UyuUStZhnRKWvJ2" + "LGdgNLlD2Nxr4BEkARuPVpvh0o0etRjqHAcgY7+G5vjho+K/MsHy5OxrwrPZzqfOglJ9o/fMjBMGb6UEsY/gpNqwUbZ3DuNnfkzTZ6BWLq" + "OCAR8wggEbMB8GA1UdIwQYMBaAFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMB0GA1UdDgQWBBSqp0kq/TCom+76Gf+70Fr4Nap24zBGBgNVHSAE" + "PzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCB4" + "AwbAYDVR0fBGUwYzBhoF+gXYZbaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2Nl" + "cnR5cGU9MTQmL3NvZnRfc2lnbl9zcnZfY3JsLmNybDATBgNVHSUEDDAKBggrBgEFBQcDAzAKBggqhkjOPQQDAwNoADBlAjA5cebpJ6jT3/" + "P9ostKezPiwpdM85/NtgyjwAN0B/6IFHbVSCZYLq+YqsPaKvIxxFECMQDIH1x6TMWpfbMWc87Dy96xCHKlKlSKdjS6uvL/mt7fF3Oz5Ar1" + "dXnT4AJ/Qc1lPsmhggWOMIIFijCCBRICAQEwCQYHKoZIzj0EATBpMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDA" + "pIdWF3ZWkgQ0JHMTQwMgYDVQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJlIFNpZ25pbmcgU2VydmljZSBDQSBUZXN0Fw0yMDA0MTcwNzMzMzNa" + "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" + "AAAA5SEAAAAA"; + + const std::string HAP_FILE_RSA_SIGN_BASE64 = + "UEsDBBQACAgIAAAAIToAAAAAAAAAAAAAAAAMAAQAcnNhX3Rlc3QuaGFw/soAADM0BABQSwcIdxVa1gQAAAACAAAAAgAAIFIVAAAYAAAAAA" + "AAILEMAABqFQAAMIIVTgYJKoZIhvcNAQcCoIIVPzCCFTsCAQExDzANBglghkgBZQMEAgEFADCCB/sGCSqGSIb3DQEHAaCCB+wEggfoeyJ2" + "ZXJzaW9uLW5hbWUiOiIxLjAuMCIsInZlcnNpb24tY29kZSI6MSwiYXBwLWRpc3RyaWJ1dGlvbi10eXBlIjoib3NfaW50ZWdyYXRpb24iLC" + "J1dWlkIjoiOThBN0Y3NzItNTg0Qi00RUQ3LTk3M0QtQjA4ODNGMEYxOUVGIiwidmFsaWRpdHkiOnsibm90LWJlZm9yZSI6MTU4NjQyMjc0" + "Mywibm90LWFmdGVyIjoxNjE3OTU4NzQzfSwidHlwZSI6InJlbGVhc2UiLCJidW5kbGUtaW5mbyI6eyJkZXZlbG9wZXItaWQiOiJ6aG9uZ3" + "hpYW5nIiwiZGlzdHJpYnV0aW9uLWNlcnRpZmljYXRlIjoiLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlFVXpDQ0E5cWdBd0lC" + "QWdJSWRFY05DbEFLNmU4d0NnWUlLb1pJemowRUF3TXdhVEVMTUFrR0ExVUVCaE1DXG5RMDR4RHpBTkJnTlZCQW9NQmtoMVlYZGxhVEVUTU" + "JFR0ExVUVDd3dLU0hWaGQyVnBJRU5DUnpFME1ESUdBMVVFXG5Bd3dyU0hWaGQyVnBJRU5DUnlCVGIyWjBkMkZ5WlNCVGFXZHVhVzVuSUZO" + "bGNuWnBZMlVnUTBFZ1ZHVnpkREFlXG5GdzB5TURBMU1Ea3dNalU0TlRCYUZ3MHlNVEExTURrd01qVTROVEJhTUU4eFRUQkxCZ05WQkFZTV" + "JFTk9JRTg5XG5TSFZoZDJWcElFTkNSeUJQVlQxSVQxTWdSR1YyWld4dmNHMWxiblFnU1VSRklGUmxZVzBnUTA0OWFIZGZhR0Z3XG5hMlY1" + "WDNKellWOXBaR1ZmWkdWMk1JSUJvakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBWThBTUlJQmlnS0NBWUVBXG5oM3VJalE1ZUhvL1pmMG5hVV" + "J6L2VRZ0hnOHdzSUl5VEFYd3lYdGh2VDZ6TEdtcmpCbjBiOWhEeHcwbGJxU2NGXG4yamZLQzk3b0EyNlg1K2E2NmdGdzhzTnZQa29DaHJI" + "T08yRloyMS9vUEVGbGYwK21NY3N4UjNDZUpkTTF1NmxvXG5samxncEF0TFZveFJiSTVqMW9SU3U5Vkw4aUFycHJIeEVnclFSbHV5aERzRm" + "RtZHN3ZnROaWl1UDdidVhQeHFYXG5ISWxka0IwK0RFSzlvSHY0L0JRWnhoOFJFQlBuYjNCck45OFc4SnYrYWdIMzhPMlBxd1gyeDZHRFl2" + "SSt6ODVLXG5uRFpCNlFPL3JTVjdiWVhuWXFkSDZJa3lGMzNuTzFnbVZ5T3lZQlF0azhLNE1mYkMrM29pWERwVzlxQnByUHJzXG4zek1ubz" + "NLa1ZNMEpJdzFXVTFwK05nNk1lTDJja3JYRzYrV3lrM2x5QnNuZ2VDVEp6ejBaZ29JOTRFZWxNL3pxXG5tejZ6cTl5TUFpWTZnTWhTdWpJ" + "a1pOendKQ3d1N1BMZXFrKzdyLy8rNGNXMEJJZ3Q5WElCTmdXd1FoOGdNWU9sXG5saHNxZmR4VWlUa1FpYnpZOXNQQ0J4bFBNWnJENW9WSX" + "hJZ1IyTUZMRDVyam5CN0ZZUytJYU14bTV1NFBYYytCXG5BZ01CQUFHamdnRTVNSUlCTlRBZkJnTlZIU01FR0RBV2dCUjd1RWRTcC9ITVdK" + "NzdWZXpoTFhFT0I1b3ZKakFkXG5CZ05WSFE0RUZnUVVmVFkwVGZhS0VjdWhhM1dPUHJnNE1XMDBaMHd3UmdZRFZSMGdCRDh3UFRBN0JnUl" + "ZIU0FBXG5NRE13TVFZSUt3WUJCUVVIQWdFV0pXaDBkSEE2THk5amNHdHBMV05oZDJWaUxtaDFZWGRsYVM1amIyMHZZM0JyXG5hUzlqY0hN" + "d0RnWURWUjBQQVFIL0JBUURBZ2VBTUd3R0ExVWRId1JsTUdNd1lhQmZvRjJHVzJoMGRIQTZMeTlqXG5jR3RwTFdOaGQyVmlMbWgxWVhkbG" + "FTNWpiMjB2WTNCcmFTOXpaWEoyYkdWMEwyTnliRVpwYkdWRWIzZHVMbU55XG5iRDlqWlhKMGVYQmxQVEUwSmk5emIyWjBYM05wWjI1ZmMz" + "SjJYMk55YkM1amNtd3dFd1lEVlIwbEJBd3dDZ1lJXG5Ld1lCQlFVSEF3TXdHQVlNS3dZQkJBR1BXd0tDZUFFREJBZ3dCZ0lCQVFvQkFEQU" + "tCZ2dxaGtqT1BRUURBd05uXG5BREJrQWpCRHJGTUNiZzAyTUdoa0p3emhCdFVIbk85Ny9hMlNqVCs4bEpxTkpCTkhMWVh3VER1Kzg5a1Jj" + "cG1zXG4rVFlCam5vQ01BL0dHUXJscTgrbldIZFNZMjkzY0hNcG5DZ09oNVJkdk5BRkRwNjlkU0NqSTdqTWc2YWN5Y2hHXG5qVlorTXVIY1" + "VRPT1cbi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS1cbiIsImJ1bmRsZS1uYW1lIjoiY29tLmh1YXdlaS5oaXdvcmxkLmhpZGVtbyIsImFw" + "cC1mZWF0dXJlIjoiaG9zX25vcm1hbF9hcHAifSwicGVybWlzc2lvbnMiOnsicmVzdHJpY3RlZC1wZXJtaXNzaW9ucyI6WyJhYWEiLCJCQk" + "IiXX0sImlzc3VlciI6Ikh1YXdlaSBBcHBzIFN0b3JlIn2gggY+MIIDCjCCApGgAwIBAgIIWbEqGvOqT10wCgYIKoZIzj0EAwMwWDELMAkG" + "A1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEjMCEGA1UEAwwaSHVhd2VpIENCRyBSb290IENBIEcyIF" + "Rlc3QwHhcNMjAwMzEzMTE1ODI4WhcNNDAwMzEzMTE1ODI4WjBpMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApI" + "dWF3ZWkgQ0JHMTQwMgYDVQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJlIFNpZ25pbmcgU2VydmljZSBDQSBUZXN0MHYwEAYHKoZIzj0CAQYFK4" + "EEACIDYgAEukPDS3s0TpYa/lANCTc7eX8fdGGjMPUbvso3TtlBvzdm0XDNTdVtZq3XVOfefgpEOaC/JSoXgiNHkeEQ4XSSm0d7MbeoYEyo" + "EKWa1G2/SOQxbVNqKLexxlGMjMuOLdMbo4IBFTCCAREwHwYDVR0jBBgwFoAUaV3AWPH1POb9CkDxHWBz3Bx4xsUwHQYDVR0OBBYEFHu4R1" + "Kn8cxYnvtV7OEtcQ4Hmi8mMA8GA1UdEwEB/wQFMAMBAf8wRgYDVR0gBD8wPTA7BgRVHSAAMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly9jcGtp" + "LWNhd2ViLmh1YXdlaS5jb20vY3BraS9jcHMwDgYDVR0PAQH/BAQDAgEGMGYGA1UdHwRfMF0wW6BZoFeGVWh0dHA6Ly9jcGtpLWNhd2ViLm" + "h1YXdlaS5jb20vY3BraS9zZXJ2bGV0L2NybEZpbGVEb3duLmNybD9jZXJ0eXBlPTEwJi9yb290X2cyX2NybC5jcmwwCgYIKoZIzj0EAwMD" + "ZwAwZAIwF7PjIuOODhpDhzpw2cqV/xbLNJ5CExFJHxcy1D0bHljE5xTtcsIN40Ma6aEi3MJQAjAHQLfAzZvMmreYwKnc2bHXlS68roSRvN" + "TvrUKp3Lcp92nKMzieiyKHlWKEgrUjnKcwggMsMIICsaADAgECAggtM330Iaua/TAKBggqhkjOPQQDAzBpMQswCQYDVQQGEwJDTjEPMA0G" + "A1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMTQwMgYDVQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJlIFNpZ25pbmcgU2VydmljZS" + "BDQSBUZXN0MB4XDTIwMDUwNjA3MDAxOVoXDTIzMDUwNjA3MDAxOVowcTELMAkGA1UEBhMCQ04xEzARBgNVBAoMCkh1YXdlaSBDQkcxHTAb" + "BgNVBAsMFEhPUyBEZXZlbG9wbWVudCBUZWFtMS4wLAYDVQQDDCVIT1MgQXBwbGljYXRpb24gUHJvdmlzaW9uIFByb2ZpbGUgRGV2MFkwEw" + "YHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZ/fslnB7+yUV0nuGzzROo0JzGj8EQMCTl594RrzKDyTwkCoPoWCKMVP1zTgcZ3zW53kQ2hU6EBib" + "hACvJYwFr6OCATkwggE1MB8GA1UdIwQYMBaAFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMB0GA1UdDgQWBBR+DzvlqMX50sOm9n1NLbEYg0nl7j" + "BGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8B" + "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" + "jOPQQDAwNoADBlAjEAglA0WoJZsnFBqx5hfi/KMCiYW6jlKm8Ll+1y/7yXKdx3h44l7u12ZmEPkALxz4VNAjAosFhWw5fBE8OFStuUG8IS" + "/0IlH4kXwiei87Xjr4y0xFeYnm0DM/50tY+/6I90bKowggMKMIICkaADAgECAghZsSoa86pPXTAKBggqhkjOPQQDAzBYMQswCQYDVQQGEw" + "JDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMSMwIQYDVQQDDBpIdWF3ZWkgQ0JHIFJvb3QgQ0EgRzIgVGVzdDAe" + "Fw0yMDAzMTMxMTU4MjhaFw00MDAzMTMxMTU4MjhaMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaS" + "BDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3QwdjAQBgcqhkjOPQIBBgUrgQQAIgNi" + "AAS6Q8NLezROlhr+UA0JNzt5fx90YaMw9Ru+yjdO2UG/N2bRcM1N1W1mrddU595+CkQ5oL8lKheCI0eR4RDhdJKbR3sxt6hgTKgQpZrUbb" + "9I5DFtU2oot7HGUYyMy44t0xujggEVMIIBETAfBgNVHSMEGDAWgBRpXcBY8fU85v0KQPEdYHPcHHjGxTAdBgNVHQ4EFgQUe7hHUqfxzFie" + "+1Xs4S1xDgeaLyYwDwYDVR0TAQH/BAUwAwEB/zBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZW" + "IuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCAQYwZgYDVR0fBF8wXTBboFmgV4ZVaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2Vp" + "LmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2NlcnR5cGU9MTAmL3Jvb3RfZzJfY3JsLmNybDAKBggqhkjOPQQDAwNnADBkAj" + "AXs+Mi444OGkOHOnDZypX/Fss0nkITEUkfFzLUPRseWMTnFO1ywg3jQxrpoSLcwlACMAdAt8DNm8yat5jAqdzZsdeVLryuhJG81O+tQqnc" + "tyn3acozOJ6LIoeVYoSCtSOcpzCCBFMwggPaoAMCAQICCHRHDQpQCunvMAoGCCqGSM49BAMDMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDA" + "ZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRl" + "c3QwHhcNMjAwNTA5MDI1ODUwWhcNMjEwNTA5MDI1ODUwWjBPMU0wSwYDVQQGDERDTiBPPUh1YXdlaSBDQkcgT1U9SE9TIERldmVsb3BtZW" + "50IElERSBUZWFtIENOPWh3X2hhcGtleV9yc2FfaWRlX2RldjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAId7iI0OXh6P2X9J" + "2lEc/3kIB4PMLCCMkwF8Ml7Yb0+syxpq4wZ9G/YQ8cNJW6knBdo3ygve6ANul+fmuuoBcPLDbz5KAoaxzjthWdtf6DxBZX9PpjHLMUdwni" + "XTNbupaJY5YKQLS1aMUWyOY9aEUrvVS/IgK6ax8RIK0EZbsoQ7BXZnbMH7TYorj+27lz8alxyJXZAdPgxCvaB7+PwUGcYfERAT529wazff" + "FvCb/moB9/Dtj6sF9sehg2LyPs/OSpw2QekDv60le22F52KnR+iJMhd95ztYJlcjsmAULZPCuDH2wvt6Ilw6Vvagaaz67N8zJ6NypFTNCS" + "MNVlNafjYOjHi9nJK1xuvlspN5cgbJ4Hgkyc89GYKCPeBHpTP86ps+s6vcjAImOoDIUroyJGTc8CQsLuzy3qpPu6///uHFtASILfVyATYF" + "sEIfIDGDpZYbKn3cVIk5EIm82PbDwgcZTzGaw+aFSMSIEdjBSw+a45wexWEviGjMZubuD13PgQIDAQABo4IBOTCCATUwHwYDVR0jBBgwFo" + "AUe7hHUqfxzFie+1Xs4S1xDgeaLyYwHQYDVR0OBBYEFH02NE32ihHLoWt1jj64ODFtNGdMMEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEGCCsG" + "AQUFBwIBFiVodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvY3BzMA4GA1UdDwEB/wQEAwIHgDBsBgNVHR8EZTBjMGGgX6Bdhl" + "todHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvc2VydmxldC9jcmxGaWxlRG93bi5jcmw/Y2VydHlwZT0xNCYvc29mdF9zaWdu" + "X3Nydl9jcmwuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBgGDCsGAQQBj1sCgngBAwQIMAYCAQEKAQAwCgYIKoZIzj0EAwMDZwAwZAIwQ6" + "xTAm4NNjBoZCcM4QbVB5zve/2tko0/vJSajSQTRy2F8Ew7vvPZEXKZrPk2AY56AjAPxhkK5avPp1h3UmNvd3BzKZwoDoeUXbzQBQ6evXUg" + "oyO4zIOmnMnIRo1WfjLh3FExggKbMIIClwIBATB1MGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKEwZIdWF3ZWkxEzARBgNVBAsTCkh1YXdlaS" + "BDQkcxNDAyBgNVBAMTK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3QCCHRHDQpQCunvMA0GCWCGSAFlAwQC" + "AgUAoHkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwNzA4MDk0NDA0WjA/BgkqhkiG9w0BCQQxMgQwOL" + "EvnL4cEWbEqTNF7esYgRUohGGQqh9+wFbegP6EXq8b6gT0J89i4SeKKCxdMJ3/MA0GCSqGSIb3DQEBCgUABIIBgHDm/h9/MGJdNAOJs4zk" + "uP41PmnWSyjxGtoUzhNscXn0iO0Mw1NDMEsBzjXZBAoEvzQ8KxN4gXNFZ/Jlb8IZ4uSd0cKRWig9lSTP52mJwHbVXYG+AlU81nauqzieVw" + "Wr4HQwXFONw4zJLyWm3ZWSw398kJ2S8nSamqvPOHWgKUIWNktPywNQk4yF4QY0gZ0AiA1AiGynkObkw88aPsLQ+afgsLCnXGzf42QSz5QM" + "/l9DcBndUpL0palOLHGLcl4o+QaYHFa4ywHGc8m9tb/omiIGPs6YnmaNCbEOBB9dgMdExqbOpVw40aRRCc7Vz7WhW7gh0PS/sIlMOj2d8c" + "DkWLAaDio8nRz8lmT+PUelubHt8svP2RMw5vI/j4CR9XVbL8qxhbZAYt0700f53ihuuGglh0ABhtpazSyT7bUcC8s/nXQVV5gmzw/aRlAa" + "m+cArPFrDBen/P6ezF5PTqvcqenc5X9Lc97HXn0UZEluIQAStfs6J4hq3+YXbXJAVy5WJgIAAAA7IgAAAAAAAEhBUCBTaWcgQmxvY2sgND" + "ICAAAAUEsBAhQAFAAICAgAAAAhOncVWtYEAAAAAgAAAAwABAAAAAAAAAAAAAAAAAAAAHJzYV90ZXN0LmhhcP7KAABQSwUGAAAAAAEAAQA+" + "AAAAfSIAAAAA"; + + const std::string HAP_FILE_INNER = + "UEsDBBQACAgIAAAAIToAAAAAAAAAAAAAAAAFAAQAMS50eHT+ygAAMzQ0NAQAUEsHCPfI+dsGAAAABAAAAAIAACBhEwAAGAAAAAAAACBVGQ" + "AAeRMAADCCE10GCSqGSIb3DQEHAqCCE04wghNKAgEBMQ8wDQYJYIZIAWUDBAIBBQAwggYHBgkqhkiG9w0BBwGgggX4BIIF9HsidmVyc2lv" + "bi1uYW1lIjoiMS4wLjAiLCJ2ZXJzaW9uLWNvZGUiOjEsImFwcC1kaXN0cmlidXRpb24tdHlwZSI6Im9zX2ludGVncmF0aW9uIiwidXVpZC" + "I6Ijk5QTdGNzcyLTU4NEItNEVENy05NzNELUIwODgzRjBGMTlFRiIsInZhbGlkaXR5Ijp7Im5vdC1iZWZvcmUiOjE1ODg3NDc2MTUsIm5v" + "dC1hZnRlciI6MTY4MzM1NTYxNX0sInR5cGUiOiJyZWxlYXNlIiwiYnVuZGxlLWluZm8iOnsiZGV2ZWxvcGVyLWlkIjoiaHVhd2VpIiwiZG" + "lzdHJpYnV0aW9uLWNlcnRpZmljYXRlIjoiLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlESkRDQ0FxbWdBd0lCQWdJSVJyaDhw" + "cTUwNEZFd0NnWUlLb1pJemowRUF3TXdhVEVMTUFrR0ExVUVCaE1DXG5RMDR4RHpBTkJnTlZCQW9NQmtoMVlYZGxhVEVUTUJFR0ExVUVDd3" + "dLU0hWaGQyVnBJRU5DUnpFME1ESUdBMVVFXG5Bd3dyU0hWaGQyVnBJRU5DUnlCVGIyWjBkMkZ5WlNCVGFXZHVhVzVuSUZObGNuWnBZMlVn" + "UTBFZ1ZHVnpkREFlXG5GdzB5TURBMU1EWXdOalV4TkRoYUZ3MHlNekExTURZd05qVXhORGhhTUdreEN6QUpCZ05WQkFZVEFrTk9NUk13XG" + "5FUVlEVlFRS0RBcElkV0YzWldrZ1EwSkhNUjB3R3dZRFZRUUxEQlJJVDFNZ1JHVjJaV3h2Y0cxbGJuUWdWR1ZoXG5iVEVtTUNRR0ExVUVB" + "d3dkU0U5VElFRndjR3hwWTJGMGFXOXVJRkJ5YjNacGMybHZiaUJFWlhZd1dUQVRCZ2NxXG5oa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQV" + "MxYjZwS3FPVXo2WC9YMURNRThici9NaHlZdldyVHhVYnFQMlpYXG5UWk9iNk1tOUZoMno2YUtkdE43RVJ6N0hvVGNPbGpHQzBhU1BybHho" + "UjdqNk8ySjBvNElCT1RDQ0FUVXdId1lEXG5WUjBqQkJnd0ZvQVVlN2hIVXFmeHpGaWUrMVhzNFMxeERnZWFMeVl3SFFZRFZSME9CQllFRk" + "43ejA5RjUvajRkXG5nalRMK1pxajhjZ2U4RUNCTUVZR0ExVWRJQVEvTUQwd093WUVWUjBnQURBek1ERUdDQ3NHQVFVRkJ3SUJGaVZvXG5k" + "SFJ3T2k4dlkzQnJhUzFqWVhkbFlpNW9kV0YzWldrdVkyOXRMMk53YTJrdlkzQnpNQTRHQTFVZER3RUIvd1FFXG5Bd0lIZ0RCc0JnTlZIUj" + "hFWlRCak1HR2dYNkJkaGx0b2RIUndPaTh2WTNCcmFTMWpZWGRsWWk1b2RXRjNaV2t1XG5ZMjl0TDJOd2Eya3ZjMlZ5ZG14bGRDOWpjbXhH" + "YVd4bFJHOTNiaTVqY213L1kyVnlkSGx3WlQweE5DWXZjMjltXG5kRjl6YVdkdVgzTnlkbDlqY213dVkzSnNNQk1HQTFVZEpRUU1NQW9HQ0" + "NzR0FRVUZCd01ETUJnR0RDc0dBUVFCXG5qMXNDZ25nQkF3UUlNQVlDQVFFS0FRQXdDZ1lJS29aSXpqMEVBd01EYVFBd1pnSXhBTC9mNXQ5" + "VGVxRStWcDVXXG5HOEgwVktxYWNFdGhVVmVzV1VKSTU3ZXRMclFkQ2dUY2haMjBqMC9Sc25oSCtsYWhmd0l4QUlOMWlpY2M3OUVhXG5Fb0" + "9URFNZMUVzaFpucSsvaUkwallYMUlJNitnbjVKZmJmem14RG1VcEtIaEsyVjAzZEpKMFE9PVxuLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0t" + "LVxuIiwiYnVuZGxlLW5hbWUiOiIuKiIsImFwcC1mZWF0dXJlIjoiaG9zX3N5c3RlbV9hcHAifSwiaXNzdWVyIjoiSHVhd2VpIEFwcHMgU3" + "RvcmUifaCCBkMwggMKMIICkaADAgECAghZsSoa86pPXTAKBggqhkjOPQQDAzBYMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMw" + "EQYDVQQLDApIdWF3ZWkgQ0JHMSMwIQYDVQQDDBpIdWF3ZWkgQ0JHIFJvb3QgQ0EgRzIgVGVzdDAeFw0yMDAzMTMxMTU4MjhaFw00MDAzMT" + "MxMTU4MjhaMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdlaSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBD" + "QkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3QwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAS6Q8NLezROlhr+UA0JNzt5fx90Ya" + "Mw9Ru+yjdO2UG/N2bRcM1N1W1mrddU595+CkQ5oL8lKheCI0eR4RDhdJKbR3sxt6hgTKgQpZrUbb9I5DFtU2oot7HGUYyMy44t0xujggEV" + "MIIBETAfBgNVHSMEGDAWgBRpXcBY8fU85v0KQPEdYHPcHHjGxTAdBgNVHQ4EFgQUe7hHUqfxzFie+1Xs4S1xDgeaLyYwDwYDVR0TAQH/BA" + "UwAwEB/zBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL2NwczAO" + "BgNVHQ8BAf8EBAMCAQYwZgYDVR0fBF8wXTBboFmgV4ZVaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2VpLmNvbS9jcGtpL3NlcnZsZXQvY3JsRm" + "lsZURvd24uY3JsP2NlcnR5cGU9MTAmL3Jvb3RfZzJfY3JsLmNybDAKBggqhkjOPQQDAwNnADBkAjAXs+Mi444OGkOHOnDZypX/Fss0nkIT" + "EUkfFzLUPRseWMTnFO1ywg3jQxrpoSLcwlACMAdAt8DNm8yat5jAqdzZsdeVLryuhJG81O+tQqnctyn3acozOJ6LIoeVYoSCtSOcpzCCAz" + "EwggK3oAMCAQICCGv0psZNBT6MMAoGCCqGSM49BAMDMGkxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZIdWF3ZWkxEzARBgNVBAsMCkh1YXdl" + "aSBDQkcxNDAyBgNVBAMMK0h1YXdlaSBDQkcgU29mdHdhcmUgU2lnbmluZyBTZXJ2aWNlIENBIFRlc3QwHhcNMjAwNTA2MDcwMTEzWhcNMj" + "MwNTA2MDcwMTEzWjB3MQswCQYDVQQGEwJDTjETMBEGA1UECgwKSHVhd2VpIENCRzEdMBsGA1UECwwUSE9TIERldmVsb3BtZW50IFRlYW0x" + "NDAyBgNVBAMMK0hPUyBBcHBsaWNhdGlvbiBQcm92aXNpb24gUHJvZmlsZSBEZXZfRGVidWcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAA" + "QdB9SYqO9atez14k6Jv6xX7TfE+m7gzj8ttU7P9+eGGBYCLRbs0LcNb6Z7krHq+8bUgnr0dffQfbhvJCaRp135o4IBOTCCATUwHwYDVR0j" + "BBgwFoAUe7hHUqfxzFie+1Xs4S1xDgeaLyYwHQYDVR0OBBYEFFTh4cdLADjM2EtQnZFreAUtdWZuMEYGA1UdIAQ/MD0wOwYEVR0gADAzMD" + "EGCCsGAQUFBwIBFiVodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvY3BzMA4GA1UdDwEB/wQEAwIHgDBsBgNVHR8EZTBjMGGg" + "X6BdhltodHRwOi8vY3BraS1jYXdlYi5odWF3ZWkuY29tL2Nwa2kvc2VydmxldC9jcmxGaWxlRG93bi5jcmw/Y2VydHlwZT0xNCYvc29mdF" + "9zaWduX3Nydl9jcmwuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBgGDCsGAQQBj1sCgngBAwQIMAYCAQEKAQEwCgYIKoZIzj0EAwMDaAAw" + "ZQIwfX/jQDoWeCvU+U285TgTBPgj8wMY9R2aR/UvL5eKwuDiMbEMWra/7OnGeG4tM6m/AjEA6ek/0qGNL+9QoxYs+p4NCcMERSN2fbLLaC" + "OH/nqKKqzJfgMuBhsGEDylKsuAl7BuoYIFjjCCBYowggUSAgEBMAkGByqGSM49BAEwaTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdl" + "aTETMBEGA1UECwwKSHVhd2VpIENCRzE0MDIGA1UEAwwrSHVhd2VpIENCRyBTb2Z0d2FyZSBTaWduaW5nIFNlcnZpY2UgQ0EgVGVzdBcNMj" + "AwNDE3MDczMzMzWhcNMjAwNDE3MTEzMzMzWjCCBEYwGQIIFDszO+/tkL4XDTIwMDQwOTAyMDU1MlowGQIIFIDfZVEvZV4XDTIwMDQxNzAx" + "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" + "swCQYDVQQGEwJDTjETMBEGA1UECgwKSHVhd2VpIENCRzEdMBsGA1UECwwUSE9TIERldmVsb3BtZW50IFRlYW0xJjAkBgNVBAMMHUhPUyBB" + "cHBsaWNhdGlvbiBQcm92aXNpb24gRGV2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtW+qSqjlM+l/19QzBPG6/zIcmL1q08VG6j9mV0" + "2Tm+jJvRYds+minbTexEc+x6E3DpYxgtGkj65cYUe4+jtidKOCATkwggE1MB8GA1UdIwQYMBaAFHu4R1Kn8cxYnvtV7OEtcQ4Hmi8mMB0G" + "A1UdDgQWBBTe89PRef4+HYI0y/mao/HIHvBAgTBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cDovL2Nwa2ktY2F3ZW" + "IuaHVhd2VpLmNvbS9jcGtpL2NwczAOBgNVHQ8BAf8EBAMCB4AwbAYDVR0fBGUwYzBhoF+gXYZbaHR0cDovL2Nwa2ktY2F3ZWIuaHVhd2Vp" + "LmNvbS9jcGtpL3NlcnZsZXQvY3JsRmlsZURvd24uY3JsP2NlcnR5cGU9MTQmL3NvZnRfc2lnbl9zcnZfY3JsLmNybDATBgNVHSUEDDAKBg" + "grBgEFBQcDAzAYBgwrBgEEAY9bAoJ4AQMECDAGAgEBCgEAMAoGCCqGSM49BAMDA2kAMGYCMQC/3+bfU3qhPlaeVhvB9FSqmnBLYVFXrFlC" + "SOe3rS60HQoE3IWdtI9P0bJ4R/pWoX8CMQCDdYonHO/RGhKDkw0mNRLIWZ6vv4iNI2F9SCOvoJ+SX2385sQ5lKSh4StldN3SSdGhghFVMI" + "IRUTCCENcCAQEwCQYHKoZIzj0EATBpMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMTQwMgYD" + "VQQDDCtIdWF3ZWkgQ0JHIFNvZnR3YXJlIFNpZ25pbmcgU2VydmljZSBDQSBUZXN0Fw0yMDA1MTkwNDMyNDJaFw0yMDA1MTkwODMyNDJaMI" + "IQCzAZAggRw8ia8W75jBcNMjAwNDIzMDkwNzQ1WjAZAggSPIRWNvcy6BcNMjAwNDIxMDczNTQ3WjAZAggSxqS2QKLsGRcNMjAwNDIyMDIw" + "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"; + } // namespace SignatureTools +} // namespace OHOS +#endif // TEST_HAP_FILE_DATA_H diff --git a/hapsigntool_cpp/test/unittest/ohos_test.xml b/hapsigntool_cpp/test/unittest/ohos_test.xml new file mode 100644 index 0000000000000000000000000000000000000000..7be32a06a735880edc925fef51e827743dd6657e --- /dev/null +++ b/hapsigntool_cpp/test/unittest/ohos_test.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + diff --git a/tools/app1-unsignedcode.hap b/tools/app1-unsignedcode.hap new file mode 100644 index 0000000000000000000000000000000000000000..8a69fcfdf5a1c9f212916270d045d579966a03c1 Binary files /dev/null and b/tools/app1-unsignedcode.hap differ