• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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