1 /*
2 * Copyright (c) 2023 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 "napi_cert_crl_collection.h"
17
18 #include "cf_log.h"
19 #include "cf_memory.h"
20 #include "cf_object_base.h"
21 #include "cf_result.h"
22 #include "config.h"
23 #include "napi/native_api.h"
24 #include "napi/native_node_api.h"
25 #include "napi_common.h"
26 #include "napi_cert_defines.h"
27 #include "napi_cert_utils.h"
28 #include "napi_pub_key.h"
29 #include "napi_x509_certificate.h"
30 #include "napi_x509_crl.h"
31 #include "napi_x509_cert_match_parameters.h"
32 #include "napi_x509_crl_match_parameters.h"
33 #include "napi_cert_crl_common.h"
34 #include "securec.h"
35 #include "utils.h"
36
37 namespace OHOS {
38 namespace CertFramework {
39 thread_local napi_ref NapiCertCRLCollection::classRef_ = nullptr;
40
41 struct CfCertCRLColCtx {
42 AsyncType asyncType = ASYNC_TYPE_CALLBACK;
43 napi_value promise = nullptr;
44 napi_ref callback = nullptr;
45 napi_deferred deferred = nullptr;
46 napi_async_work asyncWork = nullptr;
47 CfResult errCode = CF_SUCCESS;
48 const char *errMsg = nullptr;
49
50 NapiCertCRLCollection *certCRLColClass = nullptr;
51 HcfX509CertMatchParams *certMatchParam = nullptr;
52 HcfX509CrlMatchParams *crlMatchParam = nullptr;
53 HcfX509CertificateArray retCerts { nullptr, 0 };
54 HcfX509CrlArray retCrls { nullptr, 0 };
55 };
56
FreeCryptoFwkCtx(napi_env env,CfCertCRLColCtx * & context)57 static void FreeCryptoFwkCtx(napi_env env, CfCertCRLColCtx *&context)
58 {
59 if (context == nullptr) {
60 return;
61 }
62
63 if (context->asyncWork != nullptr) {
64 napi_delete_async_work(env, context->asyncWork);
65 }
66
67 if (context->callback != nullptr) {
68 napi_delete_reference(env, context->callback);
69 }
70
71 if (context->certMatchParam != nullptr) {
72 FreeX509CertMatchParams(context->certMatchParam);
73 }
74 if (context->crlMatchParam != nullptr) {
75 FreeX509CrlMatchParams(context->crlMatchParam);
76 }
77 CF_FREE_PTR(context->retCerts.data);
78 context->retCerts.count = 0;
79 CF_FREE_PTR(context->retCrls.data);
80 context->retCrls.count = 0;
81
82 CF_FREE_PTR(context);
83 }
84
ReturnCallbackResult(napi_env env,CfCertCRLColCtx * context,napi_value result)85 static void ReturnCallbackResult(napi_env env, CfCertCRLColCtx *context, napi_value result)
86 {
87 napi_value businessError = nullptr;
88 if (context->errCode != CF_SUCCESS) {
89 businessError = CertGenerateBusinessError(env, context->errCode, context->errMsg);
90 }
91 napi_value params[ARGS_SIZE_TWO] = { businessError, result };
92
93 napi_value func = nullptr;
94 napi_get_reference_value(env, context->callback, &func);
95
96 napi_value recv = nullptr;
97 napi_value callFuncRet = nullptr;
98 napi_get_undefined(env, &recv);
99 napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
100 }
101
ReturnPromiseResult(napi_env env,CfCertCRLColCtx * context,napi_value result)102 static void ReturnPromiseResult(napi_env env, CfCertCRLColCtx *context, napi_value result)
103 {
104 if (context->errCode == CF_SUCCESS) {
105 napi_resolve_deferred(env, context->deferred, result);
106 } else {
107 napi_reject_deferred(env, context->deferred, CertGenerateBusinessError(env, context->errCode, context->errMsg));
108 }
109 }
110
ReturnResult(napi_env env,CfCertCRLColCtx * context,napi_value result)111 static void ReturnResult(napi_env env, CfCertCRLColCtx *context, napi_value result)
112 {
113 if (context->asyncType == ASYNC_TYPE_CALLBACK) {
114 ReturnCallbackResult(env, context, result);
115 } else {
116 ReturnPromiseResult(env, context, result);
117 }
118 }
119
CreateCallbackAndPromise(napi_env env,CfCertCRLColCtx * context,size_t argc,size_t maxCount,napi_value callbackValue)120 static bool CreateCallbackAndPromise(
121 napi_env env, CfCertCRLColCtx *context, size_t argc, size_t maxCount, napi_value callbackValue)
122 {
123 context->asyncType = GetAsyncType(env, argc, maxCount, callbackValue);
124 if (context->asyncType == ASYNC_TYPE_CALLBACK) {
125 if (!CertGetCallbackFromJSParams(env, callbackValue, &context->callback)) {
126 LOGE("CerCRLColletion: get callback failed!");
127 return false;
128 }
129 } else {
130 napi_create_promise(env, &context->deferred, &context->promise);
131 }
132 return true;
133 }
134
NapiCertCRLCollection(HcfCertCrlCollection * collection)135 NapiCertCRLCollection::NapiCertCRLCollection(HcfCertCrlCollection *collection)
136 {
137 certCrlCollection_ = collection;
138 }
139
~NapiCertCRLCollection()140 NapiCertCRLCollection::~NapiCertCRLCollection()
141 {
142 CfObjDestroy(this->certCrlCollection_);
143 }
144
SelectCRLsRet(napi_env env,const HcfX509CrlArray * crls)145 napi_value NapiCertCRLCollection::SelectCRLsRet(napi_env env, const HcfX509CrlArray *crls)
146 {
147 napi_value instance;
148 napi_create_array(env, &instance);
149 if (instance == nullptr) {
150 LOGE("create return array failed!");
151 return nullptr;
152 }
153 if (crls == nullptr) {
154 LOGI("return emtpy erray!");
155 return instance;
156 }
157 int j = 0;
158 for (uint32_t i = 0; i < crls->count; ++i) {
159 HcfX509Crl *crl = crls->data[i];
160 NapiX509Crl *x509Crl = new (std::nothrow) NapiX509Crl(crl);
161 if (x509Crl == nullptr) {
162 LOGE("new x509Crl failed!");
163 continue;
164 }
165 napi_value element = NapiX509Crl::CreateX509Crl(env, "createX509CRL");
166 napi_wrap(
167 env, element, x509Crl,
168 [](napi_env env, void *data, void *hint) {
169 NapiX509Crl *crl = static_cast<NapiX509Crl *>(data);
170 delete crl;
171 return;
172 },
173 nullptr, nullptr);
174 napi_set_element(env, instance, j++, element);
175 }
176 return instance;
177 }
178
SelectCertsExecute(napi_env env,void * data)179 static void SelectCertsExecute(napi_env env, void *data)
180 {
181 LOGI("enter SelectCertsExecute");
182 CfCertCRLColCtx *context = static_cast<CfCertCRLColCtx *>(data);
183 NapiCertCRLCollection *certCrlCol = context->certCRLColClass;
184 HcfCertCrlCollection *collection = certCrlCol->GetCertCrlCollection();
185 CfResult res = collection->selectCerts(collection, context->certMatchParam, &context->retCerts);
186 if (res != CF_SUCCESS) {
187 LOGE("selectCerts failed!");
188 context->errCode = res;
189 context->errMsg = "selectCerts failed!";
190 }
191 }
192
SelectCertsComplete(napi_env env,napi_status status,void * data)193 static void SelectCertsComplete(napi_env env, napi_status status, void *data)
194 {
195 LOGI("enter SelectCertsComplete");
196 CfCertCRLColCtx *context = static_cast<CfCertCRLColCtx *>(data);
197 if (context->errCode != CF_SUCCESS) {
198 ReturnResult(env, context, nullptr);
199 FreeCryptoFwkCtx(env, context);
200 return;
201 }
202 napi_value instance = ConvertCertArrToNapiValue(env, &context->retCerts);
203 ReturnResult(env, context, instance);
204 FreeCryptoFwkCtx(env, context);
205 }
206
NapiSelectCerts(napi_env env,napi_callback_info info)207 static napi_value NapiSelectCerts(napi_env env, napi_callback_info info)
208 {
209 LOGI("enter NapiSelectCerts");
210 napi_value thisVar = nullptr;
211 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
212 if (thisVar == nullptr) {
213 LOGE("thisVar is nullptr");
214 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "thisVar is nullptr."));
215 return nullptr;
216 }
217 NapiCertCRLCollection *certCrlCol = nullptr;
218 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&certCrlCol));
219 if (certCrlCol == nullptr) {
220 LOGE("certCrlCol is nullptr!");
221 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "certCrlCol is nullptr."));
222 return nullptr;
223 }
224 return certCrlCol->SelectCerts(env, info);
225 }
226
SelectCerts(napi_env env,napi_callback_info info)227 napi_value NapiCertCRLCollection::SelectCerts(napi_env env, napi_callback_info info)
228 {
229 size_t argc = ARGS_SIZE_TWO;
230 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
231 napi_value thisVar = nullptr;
232 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
233 if (!CertCheckArgsCount(env, argc, ARGS_SIZE_TWO, false)) {
234 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "CertCheckArgsCount failed."));
235 LOGE("CertCheckArgsCount is not 2!");
236 return nullptr;
237 }
238
239 CfCertCRLColCtx *context = static_cast<CfCertCRLColCtx *>(HcfMalloc(sizeof(CfCertCRLColCtx), 0));
240 if (context == nullptr) {
241 napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc context failed"));
242 LOGE("malloc context failed!");
243 return nullptr;
244 }
245 context->certCRLColClass = this;
246
247 HcfX509CertMatchParams *param = static_cast<HcfX509CertMatchParams *>(HcfMalloc(sizeof(HcfX509CertMatchParams), 0));
248 if (param == nullptr) {
249 napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc matchParams failed"));
250 LOGE("malloc matchParams failed!");
251 CfFree(context);
252 return nullptr;
253 }
254 if (!BuildX509CertMatchParams(env, argv[PARAM0], param)) {
255 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "BuildX509CertMatchParams failed"));
256 LOGE("BuildX509CertMatchParams failed!");
257 CfFree(context);
258 FreeX509CertMatchParams(param);
259 return nullptr;
260 }
261 context->certMatchParam = param;
262 if (!CreateCallbackAndPromise(env, context, argc, ARGS_SIZE_TWO, argv[PARAM1])) {
263 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "CreateCallbackAndPromise failed"));
264 LOGE("CreateCallbackAndPromise failed!");
265 FreeCryptoFwkCtx(env, context);
266 return nullptr;
267 }
268 napi_create_async_work(env, nullptr, CertGetResourceName(env, "SelectCerts"), SelectCertsExecute,
269 SelectCertsComplete, static_cast<void *>(context), &context->asyncWork);
270
271 napi_queue_async_work(env, context->asyncWork);
272 if (context->asyncType == ASYNC_TYPE_PROMISE) {
273 return context->promise;
274 } else {
275 return CertNapiGetNull(env);
276 }
277 }
278
NapiSelectCRLs(napi_env env,napi_callback_info info)279 static napi_value NapiSelectCRLs(napi_env env, napi_callback_info info)
280 {
281 LOGI("enter NapiSelectCRLs");
282 napi_value thisVar = nullptr;
283 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
284 if (thisVar == nullptr) {
285 LOGE("thisVar is nullptr");
286 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "thisVar is nullptr."));
287 return nullptr;
288 }
289 NapiCertCRLCollection *certCrlCol = nullptr;
290 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&certCrlCol));
291 if (certCrlCol == nullptr) {
292 LOGE("certCrlCol is nullptr!");
293 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "certCrlCol is nullptr."));
294 return nullptr;
295 }
296 return certCrlCol->SelectCRLs(env, info);
297 }
298
SelectCRLExecute(napi_env env,void * data)299 static void SelectCRLExecute(napi_env env, void *data)
300 {
301 CfCertCRLColCtx *context = static_cast<CfCertCRLColCtx *>(data);
302 NapiCertCRLCollection *certCrlCol = context->certCRLColClass;
303 HcfCertCrlCollection *collection = certCrlCol->GetCertCrlCollection();
304 CfResult res = collection->selectCRLs(collection, context->crlMatchParam, &context->retCrls);
305 if (res != CF_SUCCESS) {
306 LOGE("selectCrls failed!");
307 context->errCode = res;
308 context->errMsg = "selectCrls failed!";
309 }
310 }
311
SelectCRLComplete(napi_env env,napi_status status,void * data)312 static void SelectCRLComplete(napi_env env, napi_status status, void *data)
313 {
314 CfCertCRLColCtx *context = static_cast<CfCertCRLColCtx *>(data);
315 if (context->errCode != CF_SUCCESS) {
316 ReturnResult(env, context, nullptr);
317 FreeCryptoFwkCtx(env, context);
318 return;
319 }
320 NapiCertCRLCollection *certCrlCol = context->certCRLColClass;
321 napi_value instance = certCrlCol->SelectCRLsRet(env, &context->retCrls);
322 ReturnResult(env, context, instance);
323 FreeCryptoFwkCtx(env, context);
324 }
325
SelectCRLs(napi_env env,napi_callback_info info)326 napi_value NapiCertCRLCollection::SelectCRLs(napi_env env, napi_callback_info info)
327 {
328 size_t argc = ARGS_SIZE_TWO;
329 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
330 napi_value thisVar = nullptr;
331 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
332 if (!CertCheckArgsCount(env, argc, ARGS_SIZE_TWO, false)) {
333 return nullptr;
334 }
335
336 CfCertCRLColCtx *context = static_cast<CfCertCRLColCtx *>(HcfMalloc(sizeof(CfCertCRLColCtx), 0));
337 if (context == nullptr) {
338 napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc context failed"));
339 LOGE("malloc context failed!");
340 return nullptr;
341 }
342 context->certCRLColClass = this;
343 HcfX509CrlMatchParams *param = static_cast<HcfX509CrlMatchParams *>(HcfMalloc(sizeof(HcfX509CrlMatchParams), 0));
344 if (param == nullptr) {
345 napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc matchParams failed"));
346 LOGE("malloc matchParams failed!");
347 CfFree(context);
348 return nullptr;
349 }
350 if (!BuildX509CrlMatchParams(env, argv[PARAM0], param)) {
351 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "BuildX509CrlMatchParams failed"));
352 LOGE("BuildX509CrlMatchParamss failed!");
353 CfFree(context);
354 FreeX509CrlMatchParams(param);
355 return nullptr;
356 }
357 context->crlMatchParam = param;
358
359 if (!CreateCallbackAndPromise(env, context, argc, ARGS_SIZE_TWO, argv[PARAM1])) {
360 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "CreateCallbackAndPromise failed"));
361 LOGE("BuildX509CrlMatchParamss failed!");
362 FreeCryptoFwkCtx(env, context);
363 return nullptr;
364 }
365
366 napi_create_async_work(env, nullptr, CertGetResourceName(env, "SelectCRLs"), SelectCRLExecute, SelectCRLComplete,
367 static_cast<void *>(context), &context->asyncWork);
368
369 napi_queue_async_work(env, context->asyncWork);
370 if (context->asyncType == ASYNC_TYPE_PROMISE) {
371 return context->promise;
372 } else {
373 return CertNapiGetNull(env);
374 }
375 }
376
CertCRLColConstructor(napi_env env,napi_callback_info info)377 static napi_value CertCRLColConstructor(napi_env env, napi_callback_info info)
378 {
379 napi_value thisVar = nullptr;
380 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
381 return thisVar;
382 }
383
ParseCreateCertCRLColJSParams(napi_env env,napi_callback_info info,HcfCertCrlCollection * & out)384 static CfResult ParseCreateCertCRLColJSParams(napi_env env, napi_callback_info info, HcfCertCrlCollection *&out)
385 {
386 size_t argc = ARGS_SIZE_TWO;
387 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
388 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
389 HcfX509CertificateArray certs = { nullptr, 0 };
390 if (argc > PARAM0 && !GetArrayCertFromNapiValue(env, argv[PARAM0], &certs)) {
391 LOGE("get array cert from data failed!");
392 return CF_INVALID_PARAMS;
393 }
394 HcfX509CrlArray crls = { nullptr, 0 };
395 if (argc > PARAM1 && !GetArrayCRLFromNapiValue(env, argv[PARAM1], &crls)) {
396 LOGE("get array crl from data failed!");
397 CF_FREE_PTR(certs.data);
398 return CF_INVALID_PARAMS;
399 }
400
401 HcfCertCrlCollection *collection = nullptr;
402 CfResult res = HcfCertCrlCollectionCreate(&certs, &crls, &collection);
403 if (res != CF_SUCCESS) {
404 LOGE("get array crl from data failed!");
405 CF_FREE_PTR(certs.data);
406 CF_FREE_PTR(crls.data);
407 return res;
408 }
409 CF_FREE_PTR(certs.data);
410 CF_FREE_PTR(crls.data);
411 out = collection;
412 return CF_SUCCESS;
413 }
414
NapiCreateCertCRLCollection(napi_env env,napi_callback_info info)415 static napi_value NapiCreateCertCRLCollection(napi_env env, napi_callback_info info)
416 {
417 LOGI("enter NapiCreateCertCRLCollection");
418 HcfCertCrlCollection *collection = nullptr;
419 CfResult res = ParseCreateCertCRLColJSParams(env, info, collection);
420 if (res != CF_SUCCESS) {
421 LOGE("Failed to parse JS params for create certcrlcollection object");
422 napi_throw(env, CertGenerateBusinessError(env, res, "parse param failed."));
423 return nullptr;
424 }
425 NapiCertCRLCollection *napiObject = new (std::nothrow) NapiCertCRLCollection(collection);
426 if (napiObject == nullptr) {
427 LOGE("Failed to create napi certcrlcolletion class");
428 napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc napiObject failed."));
429 return nullptr;
430 }
431
432 napi_value instance = NapiCertCRLCollection::CreateCertCRLCollection(env);
433 napi_wrap(
434 env, instance, napiObject,
435 [](napi_env env, void *data, void *hint) {
436 NapiCertCRLCollection *objClass = static_cast<NapiCertCRLCollection *>(data);
437 delete objClass;
438 return;
439 },
440 nullptr, nullptr);
441
442 return instance;
443 }
444
DefineCertCRLCollectionJSClass(napi_env env,napi_value exports)445 void NapiCertCRLCollection::DefineCertCRLCollectionJSClass(napi_env env, napi_value exports)
446 {
447 napi_property_descriptor desc[] = {
448 DECLARE_NAPI_FUNCTION("createCertCRLCollection", NapiCreateCertCRLCollection),
449 };
450 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
451
452 napi_property_descriptor certCrlColDesc[] = {
453 DECLARE_NAPI_FUNCTION("selectCerts", NapiSelectCerts),
454 DECLARE_NAPI_FUNCTION("selectCRLs", NapiSelectCRLs),
455 };
456 napi_value constructor = nullptr;
457 napi_define_class(env, "CertCrlCollection", NAPI_AUTO_LENGTH, CertCRLColConstructor, nullptr,
458 sizeof(certCrlColDesc) / sizeof(certCrlColDesc[0]), certCrlColDesc, &constructor);
459
460 napi_create_reference(env, constructor, 1, &classRef_);
461 }
462
CreateCertCRLCollection(napi_env env)463 napi_value NapiCertCRLCollection::CreateCertCRLCollection(napi_env env)
464 {
465 napi_value constructor = nullptr;
466 napi_value instance = nullptr;
467 napi_get_reference_value(env, classRef_, &constructor);
468 napi_new_instance(env, constructor, 0, nullptr, &instance);
469 return instance;
470 }
471 } // namespace CertFramework
472 } // namespace OHOS
473