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 "common/hap_verify_log.h"
19 
20 namespace OHOS {
21 namespace Security {
22 namespace Verify {
23 const std::string TrustedSourceManager::APP_TRUSTED_SOURCE_FILE_PATH =
24     "/system/etc/security/trusted_apps_sources.json";
25 const std::string TrustedSourceManager::APP_TRUSTED_SOURCE_TEST_FILE_PATH =
26     "/system/etc/security/trusted_apps_sources_test.json";
27 const std::string TrustedSourceManager::KEY_OF_APP_TRUSTED_SOURCE = "trust-app-source";
28 const std::string TrustedSourceManager::KEY_OF_APP_TRUSTED_SOURCE_VERSION = "version";
29 const std::string TrustedSourceManager::KEY_OF_APP_TRUSTED_SOURCE_RELEASETIME = "release-time";
30 const std::string TrustedSourceManager::KEY_OF_SOURCE_NAME = "name";
31 const std::string TrustedSourceManager::KEY_OF_APP_SIGNING_CERT = "app-signing-cert";
32 const std::string TrustedSourceManager::KEY_OF_PROFILE_SIGNING_CERTIFICATE = "profile-signing-certificate";
33 const std::string TrustedSourceManager::KEY_OF_PROFILE_DEBUG_SIGNING_CERTIFICATE = "profile-debug-signing-certificate";
34 const std::string TrustedSourceManager::KEY_OF_ISSUER = "issuer-ca";
35 const std::string TrustedSourceManager::KEY_OF_ROOT_CA = "root-ca";
36 const std::string TrustedSourceManager::KEY_OF_MAX_CERTS_PATH = "max-certs-path";
37 const std::string TrustedSourceManager::KEY_OF_CRITIALCAL_CERT_EXTENSION = "critialcal-cert-extension";
38 const std::string TrustedSourceManager::APP_GALLERY_SOURCE_NAME = "huawei app gallery";
39 const std::string TrustedSourceManager::APP_SYSTEM_SOURCE_NAME = "huawei system apps";
40 const std::string TrustedSourceManager::APP_THIRD_PARTY_PRELOAD_SOURCE_NAME = "third_party app preload";
41 
GetInstance()42 TrustedSourceManager& TrustedSourceManager::GetInstance()
43 {
44     static TrustedSourceManager singleTrustedSourceManager;
45     return singleTrustedSourceManager;
46 }
47 
TrustedSourceManager()48 TrustedSourceManager::TrustedSourceManager()
49     : appTrustedSources(), appTrustedSourcesForTest(), version(), versionForTest(), releaseTime(),
50       releaseTimeForTest(), isInit(false), isDebug(false)
51 {
52 }
53 
~TrustedSourceManager()54 TrustedSourceManager::~TrustedSourceManager()
55 {
56 }
57 
EnableDebug()58 bool TrustedSourceManager::EnableDebug()
59 {
60     if (isDebug) {
61         return true;
62     }
63 
64     isDebug = GetAppTrustedSources(appTrustedSourcesForTest, versionForTest,
65         releaseTimeForTest, APP_TRUSTED_SOURCE_TEST_FILE_PATH);
66     if (isDebug) {
67         HAPVERIFY_LOG_INFO("trusted app source test version: %{public}s, releaseTime: %{public}s, Size:"
68             " %{public}zu", versionForTest.c_str(), releaseTimeForTest.c_str(), appTrustedSourcesForTest.size());
69     }
70     return isDebug;
71 }
72 
DisableDebug()73 void TrustedSourceManager::DisableDebug()
74 {
75     isDebug = false;
76     appTrustedSourcesForTest.clear();
77 }
78 
Init()79 bool TrustedSourceManager::Init()
80 {
81     if (isInit) {
82         return true;
83     }
84 
85     isInit = GetAppTrustedSources(appTrustedSources, version, releaseTime, APP_TRUSTED_SOURCE_FILE_PATH);
86     if (isInit) {
87         HAPVERIFY_LOG_INFO("trusted app source version: %{public}s, releaseTime: %{public}s, Size:"
88             " %{public}zu", version.c_str(), releaseTime.c_str(), appTrustedSources.size());
89     }
90     return isInit;
91 }
92 
Recovery()93 void TrustedSourceManager::Recovery()
94 {
95     appTrustedSources.clear();
96     isInit = false;
97 }
98 
GetAppTrustedSources(SourceInfoVec & trustedAppSources,std::string & souucesVersion,std::string & souucesReleaseTime,const std::string & filePath)99 bool TrustedSourceManager::GetAppTrustedSources(SourceInfoVec& trustedAppSources, std::string& souucesVersion,
100     std::string& souucesReleaseTime, const std::string& filePath)
101 {
102     cJSON* trustedSourceJson = NULL;
103     std::string errorInfo;
104     if (!JsonParserUtils::ReadTrustedRootCAFromJson(&trustedSourceJson, filePath, errorInfo)) {
105         HAPVERIFY_LOG_ERROR("get jsonObj from %{public}s failed, because %{public}s",
106             filePath.c_str(), errorInfo.c_str());
107         return false;
108     }
109     if (!JsonParserUtils::GetJsonString(trustedSourceJson, KEY_OF_APP_TRUSTED_SOURCE_VERSION, souucesVersion)) {
110         HAPVERIFY_LOG_ERROR("get version failed");
111         cJSON_Delete(trustedSourceJson);
112         return false;
113     }
114     if (!JsonParserUtils::GetJsonString(trustedSourceJson,
115         KEY_OF_APP_TRUSTED_SOURCE_RELEASETIME, souucesReleaseTime)) {
116         HAPVERIFY_LOG_ERROR("get releaseTime failed");
117         cJSON_Delete(trustedSourceJson);
118         return false;
119     }
120     JsonObjVec trustedAppSourceJson;
121     if (!JsonParserUtils::ParseJsonToObjVec(trustedSourceJson, KEY_OF_APP_TRUSTED_SOURCE, trustedAppSourceJson)) {
122         HAPVERIFY_LOG_ERROR("get JsonObjVec failed");
123         cJSON_Delete(trustedSourceJson);
124         return false;
125     }
126     if (!ParseTrustedAppSourceJson(trustedAppSources, trustedAppSourceJson)) {
127         HAPVERIFY_LOG_ERROR("parse JsonObjVec failed");
128         cJSON_Delete(trustedSourceJson);
129         return false;
130     }
131     if (trustedAppSources.empty()) {
132         HAPVERIFY_LOG_ERROR("no app trusted source");
133         cJSON_Delete(trustedSourceJson);
134         return false;
135     }
136     cJSON_Delete(trustedSourceJson);
137     return true;
138 }
139 
ParseTrustedAppSourceJson(SourceInfoVec & trustedAppSources,const JsonObjVec & trustedAppSourceJson)140 bool TrustedSourceManager::ParseTrustedAppSourceJson(SourceInfoVec& trustedAppSources,
141     const JsonObjVec& trustedAppSourceJson)
142 {
143     for (auto appSource : trustedAppSourceJson) {
144         HapAppSourceInfo hapAppSource;
145         if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_SOURCE_NAME, hapAppSource.sourceName)) {
146             HAPVERIFY_LOG_ERROR("Get sourceName Failed");
147             return false;
148         }
149         hapAppSource.source = GetTrustedSource(hapAppSource.sourceName);
150         if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_APP_SIGNING_CERT, hapAppSource.appSigningCert)) {
151             HAPVERIFY_LOG_ERROR("Get appSigningCert Failed");
152             return false;
153         }
154         if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_PROFILE_SIGNING_CERTIFICATE,
155             hapAppSource.profileSigningCertificate)) {
156             HAPVERIFY_LOG_ERROR("Get profileSigningCertificate Failed");
157             return false;
158         }
159         if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_PROFILE_DEBUG_SIGNING_CERTIFICATE,
160             hapAppSource.profileDebugSigningCertificate)) {
161             HAPVERIFY_LOG_ERROR("Get profileDebugSigningCertificate Failed");
162             return false;
163         }
164         if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_ISSUER, hapAppSource.issuer)) {
165             HAPVERIFY_LOG_ERROR("Get issuer Failed");
166             return false;
167         }
168         if (!JsonParserUtils::GetJsonString(appSource, KEY_OF_ROOT_CA, hapAppSource.rootCa)) {
169             HAPVERIFY_LOG_ERROR("Get root ca Failed");
170             return false;
171         }
172         if (!JsonParserUtils::GetJsonInt(appSource, KEY_OF_MAX_CERTS_PATH, hapAppSource.maxCertsPath)) {
173             HAPVERIFY_LOG_ERROR("Get maxCertsPath Failed");
174             return false;
175         }
176         if (!JsonParserUtils::GetJsonStringVec(appSource, KEY_OF_CRITIALCAL_CERT_EXTENSION,
177             hapAppSource.critialcalCertExtension)) {
178             HAPVERIFY_LOG_ERROR("Get critialcalCertExtension Failed");
179             return false;
180         }
181         HAPVERIFY_LOG_INFO("trusted app source: %{public}s", EncapTrustedAppSourceString(hapAppSource).c_str());
182         trustedAppSources.push_back(hapAppSource);
183     }
184     return true;
185 }
186 
EncapTrustedAppSourceString(const HapAppSourceInfo & appSourceInfo)187 std::string TrustedSourceManager::EncapTrustedAppSourceString(const HapAppSourceInfo& appSourceInfo)
188 {
189     std::string info =  "sourceName: " + appSourceInfo.sourceName + "\n" +
190         "sourceNumber: " + std::to_string(static_cast<int>(appSourceInfo.source)) + "\n" +
191         "appSigningCert: " + appSourceInfo.appSigningCert + "\n" +
192         "profileSigningCertificate: " + appSourceInfo.profileSigningCertificate + "\n" +
193         "profileDebugSigningCertificate: " + appSourceInfo.profileDebugSigningCertificate + "\n" +
194         "issuer: " + appSourceInfo.issuer + "\n" +
195         "rootCa: " + appSourceInfo.rootCa + "\n" +
196         "maxCertsPath: " + std::to_string(appSourceInfo.maxCertsPath) + "\n" +
197         "critialcalCertExtension: ";
198     for (auto extension : appSourceInfo.critialcalCertExtension) {
199         info += extension + ", ";
200     }
201     return info;
202 }
203 
IsTrustedSource(const std::string & certSubject,const std::string & certIssuer,HapBlobType blobType,int32_t certListPath) const204 MatchingResult TrustedSourceManager::IsTrustedSource(const std::string& certSubject,
205     const std::string& certIssuer, HapBlobType blobType, int32_t certListPath) const
206 {
207     MatchingResult ret = MatchTrustedSource(appTrustedSources, certSubject, certIssuer, blobType, certListPath);
208     if (ret.matchState != DO_NOT_MATCH) {
209         return ret;
210     }
211 
212     if (isDebug) {
213         return MatchTrustedSource(appTrustedSourcesForTest, certSubject, certIssuer, blobType, certListPath);
214     }
215     return ret;
216 }
217 
MatchTrustedSource(const SourceInfoVec & trustedAppSources,const std::string & certSubject,const std::string & certIssuer,HapBlobType blobType,int32_t certListPath) const218 MatchingResult TrustedSourceManager::MatchTrustedSource(const SourceInfoVec& trustedAppSources,
219     const std::string& certSubject, const std::string& certIssuer, HapBlobType blobType, int32_t certListPath) const
220 {
221     MatchingResult ret;
222     ret.matchState = DO_NOT_MATCH;
223     for (auto appSource : trustedAppSources) {
224         if (certListPath == appSource.maxCertsPath) {
225             ret.matchState = TrustedSourceListCompare(certSubject, certIssuer, appSource, blobType);
226             if (ret.matchState != DO_NOT_MATCH) {
227                 ret.source = appSource.source;
228                 ret.rootCa = appSource.rootCa;
229                 break;
230             }
231         }
232     }
233     return ret;
234 }
235 
TrustedSourceListCompare(const std::string & certSubject,const std::string & certIssuer,const HapAppSourceInfo & appSource,HapBlobType blobType) const236 MatchingStates TrustedSourceManager::TrustedSourceListCompare(const std::string& certSubject,
237     const std::string& certIssuer, const HapAppSourceInfo& appSource, HapBlobType blobType) const
238 {
239     MatchingStates ret = DO_NOT_MATCH;
240     switch (blobType) {
241         case HAP_SIGN_BLOB: {
242             if (MatchSubjectAndIssuer(appSource.appSigningCert, certSubject) &&
243                 MatchSubjectAndIssuer(appSource.issuer, certIssuer)) {
244                 ret = MATCH_WITH_SIGN;
245             }
246             break;
247         }
248         case PROFILE_BLOB: {
249             if (MatchSubjectAndIssuer(appSource.issuer, certIssuer)) {
250                 if (MatchSubjectAndIssuer(appSource.profileSigningCertificate, certSubject)) {
251                     ret = MATCH_WITH_PROFILE;
252                 } else if (MatchSubjectAndIssuer(appSource.profileDebugSigningCertificate, certSubject)) {
253                     ret = MATCH_WITH_PROFILE_DEBUG;
254                 }
255             }
256             break;
257         }
258         default:
259             break;
260     }
261     return ret;
262 }
263 
GetTrustedSource(std::string & sourceName)264 TrustedSources TrustedSourceManager::GetTrustedSource(std::string& sourceName)
265 {
266     if (APP_GALLERY_SOURCE_NAME == sourceName) {
267         return APP_GALLARY;
268     }
269 
270     if (APP_SYSTEM_SOURCE_NAME == sourceName) {
271         return APP_SYSTEM;
272     }
273 
274     if (APP_THIRD_PARTY_PRELOAD_SOURCE_NAME == sourceName) {
275         return APP_THIRD_PARTY_PRELOAD;
276     }
277     return OTHER_TRUSTED_SOURCE;
278 }
279 
MatchSubjectAndIssuer(const std::string & trustedSource,const std::string & certSubjectOrIssuer) const280 bool TrustedSourceManager::MatchSubjectAndIssuer(const std::string& trustedSource,
281                                                  const std::string& certSubjectOrIssuer) const
282 {
283     if (trustedSource.empty()) {
284         return false;
285     }
286 
287     return trustedSource == certSubjectOrIssuer;
288 }
289 } // namespace Verify
290 } // namespace Security
291 } // namespace OHOS
292