1 /*
2 * Copyright (c) 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 "cm_napi_user_trusted_cert.h"
17
18 #include "securec.h"
19
20 #include "cert_manager_api.h"
21 #include "cm_log.h"
22 #include "cm_mem.h"
23 #include "cm_type.h"
24 #include "cm_napi_common.h"
25
26 namespace CMNapi {
27 namespace {
28 constexpr int CM_NAPI_USER_INSTALL_ARGS_CNT = 2;
29 constexpr int CM_NAPI_USER_UNINSTALL_ARGS_CNT = 2;
30 constexpr int CM_NAPI_USER_UNINSTALL_ALL_ARGS_CNT = 1;
31 constexpr int CM_NAPI_CALLBACK_ARG_CNT = 1;
32 constexpr uint32_t OUT_AUTH_URI_SIZE = 1000;
33 } // namespace
34
35 struct UserCertAsyncContextT {
36 napi_async_work asyncWork = nullptr;
37 napi_deferred deferred = nullptr;
38 napi_ref callback = nullptr;
39
40 int32_t errCode = 0;
41
42 struct CmBlob *userCert = nullptr;
43 struct CmBlob *certAlias = nullptr;
44 struct CmBlob *certUri = nullptr;
45 };
46 using UserCertAsyncContext = UserCertAsyncContextT *;
47
InitUserCertAsyncContext(void)48 static UserCertAsyncContext InitUserCertAsyncContext(void)
49 {
50 UserCertAsyncContext context = static_cast<UserCertAsyncContext>(CmMalloc(sizeof(UserCertAsyncContextT)));
51 if (context != nullptr) {
52 (void)memset_s(context, sizeof(UserCertAsyncContextT), 0, sizeof(UserCertAsyncContextT));
53 }
54 return context;
55 }
56
FreeUserCertAsyncContext(napi_env env,UserCertAsyncContext & context)57 static void FreeUserCertAsyncContext(napi_env env, UserCertAsyncContext &context)
58 {
59 if (context == nullptr) {
60 return;
61 }
62
63 DeleteNapiContext(env, context->asyncWork, context->callback);
64 FreeCmBlob(context->userCert);
65 FreeCmBlob(context->certAlias);
66 FreeCmBlob(context->certUri);
67 CM_FREE_PTR(context);
68 }
69
GetUserCertData(napi_env env,napi_value object,UserCertAsyncContext context)70 static int32_t GetUserCertData(napi_env env, napi_value object, UserCertAsyncContext context)
71 {
72 context->userCert = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
73 if (context->userCert == nullptr) {
74 CM_LOG_E("could not alloc userCert blob memory");
75 return CMR_ERROR_MALLOC_FAIL;
76 }
77 (void)memset_s(context->userCert, sizeof(CmBlob), 0, sizeof(CmBlob));
78
79 napi_value result = GetUint8Array(env, object, *(context->userCert));
80 if (result == nullptr) {
81 CM_LOG_E("could not get userCert data");
82 return CMR_ERROR_INVALID_OPERATION;
83 }
84
85 return CM_SUCCESS;
86 }
87
GetCertAliasData(napi_env env,napi_value object,UserCertAsyncContext context)88 static int32_t GetCertAliasData(napi_env env, napi_value object, UserCertAsyncContext context)
89 {
90 napi_value result = ParseCertAlias(env, object, context->certAlias);
91 if (result == nullptr) {
92 CM_LOG_E("could not get certAlias data");
93 return CMR_ERROR_INVALID_OPERATION;
94 }
95
96 return CM_SUCCESS;
97 }
98
ParseCertInfo(napi_env env,napi_value object,UserCertAsyncContext context)99 static napi_value ParseCertInfo(napi_env env, napi_value object, UserCertAsyncContext context)
100 {
101 napi_valuetype type = napi_undefined;
102 NAPI_CALL(env, napi_typeof(env, object, &type));
103 if (type != napi_object) {
104 CM_LOG_E("type of param CertBlob is not object");
105 return nullptr;
106 }
107
108 napi_value userCertValue = nullptr;
109 napi_status status = napi_get_named_property(env, object, "inData", &userCertValue);
110 if (status != napi_ok || userCertValue == nullptr) {
111 CM_LOG_E("get inData failed");
112 return nullptr;
113 }
114
115 napi_value certAliasValue = nullptr;
116 status = napi_get_named_property(env, object, "alias", &certAliasValue);
117 if (status != napi_ok || certAliasValue == nullptr) {
118 CM_LOG_E("get cert alias failed");
119 return nullptr;
120 }
121
122 int32_t ret = GetUserCertData(env, userCertValue, context);
123 if (ret != CM_SUCCESS) {
124 return nullptr;
125 }
126
127 ret = GetCertAliasData(env, certAliasValue, context);
128 if (ret != CM_SUCCESS) {
129 return nullptr;
130 }
131
132 return GetInt32(env, 0);
133 }
134
ParseInstallUserCertParams(napi_env env,napi_callback_info info,UserCertAsyncContext context)135 static napi_value ParseInstallUserCertParams(napi_env env, napi_callback_info info, UserCertAsyncContext context)
136 {
137 size_t argc = CM_NAPI_USER_INSTALL_ARGS_CNT;
138 napi_value argv[CM_NAPI_USER_INSTALL_ARGS_CNT] = { nullptr };
139 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
140
141 if ((argc != CM_NAPI_USER_INSTALL_ARGS_CNT) &&
142 (argc != (CM_NAPI_USER_INSTALL_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
143 ThrowError(env, PARAM_ERROR, "arguments count invalid when installing user cert");
144 CM_LOG_E("arguments count is not expected when installing user cert");
145 return nullptr;
146 }
147
148 size_t index = 0;
149 napi_value result = ParseCertInfo(env, argv[index], context);
150 if (result == nullptr) {
151 ThrowError(env, PARAM_ERROR, "get context type error");
152 CM_LOG_E("get CertBlob failed when installing user cert");
153 return nullptr;
154 }
155
156 index++;
157 if (index < argc) {
158 int32_t ret = GetCallback(env, argv[index], context->callback);
159 if (ret != CM_SUCCESS) {
160 ThrowError(env, PARAM_ERROR, "Get callback type failed.");
161 CM_LOG_E("get callback function failed when install user cert");
162 return nullptr;
163 }
164 }
165
166 return GetInt32(env, 0);
167 }
168
ParseUninstallUserCertParams(napi_env env,napi_callback_info info,UserCertAsyncContext context)169 static napi_value ParseUninstallUserCertParams(napi_env env, napi_callback_info info, UserCertAsyncContext context)
170 {
171 size_t argc = CM_NAPI_USER_UNINSTALL_ARGS_CNT;
172 napi_value argv[CM_NAPI_USER_UNINSTALL_ARGS_CNT] = { nullptr };
173 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
174
175 if ((argc != CM_NAPI_USER_UNINSTALL_ARGS_CNT) &&
176 (argc != (CM_NAPI_USER_UNINSTALL_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
177 ThrowError(env, PARAM_ERROR, "arguments count invalid when uninstalling user cert");
178 CM_LOG_E("arguments count is not expected when uninstalling user cert");
179 return nullptr;
180 }
181
182 size_t index = 0;
183 napi_value result = ParseString(env, argv[index], context->certUri);
184 if (result == nullptr) {
185 ThrowError(env, PARAM_ERROR, "get certUri type error");
186 CM_LOG_E("get CertBlob failed when uninstalling user cert");
187 return nullptr;
188 }
189
190 index++;
191 if (index < argc) {
192 int32_t ret = GetCallback(env, argv[index], context->callback);
193 if (ret != CM_SUCCESS) {
194 ThrowError(env, PARAM_ERROR, "Get callback type failed.");
195 CM_LOG_E("get callback function failed when uninstalling user cert");
196 return nullptr;
197 }
198 }
199
200 return GetInt32(env, 0);
201 }
202
ParseUninstallAllUserCertParams(napi_env env,napi_callback_info info,UserCertAsyncContext context)203 static napi_value ParseUninstallAllUserCertParams(napi_env env, napi_callback_info info, UserCertAsyncContext context)
204 {
205 size_t argc = CM_NAPI_USER_UNINSTALL_ALL_ARGS_CNT;
206 napi_value argv[CM_NAPI_USER_UNINSTALL_ALL_ARGS_CNT] = { nullptr };
207 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
208
209 if ((argc != CM_NAPI_USER_UNINSTALL_ALL_ARGS_CNT) &&
210 (argc != (CM_NAPI_USER_UNINSTALL_ALL_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
211 ThrowError(env, PARAM_ERROR, "arguments count invalid when uninstalling all user cert");
212 CM_LOG_E("arguments count is not expected when uninstalling all user cert");
213 return nullptr;
214 }
215
216 size_t index = 0;
217 if (index < argc) {
218 int32_t ret = GetCallback(env, argv[index], context->callback);
219 if (ret != CM_SUCCESS) {
220 ThrowError(env, PARAM_ERROR, "Get callback type failed.");
221 CM_LOG_E("get callback function failed when uninstalling all user cert");
222 return nullptr;
223 }
224 }
225
226 return GetInt32(env, 0);
227 }
228
InstallUserCertExecute(napi_env env,void * data)229 static void InstallUserCertExecute(napi_env env, void *data)
230 {
231 UserCertAsyncContext context = static_cast<UserCertAsyncContext>(data);
232 context->certUri = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
233 if (context->certUri == nullptr) {
234 CM_LOG_E("malloc certUri failed");
235 context->errCode = CMR_ERROR_MALLOC_FAIL;
236 return;
237 }
238 (void)memset_s(context->certUri, sizeof(CmBlob), 0, sizeof(CmBlob));
239
240 context->certUri->data = static_cast<uint8_t *>(CmMalloc(OUT_AUTH_URI_SIZE));
241 if (context->certUri->data == nullptr) {
242 CM_LOG_E("malloc certUri.data failed");
243 context->errCode = CMR_ERROR_MALLOC_FAIL;
244 return;
245 }
246 (void)memset_s(context->certUri->data, OUT_AUTH_URI_SIZE, 0, OUT_AUTH_URI_SIZE);
247 context->certUri->size = OUT_AUTH_URI_SIZE;
248
249 context->errCode = CmInstallUserTrustedCert(context->userCert, context->certAlias, context->certUri);
250 }
251
ConvertResultCertUri(napi_env env,const CmBlob * certUri)252 static napi_value ConvertResultCertUri(napi_env env, const CmBlob *certUri)
253 {
254 napi_value result = nullptr;
255 NAPI_CALL(env, napi_create_object(env, &result));
256
257 napi_value certUriNapi = nullptr;
258 NAPI_CALL(env, napi_create_string_latin1(env, reinterpret_cast<const char *>(certUri->data),
259 NAPI_AUTO_LENGTH, &certUriNapi));
260 NAPI_CALL(env, napi_set_named_property(env, result, "uri", certUriNapi));
261
262 return result;
263 }
264
InstallUserCertComplete(napi_env env,napi_status status,void * data)265 static void InstallUserCertComplete(napi_env env, napi_status status, void *data)
266 {
267 UserCertAsyncContext context = static_cast<UserCertAsyncContext>(data);
268 napi_value result[RESULT_NUMBER] = { nullptr };
269 if (context->errCode == CM_SUCCESS) {
270 napi_create_uint32(env, 0, &result[0]);
271 result[1] = ConvertResultCertUri(env, context->certUri);
272 } else {
273 result[0] = GenerateBusinessError(env, context->errCode);
274 napi_get_undefined(env, &result[1]);
275 }
276
277 if (context->deferred != nullptr) {
278 GeneratePromise(env, context->deferred, context->errCode, result, CM_ARRAY_SIZE(result));
279 } else {
280 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->errCode);
281 }
282 FreeUserCertAsyncContext(env, context);
283 }
284
InstallUserCertAsyncWork(napi_env env,UserCertAsyncContext context)285 static napi_value InstallUserCertAsyncWork(napi_env env, UserCertAsyncContext context)
286 {
287 napi_value promise = nullptr;
288 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
289
290 napi_value resourceName = nullptr;
291 NAPI_CALL(env, napi_create_string_latin1(env, "installUserCertAsyncWork", NAPI_AUTO_LENGTH, &resourceName));
292
293 NAPI_CALL(env, napi_create_async_work(
294 env, nullptr, resourceName,
295 InstallUserCertExecute,
296 InstallUserCertComplete,
297 static_cast<void *>(context),
298 &context->asyncWork));
299
300 napi_status status = napi_queue_async_work(env, context->asyncWork);
301 if (status != napi_ok) {
302 ThrowError(env, PARAM_ERROR, "queue async work error");
303 CM_LOG_E("queue async work failed when installing user cert");
304 return nullptr;
305 }
306 return promise;
307 }
308
UninstallUserCertExecute(napi_env env,void * data)309 static void UninstallUserCertExecute(napi_env env, void *data)
310 {
311 UserCertAsyncContext context = static_cast<UserCertAsyncContext>(data);
312 context->errCode = CmUninstallUserTrustedCert(context->certUri);
313 }
314
UninstallComplete(napi_env env,napi_status status,void * data)315 static void UninstallComplete(napi_env env, napi_status status, void *data)
316 {
317 UserCertAsyncContext context = static_cast<UserCertAsyncContext>(data);
318 napi_value result[RESULT_NUMBER] = { nullptr };
319 if (context->errCode == CM_SUCCESS) {
320 napi_create_uint32(env, 0, &result[0]);
321 napi_get_boolean(env, true, &result[1]);
322 } else {
323 result[0] = GenerateBusinessError(env, context->errCode);
324 napi_get_undefined(env, &result[1]);
325 }
326
327 if (context->deferred != nullptr) {
328 GeneratePromise(env, context->deferred, context->errCode, result, CM_ARRAY_SIZE(result));
329 } else {
330 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->errCode);
331 }
332 FreeUserCertAsyncContext(env, context);
333 }
334
UninstallUserCertAsyncWork(napi_env env,UserCertAsyncContext context)335 static napi_value UninstallUserCertAsyncWork(napi_env env, UserCertAsyncContext context)
336 {
337 napi_value promise = nullptr;
338 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
339
340 napi_value resourceName = nullptr;
341 NAPI_CALL(env, napi_create_string_latin1(env, "uninstallUserCertAsyncWork", NAPI_AUTO_LENGTH, &resourceName));
342
343 NAPI_CALL(env, napi_create_async_work(
344 env, nullptr, resourceName,
345 UninstallUserCertExecute,
346 UninstallComplete,
347 static_cast<void *>(context),
348 &context->asyncWork));
349
350 napi_status status = napi_queue_async_work(env, context->asyncWork);
351 if (status != napi_ok) {
352 ThrowError(env, PARAM_ERROR, "queue async work error");
353 CM_LOG_E("queue async work failed when uninstalling user cert");
354 return nullptr;
355 }
356 return promise;
357 }
358
UninstallAllUserCertExecute(napi_env env,void * data)359 static void UninstallAllUserCertExecute(napi_env env, void *data)
360 {
361 UserCertAsyncContext context = static_cast<UserCertAsyncContext>(data);
362 context->errCode = CmUninstallAllUserTrustedCert();
363 }
364
UninstallAllUserCertAsyncWork(napi_env env,UserCertAsyncContext context)365 static napi_value UninstallAllUserCertAsyncWork(napi_env env, UserCertAsyncContext context)
366 {
367 napi_value promise = nullptr;
368 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
369
370 napi_value resourceName = nullptr;
371 NAPI_CALL(env, napi_create_string_latin1(env, "uninstallAllUserCertAsyncWork", NAPI_AUTO_LENGTH, &resourceName));
372
373 NAPI_CALL(env, napi_create_async_work(
374 env, nullptr, resourceName,
375 UninstallAllUserCertExecute,
376 UninstallComplete,
377 static_cast<void *>(context),
378 &context->asyncWork));
379
380 napi_status status = napi_queue_async_work(env, context->asyncWork);
381 if (status != napi_ok) {
382 ThrowError(env, PARAM_ERROR, "queue async work error");
383 CM_LOG_E("queue async work failed uninstall all user cert");
384 return nullptr;
385 }
386 return promise;
387 }
388
CMNapiInstallUserTrustedCert(napi_env env,napi_callback_info info)389 napi_value CMNapiInstallUserTrustedCert(napi_env env, napi_callback_info info)
390 {
391 UserCertAsyncContext context = InitUserCertAsyncContext();
392 if (context == nullptr) {
393 CM_LOG_E("init install user cert context failed");
394 return nullptr;
395 }
396
397 napi_value result = ParseInstallUserCertParams(env, info, context);
398 if (result == nullptr) {
399 CM_LOG_E("parse install user cert params failed");
400 FreeUserCertAsyncContext(env, context);
401 return nullptr;
402 }
403
404 result = InstallUserCertAsyncWork(env, context);
405 if (result == nullptr) {
406 CM_LOG_E("start install user cert async work failed");
407 FreeUserCertAsyncContext(env, context);
408 return nullptr;
409 }
410
411 return result;
412 }
413
CMNapiUninstallUserTrustedCert(napi_env env,napi_callback_info info)414 napi_value CMNapiUninstallUserTrustedCert(napi_env env, napi_callback_info info)
415 {
416 UserCertAsyncContext context = InitUserCertAsyncContext();
417 if (context == nullptr) {
418 CM_LOG_E("init uninstall user cert context failed");
419 return nullptr;
420 }
421
422 napi_value result = ParseUninstallUserCertParams(env, info, context);
423 if (result == nullptr) {
424 CM_LOG_E("parse uninstall user cert params failed");
425 FreeUserCertAsyncContext(env, context);
426 return nullptr;
427 }
428
429 result = UninstallUserCertAsyncWork(env, context);
430 if (result == nullptr) {
431 CM_LOG_E("start uninstall user cert async work failed");
432 FreeUserCertAsyncContext(env, context);
433 return nullptr;
434 }
435
436 return result;
437 }
438
CMNapiUninstallAllUserTrustedCert(napi_env env,napi_callback_info info)439 napi_value CMNapiUninstallAllUserTrustedCert(napi_env env, napi_callback_info info)
440 {
441 UserCertAsyncContext context = InitUserCertAsyncContext();
442 if (context == nullptr) {
443 CM_LOG_E("init uninstall all user cert context failed");
444 return nullptr;
445 }
446
447 napi_value result = ParseUninstallAllUserCertParams(env, info, context);
448 if (result == nullptr) {
449 CM_LOG_E("parse uninstall all user cert params failed");
450 FreeUserCertAsyncContext(env, context);
451 return nullptr;
452 }
453
454 result = UninstallAllUserCertAsyncWork(env, context);
455 if (result == nullptr) {
456 CM_LOG_E("start uninstall all user cert async work failed");
457 FreeUserCertAsyncContext(env, context);
458 return nullptr;
459 }
460
461 return result;
462 }
463 } // namespace CMNapi
464
465