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_get_system_cert_info.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_GET_CERT_INFO_MIN_ARGS = 1;
29 constexpr int CM_NAPI_GET_CERT_INFO_MAX_ARGS = 2;
30 } // namespace
31
32 struct GetCertInfoAsyncContextT {
33 napi_async_work asyncWork = nullptr;
34 napi_deferred deferred = nullptr;
35 napi_ref callback = nullptr;
36
37 int32_t result = 0;
38 struct CmBlob *certUri = nullptr;
39 uint32_t store = 0;
40 struct CertInfo *certificate = nullptr;
41 };
42 using GetCertInfoAsyncContext = GetCertInfoAsyncContextT *;
43
CreateGetCertInfoAsyncContext()44 static GetCertInfoAsyncContext CreateGetCertInfoAsyncContext()
45 {
46 GetCertInfoAsyncContext context =
47 static_cast<GetCertInfoAsyncContext>(CmMalloc(sizeof(GetCertInfoAsyncContextT)));
48 if (context != nullptr) {
49 (void)memset_s(
50 context, sizeof(GetCertInfoAsyncContextT), 0, sizeof(GetCertInfoAsyncContextT));
51 }
52 return context;
53 }
54
DeleteGetCertInfoAsyncContext(napi_env env,GetCertInfoAsyncContext & context)55 static void DeleteGetCertInfoAsyncContext(napi_env env, GetCertInfoAsyncContext &context)
56 {
57 if (context == nullptr) {
58 return;
59 }
60
61 DeleteNapiContext(env, context->asyncWork, context->callback);
62
63 if (context->certUri != nullptr) {
64 FreeCmBlob(context->certUri);
65 }
66
67 if (context->certificate != nullptr) {
68 FreeCertInfo(context->certificate);
69 }
70
71 CmFree(context);
72 context = nullptr;
73 }
74
GetCertInfoParseParams(napi_env env,napi_callback_info info,GetCertInfoAsyncContext context,uint32_t store)75 static napi_value GetCertInfoParseParams(napi_env env, napi_callback_info info,
76 GetCertInfoAsyncContext context, uint32_t store)
77 {
78 size_t argc = CM_NAPI_GET_CERT_INFO_MAX_ARGS;
79 napi_value argv[CM_NAPI_GET_CERT_INFO_MAX_ARGS] = { nullptr };
80 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
81
82 if ((argc != CM_NAPI_GET_CERT_INFO_MAX_ARGS) && (argc != CM_NAPI_GET_CERT_INFO_MIN_ARGS)) {
83 ThrowError(env, PARAM_ERROR, "arguments count invalid when getting trusted certificate info");
84 CM_LOG_E("arguments count invalid when getting trusted certificate info");
85 return nullptr;
86 }
87
88 size_t index = 0;
89 napi_value result = ParseString(env, argv[index], context->certUri);
90 if (result == nullptr) {
91 ThrowError(env, PARAM_ERROR, "certUri type error");
92 CM_LOG_E("get cert uri failed when getting trusted certificate info");
93 return nullptr;
94 }
95
96 index++;
97 if (index < argc) {
98 int32_t ret = GetCallback(env, argv[index], context->callback);
99 if (ret != CM_SUCCESS) {
100 ThrowError(env, PARAM_ERROR, "Get callback type failed.");
101 CM_LOG_E("get callback function failed when get cert info function");
102 return nullptr;
103 }
104 }
105
106 context->store = store;
107 return GetInt32(env, 0);
108 }
109
GetCertInfoWriteResult(napi_env env,GetCertInfoAsyncContext context)110 static napi_value GetCertInfoWriteResult(napi_env env, GetCertInfoAsyncContext context)
111 {
112 napi_value result = nullptr;
113 NAPI_CALL(env, napi_create_object(env, &result));
114 napi_value certInfo = GenerateCertInfo(env, context->certificate);
115 if (certInfo != nullptr) {
116 napi_set_named_property(env, result, CM_RESULT_PRPPERTY_CERTINFO.c_str(), certInfo);
117 } else {
118 NAPI_CALL(env, napi_get_undefined(env, &result));
119 }
120 return result;
121 }
122
GetCertInfoExecute(napi_env env,void * data)123 static void GetCertInfoExecute(napi_env env, void *data)
124 {
125 GetCertInfoAsyncContext context = static_cast<GetCertInfoAsyncContext>(data);
126
127 context->certificate = static_cast<struct CertInfo *>(CmMalloc(sizeof(struct CertInfo)));
128 if (context->certificate == nullptr) {
129 CM_LOG_E("malloc certificate fail");
130 context->result = CMR_ERROR_MALLOC_FAIL;
131 return;
132 }
133 (void)memset_s(context->certificate, sizeof(struct CertInfo), 0, sizeof(struct CertInfo));
134
135 context->certificate->certInfo.data = static_cast<uint8_t *>(CmMalloc(MAX_LEN_CERTIFICATE));
136 if (context->certificate->certInfo.data == nullptr) {
137 CM_LOG_E("malloc certificate certInfo data fail");
138 context->result = CMR_ERROR_MALLOC_FAIL;
139 return;
140 }
141 context->certificate->certInfo.size = MAX_LEN_CERTIFICATE;
142
143 if (context->store == CM_SYSTEM_TRUSTED_STORE) {
144 context->result = CmGetCertInfo(context->certUri, context->store,
145 context->certificate);
146 } else {
147 context->result = CmGetUserCertInfo(context->certUri, context->store, context->certificate);
148 }
149 }
150
GetCertInfoComplete(napi_env env,napi_status status,void * data)151 static void GetCertInfoComplete(napi_env env, napi_status status, void *data)
152 {
153 GetCertInfoAsyncContext context = static_cast<GetCertInfoAsyncContext>(data);
154 napi_value result[RESULT_NUMBER] = { nullptr };
155 if (context->result == CM_SUCCESS) {
156 NAPI_CALL_RETURN_VOID(env, napi_create_uint32(env, 0, &result[0]));
157 result[1] = GetCertInfoWriteResult(env, context);
158 } else {
159 result[0] = GenerateBusinessError(env, context->result);
160 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &result[1]));
161 }
162 if (context->deferred != nullptr) {
163 GeneratePromise(env, context->deferred, context->result, result, CM_ARRAY_SIZE(result));
164 } else {
165 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->result);
166 }
167 DeleteGetCertInfoAsyncContext(env, context);
168 CM_LOG_D("get system cert info end");
169 }
170
GetCertInfoAsyncWork(napi_env env,GetCertInfoAsyncContext context)171 static napi_value GetCertInfoAsyncWork(napi_env env, GetCertInfoAsyncContext context)
172 {
173 napi_value promise = nullptr;
174 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
175
176 napi_value resourceName = nullptr;
177 NAPI_CALL(env, napi_create_string_latin1(env, "GetCertInfoAsyncWork", NAPI_AUTO_LENGTH, &resourceName));
178
179 NAPI_CALL(env, napi_create_async_work(
180 env,
181 nullptr,
182 resourceName,
183 GetCertInfoExecute,
184 GetCertInfoComplete,
185 static_cast<void *>(context),
186 &context->asyncWork));
187 napi_status status = napi_queue_async_work(env, context->asyncWork);
188 if (status != napi_ok) {
189 GET_AND_THROW_LAST_ERROR((env));
190 DeleteGetCertInfoAsyncContext(env, context);
191 CM_LOG_E("get system cert info could not queue async work");
192 return nullptr;
193 }
194 return promise;
195 }
196
CMNapiGetSystemCertInfo(napi_env env,napi_callback_info info)197 napi_value CMNapiGetSystemCertInfo(napi_env env, napi_callback_info info)
198 {
199 GetCertInfoAsyncContext context = CreateGetCertInfoAsyncContext();
200 if (context == nullptr) {
201 CM_LOG_E("could not create context");
202 return nullptr;
203 }
204
205 napi_value result = GetCertInfoParseParams(env, info, context, CM_SYSTEM_TRUSTED_STORE);
206 if (result == nullptr) {
207 CM_LOG_E("could not parse params");
208 DeleteGetCertInfoAsyncContext(env, context);
209 return nullptr;
210 }
211 result = GetCertInfoAsyncWork(env, context);
212 if (result == nullptr) {
213 CM_LOG_E("could not start async work");
214 DeleteGetCertInfoAsyncContext(env, context);
215 return nullptr;
216 }
217 return result;
218 }
219
CMNapiGetUserTrustedCertInfo(napi_env env,napi_callback_info info)220 napi_value CMNapiGetUserTrustedCertInfo(napi_env env, napi_callback_info info)
221 {
222 GetCertInfoAsyncContext context = CreateGetCertInfoAsyncContext();
223 if (context == nullptr) {
224 CM_LOG_E("create cert info context failed");
225 return nullptr;
226 }
227
228 napi_value result = GetCertInfoParseParams(env, info, context, CM_USER_TRUSTED_STORE);
229 if (result == nullptr) {
230 CM_LOG_E("parse get cert info params failed");
231 DeleteGetCertInfoAsyncContext(env, context);
232 return nullptr;
233 }
234 result = GetCertInfoAsyncWork(env, context);
235 if (result == nullptr) {
236 CM_LOG_E("get cert info params async work failed");
237 DeleteGetCertInfoAsyncContext(env, context);
238 return nullptr;
239 }
240 return result;
241 }
242 } // namespace CertManagerNapi
243