1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "init/trusted_source_manager.h"
17
18 #include "nlohmann/json.hpp"
19
20 #include "common/hap_verify_log.h"
21
22 namespace OHOS {
23 namespace Security {
24 namespace Verify {
25 const std::string TrustedSourceManager::APP_TRUSTED_SOURCE_FILE_PATH =
26 "/system/etc/security/trusted_apps_sources.json";
27 const std::string TrustedSourceManager::APP_TRUSTED_SOURCE_TEST_FILE_PATH =
28 "/system/etc/security/trusted_apps_sources_test.json";
29 const std::string TrustedSourceManager::KEY_OF_APP_TRUSTED_SOURCE = "trust-app-source";
30 const std::string TrustedSourceManager::KEY_OF_APP_TRUSTED_SOURCE_VERSION = "version";
31 const std::string TrustedSourceManager::KEY_OF_APP_TRUSTED_SOURCE_RELEASETIME = "release-time";
32 const std::string TrustedSourceManager::KEY_OF_SOURCE_NAME = "name";
33 const std::string TrustedSourceManager::KEY_OF_APP_SIGNING_CERT = "app-signing-cert";
34 const std::string TrustedSourceManager::KEY_OF_PROFILE_SIGNING_CERTIFICATE = "profile-signing-certificate";
35 const std::string TrustedSourceManager::KEY_OF_PROFILE_DEBUG_SIGNING_CERTIFICATE = "profile-debug-signing-certificate";
36 const std::string TrustedSourceManager::KEY_OF_ISSUER = "issuer-ca";
37 const std::string TrustedSourceManager::KEY_OF_MAX_CERTS_PATH = "max-certs-path";
38 const std::string TrustedSourceManager::KEY_OF_CRITIALCAL_CERT_EXTENSION = "critialcal-cert-extension";
39 const std::string TrustedSourceManager::APP_GALLERY_SOURCE_NAME = "huawei app gallery";
40 const std::string TrustedSourceManager::APP_SYSTEM_SOURCE_NAME = "huawei system apps";
41 const std::string TrustedSourceManager::APP_THIRD_PARTY_PRELOAD_SOURCE_NAME = "third_party app preload";
42
GetInstance()43 TrustedSourceManager& TrustedSourceManager::GetInstance()
44 {
45 static TrustedSourceManager singleTrustedSourceManager;
46 return singleTrustedSourceManager;
47 }
48
TrustedSourceManager()49 TrustedSourceManager::TrustedSourceManager()
50 : appTrustedSources(), appTrustedSourcesForTest(), version(), versionForTest(), releaseTime(),
51 releaseTimeForTest(), isInit(false), isDebug(false)
52 {
53 }
54
~TrustedSourceManager()55 TrustedSourceManager::~TrustedSourceManager()
56 {
57 }
58
EnableDebug()59 bool TrustedSourceManager::EnableDebug()
60 {
61 if (isDebug) {
62 return true;
63 }
64
65 isDebug = GetAppTrustedSources(appTrustedSourcesForTest, versionForTest,
66 releaseTimeForTest, APP_TRUSTED_SOURCE_TEST_FILE_PATH);
67 if (isDebug) {
68 HAPVERIFY_LOG_INFO(LABEL, "trusted app source test version: %{public}s, releaseTime: %{public}s, Size:"
69 " %{public}zu", versionForTest.c_str(), releaseTimeForTest.c_str(), appTrustedSourcesForTest.size());
70 }
71 return isDebug;
72 }
73
DisableDebug()74 void TrustedSourceManager::DisableDebug()
75 {
76 isDebug = false;
77 appTrustedSourcesForTest.clear();
78 }
79
Init()80 bool TrustedSourceManager::Init()
81 {
82 if (isInit) {
83 return true;
84 }
85
86 isInit = GetAppTrustedSources(appTrustedSources, version, releaseTime, APP_TRUSTED_SOURCE_FILE_PATH);
87 if (isInit) {
88 HAPVERIFY_LOG_INFO(LABEL, "trusted app source version: %{public}s, releaseTime: %{public}s, Size:"
89 " %{public}zu", version.c_str(), releaseTime.c_str(), appTrustedSources.size());
90 }
91 return isInit;
92 }
93
Recovery()94 void TrustedSourceManager::Recovery()
95 {
96 appTrustedSources.clear();
97 isInit = false;
98 }
99
GetAppTrustedSources(SourceInfoVec & trustedAppSources,std::string & souucesVersion,std::string & souucesReleaseTime,const std::string & filePath)100 bool TrustedSourceManager::GetAppTrustedSources(SourceInfoVec& trustedAppSources, std::string& souucesVersion,
101 std::string& souucesReleaseTime, const std::string& filePath)
102 {
103 nlohmann::json trustedSourceJson;
104 std::string errorInfo;
105 if (!JsonParserUtils::ReadTrustedRootCAFromJson(trustedSourceJson, filePath, errorInfo)) {
106 HAPVERIFY_LOG_ERROR(LABEL, "get jsonObj from %{public}s failed, because %{public}s",
107 filePath.c_str(), errorInfo.c_str());
108 return false;
109 }
110 if (!JsonParserUtils::GetJsonString(trustedSourceJson, KEY_OF_APP_TRUSTED_SOURCE_VERSION, souucesVersion)) {
111 HAPVERIFY_LOG_ERROR(LABEL, "get version failed");
112 return false;
113 }
114 if (!JsonParserUtils::GetJsonString(trustedSourceJson,
115 KEY_OF_APP_TRUSTED_SOURCE_RELEASETIME, souucesReleaseTime)) {
116 HAPVERIFY_LOG_ERROR(LABEL, "get releaseTime failed");
117 return false;
118 }
119 JsonObjVec trustedAppSourceJson;
120 if (!JsonParserUtils::ParseJsonToObjVec(trustedSourceJson, KEY_OF_APP_TRUSTED_SOURCE, trustedAppSourceJson)) {
121 HAPVERIFY_LOG_ERROR(LABEL, "get JsonObjVec failed");
122 return false;
123 }
124 if (!ParseTrustedAppSourceJson(trustedAppSources, trustedAppSourceJson)) {
125 HAPVERIFY_LOG_ERROR(LABEL, "parse JsonObjVec failed");
126 return false;
127 }
128 if (trustedAppSources.empty()) {
129 HAPVERIFY_LOG_ERROR(LABEL, "no app trusted source");
130 return false;
131 }
132 return true;
133 }
134
ParseTrustedAppSourceJson(SourceInfoVec & trustedAppSources,const JsonObjVec & trustedAppSourceJson)135 bool TrustedSourceManager::ParseTrustedAppSourceJson(SourceInfoVec& trustedAppSources,
136 const JsonObjVec& trustedAppSourceJson)
137 {
138 for (auto appSource : trustedAppSourceJson) {
139 HapAppSourceInfo hapAppSource;
140 if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_SOURCE_NAME, hapAppSource.sourceName)) {
141 HAPVERIFY_LOG_ERROR(LABEL, "Get sourceName Failed");
142 return false;
143 }
144 hapAppSource.source = GetTrustedSource(hapAppSource.sourceName);
145 if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_APP_SIGNING_CERT, hapAppSource.appSigningCert)) {
146 HAPVERIFY_LOG_ERROR(LABEL, "Get appSigningCert Failed");
147 return false;
148 }
149 if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_PROFILE_SIGNING_CERTIFICATE,
150 hapAppSource.profileSigningCertificate)) {
151 HAPVERIFY_LOG_ERROR(LABEL, "Get profileSigningCertificate Failed");
152 return false;
153 }
154 if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_PROFILE_DEBUG_SIGNING_CERTIFICATE,
155 hapAppSource.profileDebugSigningCertificate)) {
156 HAPVERIFY_LOG_ERROR(LABEL, "Get profileDebugSigningCertificate Failed");
157 return false;
158 }
159 if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_ISSUER, hapAppSource.issuer)) {
160 HAPVERIFY_LOG_ERROR(LABEL, "Get issuer Failed");
161 return false;
162 }
163 if (!JsonParserUtils::GetJsonInt(appSource, KEY_OF_MAX_CERTS_PATH, hapAppSource.maxCertsPath)) {
164 HAPVERIFY_LOG_ERROR(LABEL, "Get maxCertsPath Failed");
165 return false;
166 }
167 if (!JsonParserUtils::GetJsonStringVec(appSource, KEY_OF_CRITIALCAL_CERT_EXTENSION,
168 hapAppSource.critialcalCertExtension)) {
169 HAPVERIFY_LOG_ERROR(LABEL, "Get critialcalCertExtension Failed");
170 return false;
171 }
172 HAPVERIFY_LOG_INFO(LABEL, "trusted app source: %{public}s", EncapTrustedAppSourceString(hapAppSource).c_str());
173 trustedAppSources.push_back(hapAppSource);
174 }
175 return true;
176 }
177
EncapTrustedAppSourceString(const HapAppSourceInfo & appSourceInfo)178 std::string TrustedSourceManager::EncapTrustedAppSourceString(const HapAppSourceInfo& appSourceInfo)
179 {
180 std::string info = "sourceName: " + appSourceInfo.sourceName + "\n" +
181 "sourceNumber: " + std::to_string(static_cast<int>(appSourceInfo.source)) + "\n" +
182 "appSigningCert: " + appSourceInfo.appSigningCert + "\n" +
183 "profileSigningCertificate: " + appSourceInfo.profileSigningCertificate + "\n" +
184 "profileDebugSigningCertificate: " + appSourceInfo.profileDebugSigningCertificate + "\n" +
185 "issuer: " + appSourceInfo.issuer + "\n" +
186 "maxCertsPath: " + std::to_string(appSourceInfo.maxCertsPath) + "\n" +
187 "critialcalCertExtension: ";
188 for (auto extension : appSourceInfo.critialcalCertExtension) {
189 info += extension + ", ";
190 }
191 return info;
192 }
193
IsTrustedSource(const std::string & certSubject,const std::string & certIssuer,HapBlobType blobType,int certListPath) const194 MatchingResult TrustedSourceManager::IsTrustedSource(const std::string& certSubject,
195 const std::string& certIssuer, HapBlobType blobType, int certListPath) const
196 {
197 MatchingResult ret = MatchTrustedSource(appTrustedSources, certSubject, certIssuer, blobType, certListPath);
198 if (ret.matchState != DO_NOT_MATCH) {
199 return ret;
200 }
201
202 if (isDebug) {
203 return MatchTrustedSource(appTrustedSourcesForTest, certSubject, certIssuer, blobType, certListPath);
204 }
205 return ret;
206 }
207
MatchTrustedSource(const SourceInfoVec & trustedAppSources,const std::string & certSubject,const std::string & certIssuer,HapBlobType blobType,int certListPath) const208 MatchingResult TrustedSourceManager::MatchTrustedSource(const SourceInfoVec& trustedAppSources,
209 const std::string& certSubject, const std::string& certIssuer, HapBlobType blobType, int certListPath) const
210 {
211 MatchingResult ret;
212 ret.matchState = DO_NOT_MATCH;
213 for (auto appSource : trustedAppSources) {
214 if (certListPath == appSource.maxCertsPath) {
215 ret.matchState = TrustedSourceListCompare(certSubject, certIssuer, appSource, blobType);
216 if (ret.matchState != DO_NOT_MATCH) {
217 ret.source = appSource.source;
218 break;
219 }
220 }
221 }
222 return ret;
223 }
224
TrustedSourceListCompare(const std::string & certSubject,const std::string & certIssuer,const HapAppSourceInfo & appSource,HapBlobType blobType) const225 MatchingStates TrustedSourceManager::TrustedSourceListCompare(const std::string& certSubject,
226 const std::string& certIssuer, const HapAppSourceInfo& appSource, HapBlobType blobType) const
227 {
228 MatchingStates ret = DO_NOT_MATCH;
229 switch (blobType) {
230 case HAP_SIGN_BLOB: {
231 if (MatchSubjectAndIssuer(appSource.appSigningCert, certSubject) &&
232 MatchSubjectAndIssuer(appSource.issuer, certIssuer)) {
233 ret = MATCH_WITH_SIGN;
234 }
235 break;
236 }
237 case PROFILE_BLOB: {
238 if (MatchSubjectAndIssuer(appSource.issuer, certIssuer)) {
239 if (MatchSubjectAndIssuer(appSource.profileSigningCertificate, certSubject)) {
240 ret = MATCH_WITH_PROFILE;
241 } else if (MatchSubjectAndIssuer(appSource.profileDebugSigningCertificate, certSubject)) {
242 ret = MATCH_WITH_PROFILE_DEBUG;
243 }
244 }
245 break;
246 }
247 default:
248 break;
249 }
250 return ret;
251 }
252
GetTrustedSource(std::string & sourceName)253 TrustedSources TrustedSourceManager::GetTrustedSource(std::string& sourceName)
254 {
255 if (APP_GALLERY_SOURCE_NAME == sourceName) {
256 return APP_GALLARY;
257 }
258
259 if (APP_SYSTEM_SOURCE_NAME == sourceName) {
260 return APP_SYSTEM;
261 }
262
263 if (APP_THIRD_PARTY_PRELOAD_SOURCE_NAME == sourceName) {
264 return APP_THIRD_PARTY_PRELOAD;
265 }
266 return OTHER_TRUSTED_SOURCE;
267 }
268
MatchSubjectAndIssuer(const std::string & trustedSource,const std::string & certSubjectOrIssuer) const269 bool TrustedSourceManager::MatchSubjectAndIssuer(const std::string& trustedSource,
270 const std::string& certSubjectOrIssuer) const
271 {
272 if (trustedSource.empty()) {
273 return false;
274 }
275
276 return trustedSource == certSubjectOrIssuer;
277 }
278 } // namespace Verify
279 } // namespace Security
280 } // namespace OHOS
281