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