diff --git a/interfaces/innerkits/appverify/BUILD.gn b/interfaces/innerkits/appverify/BUILD.gn index 65a1fb4a8ef59f7821749abf7c8a6ade9b06e2a4..dddd99a7b8f37941bd1655de9577bd2438af79c6 100644 --- a/interfaces/innerkits/appverify/BUILD.gn +++ b/interfaces/innerkits/appverify/BUILD.gn @@ -35,9 +35,11 @@ ohos_shared_library("libhapverify") { "src/init/json_parser_utils.cpp", "src/init/trusted_root_ca.cpp", "src/init/trusted_source_manager.cpp", + "src/init/trusted_ticket_manager.cpp", "src/interfaces/hap_verify.cpp", "src/interfaces/hap_verify_result.cpp", "src/provision/provision_verify.cpp", + "src/ticket/ticket_verify.cpp", "src/util/digest_parameter.cpp", "src/util/hap_cert_verify_openssl_utils.cpp", "src/util/hap_profile_verify_utils.cpp", diff --git a/interfaces/innerkits/appverify/config/BUILD.gn b/interfaces/innerkits/appverify/config/BUILD.gn index 32e72dd126362d76dba56b01e4c7c2a49c3c07de..eb083dcac5ad481b9b6a3910eb443725f41905ec 100644 --- a/interfaces/innerkits/appverify/config/BUILD.gn +++ b/interfaces/innerkits/appverify/config/BUILD.gn @@ -48,3 +48,10 @@ ohos_prebuilt_etc("trusted_root_ca_test") { subsystem_name = "security" relative_install_dir = "security" } + +ohos_prebuilt_etc("trusted_tickets_sources") { + source = "trusted_tickets_sources.json" + part_name = "appverify" + subsystem_name = "security" + relative_install_dir = "security" +} diff --git a/interfaces/innerkits/appverify/config/trusted_tickets_sources.json b/interfaces/innerkits/appverify/config/trusted_tickets_sources.json new file mode 100644 index 0000000000000000000000000000000000000000..2e86cd59b633d605daf999913f53c6a9916f28b1 --- /dev/null +++ b/interfaces/innerkits/appverify/config/trusted_tickets_sources.json @@ -0,0 +1,13 @@ +{ + "version": "1.0.1", + "release-time":"2021-06-03 10:06:00", + "trust-app-source":[ + { + "name":"huawei member center", + "ticket-signing-cert":"^C=CN, O=Huawei, OU=MemberCenter, CN=MemberShip ticket Release V([1-9])([0-9])*$", + "issuer-ca":"C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA", + "max-certs-path":3, + "critialcal-cert-extension":["keyusage","huawei-signing-capability"] + } + ] +} \ No newline at end of file diff --git a/interfaces/innerkits/appverify/include/init/matching_result.h b/interfaces/innerkits/appverify/include/init/matching_result.h index 97f90546ebd779cd568c13d45721182fc0e42472..70578e2e5ca48e74396778aad2eb056d0e657300 100644 --- a/interfaces/innerkits/appverify/include/init/matching_result.h +++ b/interfaces/innerkits/appverify/include/init/matching_result.h @@ -30,6 +30,7 @@ enum MatchingStates { MATCH_WITH_SIGN, MATCH_WITH_PROFILE, MATCH_WITH_PROFILE_DEBUG, + MATCH_WITH_TICKET, }; struct MatchingResult { diff --git a/interfaces/innerkits/appverify/include/init/trusted_ticket_manager.h b/interfaces/innerkits/appverify/include/init/trusted_ticket_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..12d6057daa534e4958af0e7e32b28df199c8c260 --- /dev/null +++ b/interfaces/innerkits/appverify/include/init/trusted_ticket_manager.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2021 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_TRUSTED_TICKET_MANAGER_H +#define HAP_TRUSTED_TICKET_MANAGER_H + +#include +#include + +#include "common/export_define.h" +#include "init/json_parser_utils.h" +#include "init/matching_result.h" + +namespace OHOS { +namespace Security { +namespace Verify { +struct HapTicketSourceInfo { + TrustedSources source; + std::string sourceName; + std::string ticketSigningCert; + std::string issuer; + int maxCertsPath; + StringVec critialcalCertExtension; +}; + +using TicketSourceInfoVec = std::vector; + +class TrustedTicketManager { +public: + DLL_EXPORT static TrustedTicketManager& GetInstance(); + DLL_EXPORT bool Init(); + DLL_EXPORT void Recovery(); + DLL_EXPORT MatchingResult IsTrustedSource(const std::string& certSubject, const std::string& certIssuer, + int certListPath) const; + +private: + TrustedTicketManager(); + ~TrustedTicketManager(); + + /* Forbid external replication constructs and external replication */ + TrustedTicketManager(const TrustedTicketManager& trustedSource) = delete; + TrustedTicketManager& operator = (const TrustedTicketManager& trustedSource) = delete; + + bool GetTicketTrustedSources(TicketSourceInfoVec& trustedTicketSources, std::string& sourcesVersion, + std::string& sourcesReleaseTime, const std::string& filePath); + bool ParseTrustedTicketSourceJson(TicketSourceInfoVec& trustedTicketSources, + const JsonObjVec& trustedTicketSourceJson); + std::string EncapTrustedTicketSourceString(const HapTicketSourceInfo& ticketSourceInfo); + MatchingResult MatchTrustedSource(const TicketSourceInfoVec& trustedTicketSources, const std::string& certSubject, + const std::string& certIssuer, int certListPath) const; + MatchingStates TrustedSourceListCompare(const std::string& certSubject, const std::string& certIssuer, + const HapTicketSourceInfo& TicketSource) const; + bool MatchSubject(const std::string& trustedSource, const std::string& certSubject) const; + bool MatchIssuer(const std::string& trustedSource, const std::string& certIssuer) const; + +private: + static const std::string TICKET_TRUSTED_SOURCE_FILE_PATH; + static const std::string KEY_OF_TICKET_TRUSTED_SOURCE; + static const std::string KEY_OF_TICKET_TRUSTED_SOURCE_VERSION; + static const std::string KEY_OF_TICKET_TRUSTED_SOURCE_RELEASETIME; + static const std::string KEY_OF_SOURCE_NAME; + static const std::string KEY_OF_TICKET_SIGNING_CERT; + static const std::string KEY_OF_ISSUER; + static const std::string KEY_OF_MAX_CERTS_PATH; + static const std::string KEY_OF_CRITIALCAL_CERT_EXTENSION; + TicketSourceInfoVec TicketTrustedSources; + std::string version; + std::string releaseTime; + bool isInit; +}; +} // namespace Verify +} // namespace Security +} // namespace OHOS +#endif // HAP_TRUSTED_TICKET_MANAGER_H \ No newline at end of file diff --git a/interfaces/innerkits/appverify/include/provision/provision_verify.h b/interfaces/innerkits/appverify/include/provision/provision_verify.h index 200d70d9722194d34703eaaf99adc22cf7858173..95ad513189d6c4561b041a6421d72c0737908dc9 100644 --- a/interfaces/innerkits/appverify/include/provision/provision_verify.h +++ b/interfaces/innerkits/appverify/include/provision/provision_verify.h @@ -28,7 +28,7 @@ enum AppProvisionVerifyResult { PROVISION_OK, // Passed PROVISION_UNSUPPORTED_DEVICE_TYPE, // Failed to get device id PROVISION_NUM_DEVICE_EXCEEDED, // No. of device exceeds maximum number - PROVISION_DEVICE_UNAUTHORIZED // Device id not included + PROVISION_DEVICE_UNAUTHORIZED, // Device id not included }; /** @@ -38,6 +38,7 @@ enum AppProvisionVerifyResult { * @return AppProvisionVerifyResult Verification result. */ DLL_EXPORT AppProvisionVerifyResult ParseAndVerify(const std::string& appProvision, ProvisionInfo& info); +DLL_EXPORT AppProvisionVerifyResult ParseProvision(const std::string& appProvision, ProvisionInfo& info); } // namespace Verify } // namespace Security } // namespace OHOS diff --git a/interfaces/innerkits/appverify/include/ticket/ticket_verify.h b/interfaces/innerkits/appverify/include/ticket/ticket_verify.h new file mode 100644 index 0000000000000000000000000000000000000000..5adcdc69916e31c8ff8cd0696feeda206086b550 --- /dev/null +++ b/interfaces/innerkits/appverify/include/ticket/ticket_verify.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021 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 TICKET_VERIFY_H +#define TICKET_VERIFY_H + +#include "common/export_define.h" +#include "common/hap_byte_buffer.h" +#include "common/random_access_file.h" + +#include "provision/provision_info.h" +#include "provision/provision_verify.h" + +namespace OHOS { +namespace Security { +namespace Verify { +enum TicketVerifyResultCode { + TICKET_VERIFY_SUCCESS = 0, + OPEN_TICKET_FILE_ERROR = -1, + SIGNATURE_VERIFY_FAIL = -2, + TICKET_OK = -3, + TICKET_NOT_MATCH = -4, + TICKET_DEVICE_INVALID = -5, + TICKET_PARSE_FAIL = -6, + TICKET_PERMISSION_ERROR = -7, + TICKET_READ_FAIL = -8, +}; +/** + * @brief Parse and verify the ticket + * @param profileInfo input param, the parsed profile structure. + * @return ticket verify result. + */ +DLL_EXPORT bool CheckTicketSource(const ProvisionInfo& profileInfo); +} // namespace Verify +} // namespace Security +} // namespace OHOS +#endif // TICKET_VERIFY_H \ No newline at end of file diff --git a/interfaces/innerkits/appverify/include/verify/hap_verify_v2.h b/interfaces/innerkits/appverify/include/verify/hap_verify_v2.h index cb1950cccedf986baae75eabbfecf9c6a78e06c9..0ef5c5f087439f4922fab2917ad1ce424b564c38 100644 --- a/interfaces/innerkits/appverify/include/verify/hap_verify_v2.h +++ b/interfaces/innerkits/appverify/include/verify/hap_verify_v2.h @@ -43,7 +43,7 @@ private: void WriteCrlIfNeed(const Pkcs7Context& pkcs7Context, const bool& profileNeedWriteCrl); DLL_EXPORT bool ParseAndVerifyProfileIfNeed(const std::string& profile, ProvisionInfo& provisionInfo, bool isCallParseAndVerify); - bool IsAppDistributedTypeAllowInstall(const AppDistType& type) const; + bool IsAppDistributedTypeAllowInstall(const AppDistType& type, const ProvisionInfo& provisionInfo) const; DLL_EXPORT bool VerifyProfileInfo(const Pkcs7Context& pkcs7Context, const Pkcs7Context& profileContext, ProvisionInfo& provisionInfo); bool CheckProfileSignatureIsRight(const MatchingStates& matchState, const ProvisionType& type); diff --git a/interfaces/innerkits/appverify/src/init/trusted_ticket_manager.cpp b/interfaces/innerkits/appverify/src/init/trusted_ticket_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..911eaaba89b0d6b4c57b3aa2bbf0ab6b8000c1fd --- /dev/null +++ b/interfaces/innerkits/appverify/src/init/trusted_ticket_manager.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2021 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 "init/trusted_ticket_manager.h" + +#include + +#include "nlohmann/json.hpp" + +#include "common/hap_verify_log.h" + +namespace OHOS { +namespace Security { +namespace Verify { +const std::string TrustedTicketManager::TICKET_TRUSTED_SOURCE_FILE_PATH = + "/system/etc/security/trusted_tickets_sources.json"; +const std::string TrustedTicketManager::KEY_OF_TICKET_TRUSTED_SOURCE = "trust-app-source"; +const std::string TrustedTicketManager::KEY_OF_TICKET_TRUSTED_SOURCE_VERSION = "version"; +const std::string TrustedTicketManager::KEY_OF_TICKET_TRUSTED_SOURCE_RELEASETIME = "release-time"; +const std::string TrustedTicketManager::KEY_OF_SOURCE_NAME = "name"; +const std::string TrustedTicketManager::KEY_OF_TICKET_SIGNING_CERT = "ticket-signing-cert"; +const std::string TrustedTicketManager::KEY_OF_ISSUER = "issuer-ca"; +const std::string TrustedTicketManager::KEY_OF_MAX_CERTS_PATH = "max-certs-path"; +const std::string TrustedTicketManager::KEY_OF_CRITIALCAL_CERT_EXTENSION = "critialcal-cert-extension"; + +TrustedTicketManager& TrustedTicketManager::GetInstance() +{ + static TrustedTicketManager singleTrustedTicketManager; + return singleTrustedTicketManager; +} + +TrustedTicketManager::TrustedTicketManager() + : TicketTrustedSources(), version(), releaseTime(), isInit(false) +{ +} + +TrustedTicketManager::~TrustedTicketManager() +{ +} + +bool TrustedTicketManager::Init() +{ + if (isInit) { + return true; + } + + isInit = GetTicketTrustedSources(TicketTrustedSources, version, releaseTime, TICKET_TRUSTED_SOURCE_FILE_PATH); + if (isInit) { + HAPVERIFY_LOG_INFO(LABEL, "trusted ticket source version: %{public}s, releaseTime: %{public}s, Size:" + " %{public}zu", version.c_str(), releaseTime.c_str(), TicketTrustedSources.size()); + } + return isInit; +} + +void TrustedTicketManager::Recovery() +{ + TicketTrustedSources.clear(); + isInit = false; +} + +bool TrustedTicketManager::GetTicketTrustedSources(TicketSourceInfoVec& trustedTicketSources, + std::string& sourcesVersion, std::string& sourcesReleaseTime, const std::string& filePath) +{ + nlohmann::json trustedSourceJson; + std::string errorInfo; + if (!JsonParserUtils::ReadTrustedRootCAFromJson(trustedSourceJson, filePath, errorInfo)) { + HAPVERIFY_LOG_ERROR(LABEL, "get jsonObj from %{public}s failed, because %{public}s", + filePath.c_str(), errorInfo.c_str()); + return false; + } + if (!JsonParserUtils::GetJsonString(trustedSourceJson, KEY_OF_TICKET_TRUSTED_SOURCE_VERSION, sourcesVersion)) { + HAPVERIFY_LOG_ERROR(LABEL, "get version failed"); + return false; + } + if (!JsonParserUtils::GetJsonString(trustedSourceJson, + KEY_OF_TICKET_TRUSTED_SOURCE_RELEASETIME, sourcesReleaseTime)) { + HAPVERIFY_LOG_ERROR(LABEL, "get releaseTime failed"); + return false; + } + JsonObjVec trustedTicketSourceJson; + if (!JsonParserUtils::ParseJsonToObjVec(trustedSourceJson, KEY_OF_TICKET_TRUSTED_SOURCE, trustedTicketSourceJson)) { + HAPVERIFY_LOG_ERROR(LABEL, "get JsonObjVec failed"); + return false; + } + if (!ParseTrustedTicketSourceJson(trustedTicketSources, trustedTicketSourceJson)) { + HAPVERIFY_LOG_ERROR(LABEL, "parse JsonObjVec failed"); + return false; + } + if (trustedTicketSources.empty()) { + HAPVERIFY_LOG_ERROR(LABEL, "no ticket trusted source"); + return false; + } + return true; +} + +bool TrustedTicketManager::ParseTrustedTicketSourceJson(TicketSourceInfoVec& trustedTicketSources, + const JsonObjVec& trustedTicketSourceJson) +{ + for (auto TicketSource : trustedTicketSourceJson) { + HapTicketSourceInfo hapTicketSource; + if (!JsonParserUtils::GetJsonString(TicketSource, KEY_OF_SOURCE_NAME, hapTicketSource.sourceName)) { + HAPVERIFY_LOG_ERROR(LABEL, "Get sourceName Failed"); + return false; + } + hapTicketSource.source = OTHER_TRUSTED_SOURCE; + if (!JsonParserUtils::GetJsonString(TicketSource, KEY_OF_TICKET_SIGNING_CERT, + hapTicketSource.ticketSigningCert)) { + HAPVERIFY_LOG_ERROR(LABEL, "Get ticketSigningCert Failed"); + return false; + } + if (!JsonParserUtils::GetJsonString(TicketSource, KEY_OF_ISSUER, hapTicketSource.issuer)) { + HAPVERIFY_LOG_ERROR(LABEL, "Get issuer Failed"); + return false; + } + if (!JsonParserUtils::GetJsonInt(TicketSource, KEY_OF_MAX_CERTS_PATH, hapTicketSource.maxCertsPath)) { + HAPVERIFY_LOG_ERROR(LABEL, "Get maxCertsPath Failed"); + return false; + } + if (!JsonParserUtils::GetJsonStringVec(TicketSource, KEY_OF_CRITIALCAL_CERT_EXTENSION, + hapTicketSource.critialcalCertExtension)) { + HAPVERIFY_LOG_ERROR(LABEL, "Get critialcalCertExtension Failed"); + return false; + } + HAPVERIFY_LOG_INFO(LABEL, "trusted ticket source: %{public}s", + EncapTrustedTicketSourceString(hapTicketSource).c_str()); + trustedTicketSources.push_back(hapTicketSource); + } + return true; +} + +std::string TrustedTicketManager::EncapTrustedTicketSourceString(const HapTicketSourceInfo& ticketSourceInfo) +{ + std::string info = "sourceName: " + ticketSourceInfo.sourceName + "\n" + + "sourceNumber: " + std::to_string(static_cast(ticketSourceInfo.source)) + "\n" + + "ticketSigningCert: " + ticketSourceInfo.ticketSigningCert + "\n" + + "issuer: " + ticketSourceInfo.issuer + "\n" + + "maxCertsPath: " + std::to_string(ticketSourceInfo.maxCertsPath) + "\n" + + "critialcalCertExtension: "; + for (auto extension : ticketSourceInfo.critialcalCertExtension) { + info += extension + ", "; + } + return info; +} + +MatchingResult TrustedTicketManager::IsTrustedSource(const std::string& certSubject, + const std::string& certIssuer, int certListPath) const +{ + MatchingResult ret = MatchTrustedSource(TicketTrustedSources, certSubject, certIssuer, certListPath); + if (ret.matchState != DO_NOT_MATCH) { + return ret; + } + return ret; +} + +MatchingResult TrustedTicketManager::MatchTrustedSource(const TicketSourceInfoVec& trustedTicketSources, + const std::string& certSubject, const std::string& certIssuer, int certListPath) const +{ + MatchingResult ret; + ret.matchState = DO_NOT_MATCH; + for (auto TicketSource : trustedTicketSources) { + if (certListPath == TicketSource.maxCertsPath) { + ret.matchState = TrustedSourceListCompare(certSubject, certIssuer, TicketSource); + if (ret.matchState != DO_NOT_MATCH) { + ret.source = TicketSource.source; + break; + } + } + } + return ret; +} + +MatchingStates TrustedTicketManager::TrustedSourceListCompare(const std::string& certSubject, + const std::string& certIssuer, const HapTicketSourceInfo& TicketSource) const +{ + MatchingStates ret = DO_NOT_MATCH; + if (MatchSubject(TicketSource.ticketSigningCert, certSubject) && + MatchIssuer(TicketSource.issuer, certIssuer)) { + ret = MATCH_WITH_TICKET; + } + return ret; +} + +bool TrustedTicketManager::MatchSubject(const std::string& trustedSource, + const std::string& certSubject) const +{ + if (trustedSource.empty()) { + return false; + } + return std::regex_match(certSubject, std::regex(trustedSource)); +} + +bool TrustedTicketManager::MatchIssuer(const std::string& trustedSource, + const std::string& certIssuer) const +{ + if (trustedSource.empty()) { + return false; + } + return trustedSource == certIssuer; +} +} // namespace Verify +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp b/interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp index 754cc6e197d2f91f421e485952156bfc2e169583..1f31642fb5cbe973b6248428bb6817bcf96d1b7a 100644 --- a/interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp +++ b/interfaces/innerkits/appverify/src/interfaces/hap_verify.cpp @@ -21,6 +21,7 @@ #include "init/hap_crl_manager.h" #include "init/trusted_root_ca.h" #include "init/trusted_source_manager.h" +#include "init/trusted_ticket_manager.h" #include "verify/hap_verify_v2.h" namespace OHOS { @@ -35,12 +36,14 @@ bool HapVerifyInit() TrustedSourceManager& trustedAppSourceManager = TrustedSourceManager::GetInstance(); HapCrlManager& hapCrlManager = HapCrlManager::GetInstance(); DeviceTypeManager& deviceTypeManager = DeviceTypeManager::GetInstance(); + TrustedTicketManager& trustedTicketSourceManager = TrustedTicketManager::GetInstance(); g_mtx.lock(); g_isInit = rootCertsObj.Init() && trustedAppSourceManager.Init(); if (!g_isInit) { rootCertsObj.Recovery(); trustedAppSourceManager.Recovery(); } + trustedTicketSourceManager.Init(); hapCrlManager.Init(); deviceTypeManager.GetDeviceTypeInfo(); g_mtx.unlock(); diff --git a/interfaces/innerkits/appverify/src/provision/provision_verify.cpp b/interfaces/innerkits/appverify/src/provision/provision_verify.cpp index 4869b98d1aeecdf2bc51d3b2ebcbd130e734862f..10817c81a4c2941d17273c95e943f2e39569de2b 100644 --- a/interfaces/innerkits/appverify/src/provision/provision_verify.cpp +++ b/interfaces/innerkits/appverify/src/provision/provision_verify.cpp @@ -28,6 +28,9 @@ #include "common/hap_verify_log.h" #include "init/device_type_manager.h" +#include "init/trusted_ticket_manager.h" +#include "interfaces/hap_verify_result.h" +#include "ticket/ticket_verify.h" using namespace std; using namespace nlohmann; @@ -203,10 +206,16 @@ AppProvisionVerifyResult ParseProvision(const string& appProvision, ProvisionInf return PROVISION_OK; } -inline bool CheckDeviceID(const std::vector& deviceIds, const string& deviceId) +inline bool CheckDeviceID(const std::vector& deviceIds, const string& deviceId, ProvisionInfo& profileInfo) { auto iter = find(deviceIds.begin(), deviceIds.end(), deviceId); if (iter == deviceIds.end()) { + /* check ticketsource and verify ticket */ + if (CheckTicketSource(profileInfo)) { + HAPVERIFY_LOG_INFO(LABEL, "current device is allowed to install opentest application"); + return true; + } + DeviceTypeManager& deviceTypeManager = DeviceTypeManager::GetInstance(); if (!deviceTypeManager.GetDeviceTypeInfo()) { HAPVERIFY_LOG_ERROR(LABEL, "current device is not authorized"); @@ -258,7 +267,7 @@ AppProvisionVerifyResult CheckDeviceID(ProvisionInfo& info) return PROVISION_DEVICE_UNAUTHORIZED; } - if (!CheckDeviceID(info.debugInfo.deviceIds, deviceId)) { + if (!CheckDeviceID(info.debugInfo.deviceIds, deviceId, info)) { return PROVISION_DEVICE_UNAUTHORIZED; } return PROVISION_OK; diff --git a/interfaces/innerkits/appverify/src/ticket/ticket_verify.cpp b/interfaces/innerkits/appverify/src/ticket/ticket_verify.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe62c25aa9b824c31f7878890447ababb456bc6d --- /dev/null +++ b/interfaces/innerkits/appverify/src/ticket/ticket_verify.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2021 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 "ticket/ticket_verify.h" + +#include +#include + +#include "nlohmann/json.hpp" + +#ifndef STANDARD_SYSTEM +#include "ohos_account_kits.h" +#else +#include "parameter.h" +#include "sysparam_errno.h" +#endif // STANDARD_SYSTEM + +#include "common/hap_byte_buffer.h" +#include "common/hap_verify_log.h" +#include "common/random_access_file.h" +#include "init/device_type_manager.h" +#include "init/trusted_ticket_manager.h" +#include "util/hap_cert_verify_openssl_utils.h" +#include "util/hap_verify_openssl_utils.h" +#include "util/pkcs7_context.h" + +namespace { +const int MAXIMUM_DEVICES = 100; +const int TICKET_MAX_SIZE = 18432; +const std::string TICKET_FILE_PATH = "/data/misc/ticket/"; +const std::string VALUE_DEVICE_TYPE_UDID = "udid"; +const std::string TICKET_PATTERN = "[^]*.p7b$"; +} // namespace + +namespace OHOS { +namespace Security { +namespace Verify { +bool CheckTicketFilePath(const std::string& filePath, std::string& standardFilePath) +{ + char path[PATH_MAX + 1] = { 0x00 }; + if (filePath.size() > PATH_MAX || realpath(filePath.c_str(), path) == nullptr) { + HAPVERIFY_LOG_ERROR(LABEL, "It is not a standard path, %{public}s", filePath.c_str()); + return false; + } + standardFilePath = std::string(path); + if (!std::regex_match(standardFilePath, std::regex(TICKET_PATTERN))) { + HAPVERIFY_LOG_ERROR(LABEL, "file is not p7b, %{public}s", standardFilePath.c_str()); + return false; + } + return true; +} + +bool CheckPermissions(std::vector ticketPermissions, std::vector profilePermissions) +{ + for (auto ticket : ticketPermissions) { + auto iter = find(profilePermissions.begin(), profilePermissions.end(), ticket); + if (iter == profilePermissions.end()) { + return false; + } + } + return true; +} + +inline bool CheckDevice(const std::vector& deviceIds, const std::string& deviceId) +{ + auto iter = find(deviceIds.begin(), deviceIds.end(), deviceId); + if (iter == deviceIds.end()) { + return false; + } + return true; +} + +AppProvisionVerifyResult CheckDevice(ProvisionInfo& info) +{ + // Checking device ids + if (info.debugInfo.deviceIds.empty()) { + HAPVERIFY_LOG_ERROR(LABEL, "device-id list is empty."); + return PROVISION_DEVICE_UNAUTHORIZED; + } + + if (info.debugInfo.deviceIds.size() > MAXIMUM_DEVICES) { + HAPVERIFY_LOG_ERROR(LABEL, "No. of device IDs in list exceed maximum number %{public}d", MAXIMUM_DEVICES); + return PROVISION_NUM_DEVICE_EXCEEDED; + } + + if (info.debugInfo.deviceIdType != VALUE_DEVICE_TYPE_UDID) { + HAPVERIFY_LOG_ERROR(LABEL, "type of device ID is not supported."); + return PROVISION_UNSUPPORTED_DEVICE_TYPE; + } + + std::string deviceId; +#ifndef STANDARD_SYSTEM + int32_t ret = OHOS::AccountSA::OhosAccountKits::GetInstance().GetUdid(deviceId); + if (ret != 0) { + HAPVERIFY_LOG_ERROR(LABEL, "obtaining current device id failed (%{public}d).", ret); + return PROVISION_DEVICE_UNAUTHORIZED; + } +#else + char udid[DEV_UUID_LEN] = {0}; + int ret = GetDevUdid(udid, sizeof(udid)); + if (ret != EC_SUCCESS) { + HAPVERIFY_LOG_ERROR(LABEL, "obtaining current device id failed (%{public}d).", static_cast(ret)); + return PROVISION_DEVICE_UNAUTHORIZED; + } + deviceId = std::string(udid, sizeof(udid) - 1); + HAPVERIFY_LOG_INFO(LABEL, "L2 UDID:%{public}s, len:%{public}d.", deviceId.c_str(), + static_cast(deviceId.size())); +#endif // STANDARD_SYSTEM + if (deviceId.empty()) { + HAPVERIFY_LOG_ERROR(LABEL, "device-id of current device is empty."); + return PROVISION_DEVICE_UNAUTHORIZED; + } + + if (!CheckDevice(info.debugInfo.deviceIds, deviceId)) { + return PROVISION_DEVICE_UNAUTHORIZED; + } + return PROVISION_OK; +} + +int CompareTicketAndProfile(const ProvisionInfo& ticketInfo, const ProvisionInfo& profileInfo) +{ + if (ticketInfo.bundleInfo.bundleName != profileInfo.bundleInfo.bundleName) { + HAPVERIFY_LOG_ERROR(LABEL, "ticket bundlename doesn't match"); + return TICKET_NOT_MATCH; + } + + if (ticketInfo.type == DEBUG) { + if (ticketInfo.bundleInfo.developmentCertificate != profileInfo.bundleInfo.developmentCertificate) { + HAPVERIFY_LOG_ERROR(LABEL, "ticket developmentCertificate doesn't match"); + return TICKET_NOT_MATCH; + } + } else { + if (ticketInfo.bundleInfo.distributionCertificate != profileInfo.bundleInfo.distributionCertificate) { + HAPVERIFY_LOG_ERROR(LABEL, "ticket distributionCertificate doesn't match"); + return TICKET_NOT_MATCH; + } + } + + if (!ticketInfo.permissions.restrictedCapabilities.empty()) { + if (!CheckPermissions(ticketInfo.permissions.restrictedCapabilities, + profileInfo.permissions.restrictedCapabilities)) { + HAPVERIFY_LOG_ERROR(LABEL, "ticket restrictedCapabilities doesn't match"); + return TICKET_PERMISSION_ERROR; + } + } + + if (!ticketInfo.permissions.restrictedPermissions.empty()) { + if (!CheckPermissions(ticketInfo.permissions.restrictedPermissions, + profileInfo.permissions.restrictedPermissions)) { + HAPVERIFY_LOG_ERROR(LABEL, "ticket restrictedPermissions doesn't match"); + return TICKET_PERMISSION_ERROR; + } + } + return TICKET_OK; +} + +bool VerifyTicketSignature(HapByteBuffer& ticketBlock, Pkcs7Context& pkcs7Context, std::string& ticket) +{ + const unsigned char* pkcs7Block = reinterpret_cast(ticketBlock.GetBufferPtr()); + unsigned int pkcs7Len = ticketBlock.GetCapacity(); + if (!HapVerifyOpensslUtils::ParsePkcs7Package(pkcs7Block, pkcs7Len, pkcs7Context)) { + HAPVERIFY_LOG_ERROR(LABEL, "Parse ticket pkcs7 failed"); + return false; + } + ticket = std::string(pkcs7Context.content.GetBufferPtr(), pkcs7Context.content.GetCapacity()); + + if (!HapVerifyOpensslUtils::GetCertChains(pkcs7Context.p7, pkcs7Context)) { + HAPVERIFY_LOG_ERROR(LABEL, "GetCertChains from ticket pkcs7 failed"); + return false; + } + + if (!HapVerifyOpensslUtils::VerifyPkcs7(pkcs7Context)) { + HAPVERIFY_LOG_ERROR(LABEL, "verify ticket signature failed"); + return false; + } + + std::string certSubject; + if (!HapCertVerifyOpensslUtils::GetSubjectFromX509(pkcs7Context.certChains[0][0], certSubject)) { + HAPVERIFY_LOG_ERROR(LABEL, "Get info of sign cert from ticket failed"); + return false; + } + + TrustedTicketManager& trustedTicketSourceManager = TrustedTicketManager::GetInstance(); + pkcs7Context.matchResult = trustedTicketSourceManager.IsTrustedSource(certSubject, pkcs7Context.certIssuer, + pkcs7Context.certChains[0].size()); + if (pkcs7Context.matchResult.matchState == DO_NOT_MATCH) { + HAPVERIFY_LOG_ERROR(LABEL, "Ticket signature is not trusted source, subject: %{public}s, issuer: %{public}s", + certSubject.c_str(), pkcs7Context.certIssuer.c_str()); + return false; + } + HAPVERIFY_LOG_INFO(LABEL, "Ticket subject: %{public}s, issuer: %{public}s", + certSubject.c_str(), pkcs7Context.certIssuer.c_str()); + return true; +} + +int TicketParseAndVerify(const std::string& Ticket, ProvisionInfo& ticketInfo, + const ProvisionInfo& profileInfo) +{ + if (ParseProvision(Ticket, ticketInfo) != PROVISION_OK) { + return TICKET_PARSE_FAIL; + } + int ret = CompareTicketAndProfile(ticketInfo, profileInfo); + if (ret != TICKET_OK) { + return ret; + } + if (CheckDevice(ticketInfo) != PROVISION_OK) { + return TICKET_DEVICE_INVALID; + } + return TICKET_OK; +} + +int VerifyTicket(const std::string& filePath, const ProvisionInfo& profileInfo) +{ + HAPVERIFY_LOG_DEBUG(LABEL, "Enter Ticket Verify"); + RandomAccessFile TicketFile; + if (!TicketFile.Init(filePath)) { + HAPVERIFY_LOG_ERROR(LABEL, "open %{public}s failed", filePath.c_str()); + return OPEN_TICKET_FILE_ERROR; + } + long long fileLength = TicketFile.GetLength(); + if (fileLength > TICKET_MAX_SIZE) { + HAPVERIFY_LOG_ERROR(LABEL, "file length %{public}lld is too larger", fileLength); + return OPEN_TICKET_FILE_ERROR; + } + int fileLen = static_cast(fileLength); + HapByteBuffer ticketBlock(fileLen); + long long ret = TicketFile.ReadFileFullyFromOffset(ticketBlock, 0); + if (ret < 0) { + HAPVERIFY_LOG_ERROR(LABEL, "read data from ticket error: %{public}lld", ret); + return TICKET_READ_FAIL; + } + + Pkcs7Context pkcs7Context; + std::string ticket; + if (!VerifyTicketSignature(ticketBlock, pkcs7Context, ticket)) { + HAPVERIFY_LOG_ERROR(LABEL, "verify ticket signature failed"); + return SIGNATURE_VERIFY_FAIL; + } + + ProvisionInfo ticketInfo; + int ticketRet = TicketParseAndVerify(ticket, ticketInfo, profileInfo); + if (ticketRet != TICKET_OK) { + HAPVERIFY_LOG_ERROR(LABEL, "ticket parse failed, error: %{public}d", static_cast(ticketRet)); + return ticketRet; + } + HAPVERIFY_LOG_DEBUG(LABEL, "Leave Ticket Verify"); + return TICKET_VERIFY_SUCCESS; +} + +bool CheckTicketSource(const ProvisionInfo& profileInfo) +{ + std::string ticketfilepath = TICKET_FILE_PATH + profileInfo.bundleInfo.bundleName + ".p7b"; + std::string standardFilePath; + if (!CheckTicketFilePath(ticketfilepath, standardFilePath)) { + return false; + } + + int ret = VerifyTicket(standardFilePath, profileInfo); + if (ret != TICKET_VERIFY_SUCCESS) { + HAPVERIFY_LOG_ERROR(LABEL, "ticket verify failed, result: %{public}d", ret); + return false; + } + HAPVERIFY_LOG_INFO(LABEL, "Ticket verify success"); + return true; +} +} // namespace Verify +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp b/interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp index 12b6ae546db9e82e74d9b35b2397f70a93df497a..a1129bce41c68a98a9dcd62655da2964f1328eaf 100644 --- a/interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp +++ b/interfaces/innerkits/appverify/src/verify/hap_verify_v2.cpp @@ -27,6 +27,7 @@ #include "util/hap_profile_verify_utils.h" #include "util/hap_signing_block_utils.h" #include "util/signature_info.h" +#include "ticket/ticket_verify.h" namespace OHOS { namespace Security { @@ -238,7 +239,7 @@ bool HapVerifyV2::VerifyProfileInfo(const Pkcs7Context& pkcs7Context, const Pkcs } std::string& certInProfile = provisionInfo.bundleInfo.developmentCertificate; if (provisionInfo.type == ProvisionType::RELEASE) { - if (!IsAppDistributedTypeAllowInstall(provisionInfo.distributionType)) { + if (!IsAppDistributedTypeAllowInstall(provisionInfo.distributionType, provisionInfo)) { HAPVERIFY_LOG_ERROR(LABEL, "untrusted source app with release profile distributionType: %{public}d", static_cast(provisionInfo.distributionType)); return false; @@ -255,11 +256,16 @@ bool HapVerifyV2::VerifyProfileInfo(const Pkcs7Context& pkcs7Context, const Pkcs return true; } -bool HapVerifyV2::IsAppDistributedTypeAllowInstall(const AppDistType& type) const +bool HapVerifyV2::IsAppDistributedTypeAllowInstall(const AppDistType& type, const ProvisionInfo& provisionInfo) const { switch (type) { case AppDistType::NONE_TYPE: + return false; case AppDistType::APP_GALLERY: + if (CheckTicketSource(provisionInfo)) { + HAPVERIFY_LOG_INFO(LABEL, "current device is allowed to install opentest application"); + return true; + } return false; case AppDistType::ENTERPRISE: case AppDistType::OS_INTEGRATION: diff --git a/interfaces/innerkits/appverify/test/BUILD.gn b/interfaces/innerkits/appverify/test/BUILD.gn index 302dcd7bee8be77e9997382e17dd79f677344002..edeca09d16d5196595cd96d35ad25baa7bf91b30 100644 --- a/interfaces/innerkits/appverify/test/BUILD.gn +++ b/interfaces/innerkits/appverify/test/BUILD.gn @@ -43,6 +43,7 @@ ohos_unittest("verify_test") { "unittest/src/provision_verify_test.cpp", "unittest/src/random_access_file_test.cpp", "unittest/src/trusted_root_ca_test.cpp", + "unittest/src/trusted_ticket_test.cpp", ] configs = [ ":verify_test_config" ] diff --git a/interfaces/innerkits/appverify/test/unittest/include/trusted_ticket_test.h b/interfaces/innerkits/appverify/test/unittest/include/trusted_ticket_test.h new file mode 100644 index 0000000000000000000000000000000000000000..47357da6379f7f70b15d6e44bd912e82f419fbec --- /dev/null +++ b/interfaces/innerkits/appverify/test/unittest/include/trusted_ticket_test.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 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_TRUSTED_TICKET_TEST_H +#define HAP_TRUSTED_TICKET_TEST_H + +#include "test_const.h" + +int CreatTrustedTicketCA001(void); +int IsTrustedSourceTest001(void); +int IsTrustedSourceTest002(void); +#endif // HAP_TRUSTED_TICKET_TEST_H \ No newline at end of file diff --git a/interfaces/innerkits/appverify/test/unittest/src/trusted_ticket_test.cpp b/interfaces/innerkits/appverify/test/unittest/src/trusted_ticket_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6442c319b4c0a7897955b2a5f6fc341908013606 --- /dev/null +++ b/interfaces/innerkits/appverify/test/unittest/src/trusted_ticket_test.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2021 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 "trusted_ticket_test.h" + +#include + +#include "init/trusted_ticket_manager.h" + +using namespace testing::ext; +using namespace OHOS::Security::Verify; + +namespace { +class TrustedTicketTest : public testing::Test { +public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp(); + + void TearDown(); +}; + +void TrustedTicketTest::SetUpTestCase(void) +{ +} + +void TrustedTicketTest::TearDownTestCase(void) +{ +} + +void TrustedTicketTest::SetUp() +{ +} + +void TrustedTicketTest::TearDown() +{ +} + +/** + * @tc.name: Test trusted root init and debug mode + * @tc.desc: The static function will return true; + * @tc.type: FUNC + */ +HWTEST_F (TrustedTicketTest, CreatTrustedTicketCA001, TestSize.Level1) +{ + /* + * @tc.steps: step1. run init and recovery. + * @tc.expected: step1. the return will true. + */ + TrustedTicketManager& trustedticketsource = TrustedTicketManager::GetInstance(); + ASSERT_TRUE(trustedticketsource.Init()); + trustedticketsource.Recovery(); + ASSERT_TRUE(trustedticketsource.Init()); +} + +/** + * @tc.name: Test IsTrustedSource function + * @tc.desc: The static function will return object of matched cert; + * @tc.type: FUNC + */ +HWTEST_F (TrustedTicketTest, IsTrustedSourceTest001, TestSize.Level1) +{ + /* + * @tc.steps: step1. input nullptr. + * @tc.expected: step1. the return will be DO_NOT_MATCH, because certSubject and certIssuer are not matched. + */ + TrustedTicketManager& trustedticketsource = TrustedTicketManager::GetInstance(); + std::string certSubject = ""; + std::string certIssuer = ""; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject, certIssuer, 3).matchState == DO_NOT_MATCH); + /* + * @tc.steps: step2. input invalid certSubject and valid certIssuer. + * @tc.expected: step2. the return will be DO_NOT_MATCH, because invalid certSubject. + */ + certSubject = "C=CN, O=Huawei, OU=MemberCenter, CN=MemberShip Ticket Release V1"; + certIssuer = "C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject, certIssuer, 3).matchState == DO_NOT_MATCH); + /* + * @tc.steps: step3. input valid certSubject and invalid certIssuer. + * @tc.expected: step3. the return will be DO_NOT_MATCH, because invalid certIssuer. + */ + certSubject = "C=CN, O=Huawei, OU=MemberCenter, CN=MemberShip ticket Release V1"; + certIssuer = "C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject, certIssuer, 3).matchState == DO_NOT_MATCH); + /* + * @tc.steps: step4. input valid certSubject and certIssuer. + * @tc.expected: step4. the return will be MATCH_WITH_TICKET. + */ + certSubject = "C=CN, O=Huawei, OU=MemberCenter, CN=MemberShip ticket Release V1"; + certIssuer = "C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject, certIssuer, 3).matchState == MATCH_WITH_TICKET); + /* + * @tc.steps: step5. input invalid certListpath. + * @tc.expected: step5. the return will be DO_NOT_MATCH, because certListpath is not matched. + */ + certSubject = "C=CN, O=Huawei, OU=MemberCenter, CN=MemberShip ticket Release V1"; + certIssuer = "C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject, certIssuer, 2).matchState == DO_NOT_MATCH); +} + +HWTEST_F (TrustedTicketTest, IsTrustedSourceTest002, TestSize.Level1) +{ + /* + * @tc.steps: step1. input invalid certsubject. + * @tc.expected: step1. the return will be DO_NOT_MATCH, because invalid certSubject. + */ + TrustedTicketManager& trustedticketsource = TrustedTicketManager::GetInstance(); + std::string certSubject1 = "C=CN, O=Huawei, OU=MemberCenter, CN=MemberShip ticket Release V0"; + std::string certIssuer = "C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Software Signing Service CA"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject1, certIssuer, 3).matchState == DO_NOT_MATCH); + /* + * @tc.steps: step2. input invalid certsubject. + * @tc.expected: step2. the return will be DO_NOT_MATCH, because invalid certSubject. + */ + std::string certSubject2 = "C=CN, O=Huawei, OU=MemberCenter, CN=MemberShip ticket Release V01"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject2, certIssuer, 3).matchState == DO_NOT_MATCH); + /* + * @tc.steps: step3. input valid certsubject. + * @tc.expected: step3. the return will be MATCH_WITH_TICKET. + */ + std::string certSubject3 = "C=CN, O=Huawei, OU=MemberCenter, CN=MemberShip ticket Release V2"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject3, certIssuer, 3).matchState == MATCH_WITH_TICKET); + /* + * @tc.steps: step4. input valid certsubject. + * @tc.expected: step4. the return will be MATCH_WITH_TICKET. + */ + std::string certSubject4 = "C=CN, O=Huawei, OU=MemberCenter, CN=MemberShip ticket Release V109"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject4, certIssuer, 3).matchState == MATCH_WITH_TICKET); + /* + * @tc.steps: step5. input valid and invalid certsubject. + * @tc.expected: step5. the return will be DO_NOT_MATCH, because invalid certSubject. + */ + std::string certSubject5 = "C=CN, O=Huawei, OU=Member Center, CN=MemberShip ticket Release V6"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject5, certIssuer, 3).matchState == DO_NOT_MATCH); + /* + * @tc.steps: step6. input invalid certsubject. + * @tc.expected: step6. the return will be DO_NOT_MATCH, because invalid certSubject. + */ + std::string certSubject6 = "C=CN, O=Other, OU=MemberCenter, CN=MemberShip ticket Release V8"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject6, certIssuer, 3).matchState == DO_NOT_MATCH); + /* + * @tc.steps: step7. input invalid certsubject. + * @tc.expected: step6. the return will be DO_NOT_MATCH, because invalid certSubject. + */ + std::string certSubject7 = "1C=CN, O=Other, OU=MemberCenter, CN=MemberShip ticket Release V9"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject7, certIssuer, 3).matchState == DO_NOT_MATCH); + /* + * @tc.steps: step8. input invalid certsubject. + * @tc.expected: step6. the return will be DO_NOT_MATCH, because invalid certSubject. + */ + std::string certSubject8 = "C=CN, O=Other, OU=MemberCenter, CN=MemberShip ticket Release V9 9"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject8, certIssuer, 3).matchState == DO_NOT_MATCH); + /* + * @tc.steps: step9. input invalid certsubject. + * @tc.expected: step6. the return will be DO_NOT_MATCH, because invalid certSubject. + */ + std::string certSubject9 = "C=CN, O=Other, OU=MemberCenter, CN=MemberShip ticket Release V9a"; + ASSERT_TRUE(trustedticketsource.IsTrustedSource(certSubject9, certIssuer, 3).matchState == DO_NOT_MATCH); + +} +}