1 /*
2 * Copyright (c) 2024-2025 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 "cm_napi_get_cert_store_path.h"
17
18 #include <unistd.h>
19
20 #include "cm_log.h"
21 #include "cm_napi_common.h"
22 #include "cm_type.h"
23
24 #include "bundle_mgr_proxy.h"
25 #include "iservice_registry.h"
26 #include "os_account_manager.h"
27 #include "system_ability_definition.h"
28
29 using namespace std;
30 using namespace OHOS;
31 using namespace OHOS::AppExecFwk;
32
33 namespace CMNapi {
34 namespace {
35 constexpr int CM_NAPI_GET_CERT_STORE_PATH_ARGS = 1;
36 }
37
GetBundleMgrProxy()38 static sptr<BundleMgrProxy> GetBundleMgrProxy()
39 {
40 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
41 if (!systemAbilityManager) {
42 CM_LOG_E("Failed to get system ability mgr.");
43 return nullptr;
44 }
45
46 auto remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
47 if (!remoteObject) {
48 CM_LOG_E("Failed to get bundle manager proxy.");
49 return nullptr;
50 }
51 return iface_cast<BundleMgrProxy>(remoteObject);
52 }
53
GetUserCaStorePath(const enum CmCertScope certScope,string & path)54 static int32_t GetUserCaStorePath(const enum CmCertScope certScope, string &path)
55 {
56 path += CA_STORE_PATH_USER_SANDBOX_BASE;
57 if (certScope == CM_GLOBAL_USER) {
58 path += "0";
59 return CM_SUCCESS;
60 }
61
62 int32_t userId = 0;
63 sptr<BundleMgrProxy> bundleMgrProxy = GetBundleMgrProxy();
64 if (bundleMgrProxy == nullptr) {
65 CM_LOG_E("Failed to get bundle manager proxy.");
66 return CM_FAILURE;
67 }
68
69 BundleInfo bundleInfo;
70 int32_t flags = static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_DEFAULT) |
71 static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION);
72 int32_t ret = bundleMgrProxy->GetBundleInfoForSelf(flags, bundleInfo);
73 if (ret != 0) {
74 CM_LOG_E("Failed to get bundle info for self");
75 return CM_FAILURE;
76 }
77
78 ret = AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(bundleInfo.applicationInfo.uid, userId);
79 if (ret != 0) {
80 CM_LOG_E("Failed to get userid from uid[%d]", bundleInfo.applicationInfo.uid);
81 return CM_FAILURE;
82 }
83
84 path += to_string(userId);
85 return CM_SUCCESS;
86 }
87
IsDirExist(const char * fileName)88 static bool IsDirExist(const char *fileName)
89 {
90 if (fileName == nullptr) {
91 return false;
92 }
93 if (access(fileName, F_OK) == 0) {
94 return true;
95 }
96 return false;
97 }
98
GetSysCaStorePath(napi_env env,const enum CmCertAlg certAlg,string & path)99 static int32_t GetSysCaStorePath(napi_env env, const enum CmCertAlg certAlg, string &path)
100 {
101 if (certAlg == CM_ALG_INTERNATIONAL) {
102 path = CA_STORE_PATH_SYSTEM;
103 return CM_SUCCESS;
104 }
105 if (!IsDirExist(SYSTEM_CA_STORE_GM)) {
106 CM_LOG_E("system gm ca store path not exist");
107 ThrowError(env, STORE_PATH_NOT_SUPPORTED, "the device does not support specified certificate store path");
108 return STORE_PATH_NOT_SUPPORTED;
109 } else {
110 path = CA_STORE_PATH_SYSTEM_SM;
111 }
112 return CM_SUCCESS;
113 }
114
GetCertStorePath(napi_env env,const enum CmCertType certType,const enum CmCertScope certScope,const enum CmCertAlg certAlg)115 static napi_value GetCertStorePath(napi_env env, const enum CmCertType certType, const enum CmCertScope certScope,
116 const enum CmCertAlg certAlg)
117 {
118 string path = "";
119 if (certType == CM_CA_CERT_SYSTEM) {
120 int32_t ret = GetSysCaStorePath(env, certAlg, path);
121 if (ret != CM_SUCCESS) {
122 CM_LOG_E("Failed to get system ca path, ret = %d", ret);
123 return nullptr;
124 }
125 } else {
126 int32_t ret = GetUserCaStorePath(certScope, path);
127 if (ret != CM_SUCCESS) {
128 CM_LOG_E("Failed to get user ca path.");
129 ThrowError(env, INNER_FAILURE, GENERIC_MSG);
130 return nullptr;
131 }
132 }
133
134 napi_value result = nullptr;
135 napi_status status = napi_create_string_utf8(env, path.c_str(), path.length(), &result);
136 if (status != napi_ok) {
137 CM_LOG_E("Failed to creat string out.");
138 ThrowError(env, INNER_FAILURE, GENERIC_MSG);
139 return nullptr;
140 }
141 return result;
142 }
143
GetCertScope(napi_env env,napi_value arg,uint32_t & scope)144 static int32_t GetCertScope(napi_env env, napi_value arg, uint32_t &scope)
145 {
146 bool hasScope = false;
147 napi_status status = napi_has_named_property(env, arg, CM_CERT_SCOPE_STR.c_str(), &hasScope);
148 if (status != napi_ok || !hasScope) {
149 CM_LOG_D("property certScope not exist");
150 return CM_SUCCESS; /* certScope is optional parameter, can be unset */
151 }
152
153 napi_value obj = nullptr;
154 status = napi_get_named_property(env, arg, CM_CERT_SCOPE_STR.c_str(), &obj);
155 if (status != napi_ok) {
156 CM_LOG_E("Failed to get property certScope");
157 return CM_FAILURE;
158 }
159
160 napi_valuetype valueType;
161 status = napi_typeof(env, obj, &valueType);
162 if (status != napi_ok) {
163 CM_LOG_E("Failed to get property type");
164 return CM_FAILURE;
165 }
166
167 if (valueType == napi_undefined) {
168 CM_LOG_D("property certScope is undefined");
169 return CM_SUCCESS; /* certScope is optional parameter, can be undefined */
170 }
171
172 napi_value result = ParseUint32(env, obj, scope);
173 if (result == nullptr) {
174 CM_LOG_E("Failed to get scope value");
175 return CM_FAILURE;
176 }
177
178 if (!IsValidCertScope(scope)) { /* the scope needs to be checked regardless of the certType type */
179 CM_LOG_E("certScope[%u] is invalid", scope);
180 return CM_FAILURE;
181 }
182
183 return CM_SUCCESS;
184 }
185
GetAndCheckCertType(napi_env env,napi_value arg,uint32_t & type)186 static int32_t GetAndCheckCertType(napi_env env, napi_value arg, uint32_t &type)
187 {
188 napi_value certType = nullptr;
189 napi_status status = napi_get_named_property(env, arg, CM_CERT_TYPE_STR.c_str(), &certType);
190 if (status != napi_ok) {
191 CM_LOG_E("Failed to get certType");
192 return CM_FAILURE;
193 }
194
195 napi_value result = ParseUint32(env, certType, type);
196 if (result == nullptr) {
197 CM_LOG_E("Failed to get certType value");
198 return CM_FAILURE;
199 }
200
201 if (!IsValidCertType(type)) {
202 CM_LOG_E("certType[%u] is invalid", type);
203 return CM_FAILURE;
204 }
205 return CM_SUCCESS;
206 }
207
GetAndCheckCertScope(napi_env env,napi_value arg,const enum CmCertType type,uint32_t & scope)208 static int32_t GetAndCheckCertScope(napi_env env, napi_value arg, const enum CmCertType type, uint32_t &scope)
209 {
210 int32_t ret = GetCertScope(env, arg, scope);
211 if (ret != CM_SUCCESS) {
212 CM_LOG_E("Failed to get certScope");
213 return CM_FAILURE;
214 }
215
216 if ((type == CM_CA_CERT_USER) && (scope == INIT_INVALID_VALUE)) {
217 CM_LOG_E("get user ca cert store path, but scope is not set");
218 return CM_FAILURE;
219 }
220 return CM_SUCCESS;
221 }
222
GetAndCheckCertAlg(napi_env env,napi_value arg,uint32_t & algorithm)223 static int32_t GetAndCheckCertAlg(napi_env env, napi_value arg, uint32_t &algorithm)
224 {
225 bool hasAlg = false;
226 napi_status status = napi_has_named_property(env, arg, CM_CERT_ALG_STR.c_str(), &hasAlg);
227 if (status != napi_ok || !hasAlg) {
228 CM_LOG_D("property certAlg not exist");
229 algorithm = CM_ALG_INTERNATIONAL;
230 return SUCCESS;
231 }
232
233 napi_value certAlg = nullptr;
234 status = napi_get_named_property(env, arg, CM_CERT_ALG_STR.c_str(), &certAlg);
235 if (status != napi_ok) {
236 CM_LOG_E("Failed to get certAlg");
237 return CM_FAILURE;
238 }
239
240 napi_value result = ParseUint32(env, certAlg, algorithm);
241 if (result == nullptr) {
242 CM_LOG_E("Failed to get certAlg value");
243 return CM_FAILURE;
244 }
245
246 if (!IsValidCertAlg(algorithm)) {
247 CM_LOG_E("certAlg[%u] is invalid", algorithm);
248 return CM_FAILURE;
249 }
250 return CM_SUCCESS;
251 }
252
CMNapiGetCertStorePath(napi_env env,napi_callback_info info)253 napi_value CMNapiGetCertStorePath(napi_env env, napi_callback_info info)
254 {
255 CM_LOG_I("get cert store path enter");
256 // get params
257 size_t argc = CM_NAPI_GET_CERT_STORE_PATH_ARGS;
258 napi_value argv[CM_NAPI_GET_CERT_STORE_PATH_ARGS] = { nullptr };
259 napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
260 if (status != napi_ok) {
261 ThrowError(env, PARAM_ERROR, "Failed to get params");
262 return nullptr;
263 }
264
265 // check param count should be 1.
266 if (argc != CM_NAPI_GET_CERT_STORE_PATH_ARGS) {
267 ThrowError(env, PARAM_ERROR, "param count invalid, should be 1.");
268 CM_LOG_E("args count[%zu] invalid, should be 1.", argc);
269 return nullptr;
270 }
271
272 uint32_t type;
273 int32_t ret = GetAndCheckCertType(env, argv[0], type);
274 if (ret != CM_SUCCESS) {
275 ThrowError(env, PARAM_ERROR, "Failed to get param certType");
276 return nullptr;
277 }
278
279 uint32_t scope = INIT_INVALID_VALUE;
280 ret = GetAndCheckCertScope(env, argv[0], static_cast<CmCertType>(type), scope);
281 if (ret != CM_SUCCESS) {
282 ThrowError(env, PARAM_ERROR, "Failed to get param certScope");
283 return nullptr;
284 }
285
286 uint32_t algorithm;
287 ret = GetAndCheckCertAlg(env, argv[0], algorithm);
288 if (ret != CM_SUCCESS) {
289 ThrowError(env, PARAM_ERROR, "Failed to get param certAlg");
290 return nullptr;
291 }
292
293 napi_value res = GetCertStorePath(env, static_cast<CmCertType>(type), static_cast<CmCertScope>(scope),
294 static_cast<CmCertAlg>(algorithm));
295 CM_LOG_I("get cert store path end");
296 return res;
297 }
298 } // namespace CertManagerNapi
299