• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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_x509_cert_chain.h"
17 
18 #include "cert_crl_common.h"
19 #include "cf_api.h"
20 #include "cf_log.h"
21 #include "cf_memory.h"
22 #include "cf_param.h"
23 #include "cf_result.h"
24 #include "napi/native_api.h"
25 #include "napi/native_common.h"
26 #include "napi_cert_crl_common.h"
27 #include "napi_cert_defines.h"
28 #include "napi_cert_utils.h"
29 #include "napi_common.h"
30 #include "napi_object.h"
31 #include "napi_x509_cert_chain_validate_params.h"
32 #include "napi_x509_cert_chain_validate_result.h"
33 #include "napi_x509_cert_match_parameters.h"
34 #include "napi_x509_trust_anchor.h"
35 #include "securec.h"
36 #include "x509_cert_chain.h"
37 #include "x509_cert_chain_validate_params.h"
38 #include "x509_certificate.h"
39 
40 namespace OHOS {
41 namespace CertFramework {
42 thread_local napi_ref NapiX509CertChain::classRef_ = nullptr;
43 thread_local napi_ref NapiX509CertChainBulidResult::classRef_ = nullptr;
44 
45 struct CfCtx {
46     AsyncCtx async;
47     napi_ref cfRef = nullptr;
48     napi_ref certChainValidateParamsRef = nullptr;
49     NapiX509CertChain *certChainClass = nullptr;
50     HcfCertChain *certChain = nullptr;
51     CfEncodingBlob *encodingBlob = nullptr;
52     HcfX509CertChainValidateParams params;
53     HcfX509CertChainValidateResult result;
54     HcfX509CertChainBuildParameters *buildParams = nullptr;
55     HcfX509CertChainBuildResult *buildResult = nullptr;
56     CfBlob *keyStore = nullptr;
57     CfBlob *pwd = nullptr;
58     HcfX509TrustAnchorArray *trustAnchorArray = nullptr;
59 };
60 
NapiX509CertChain(HcfCertChain * certChain)61 NapiX509CertChain::NapiX509CertChain(HcfCertChain *certChain)
62 {
63     this->certChain_ = certChain;
64 }
65 
~NapiX509CertChain()66 NapiX509CertChain::~NapiX509CertChain()
67 {
68     CfObjDestroy(this->certChain_);
69 }
70 
NapiX509CertChainBulidResult(HcfX509CertChainBuildResult * buildResult)71 NapiX509CertChainBulidResult::NapiX509CertChainBulidResult(HcfX509CertChainBuildResult *buildResult)
72 {
73     this->buildResult_ = buildResult;
74 }
75 
~NapiX509CertChainBulidResult()76 NapiX509CertChainBulidResult::~NapiX509CertChainBulidResult()
77 {
78     CfObjDestroy(this->buildResult_);
79 }
80 
BuildCertChainContext()81 static CfCtx *BuildCertChainContext()
82 {
83     CfCtx *context = static_cast<CfCtx *>(CfMalloc(sizeof(CfCtx), 0));
84     if (context == nullptr) {
85         LOGE("malloc cf ctx failed!");
86         return nullptr;
87     }
88     context->async = static_cast<AsyncCtx>(CfMalloc(sizeof(AsyncContext), 0));
89     if (context->async == nullptr) {
90         LOGE("malloc async ctx failed!");
91         CfFree(context);
92         context = nullptr;
93         return nullptr;
94     }
95     return context;
96 }
97 
DeleteCertChainContext(napi_env env,CfCtx * & context,bool freeCertFlag=false)98 static void DeleteCertChainContext(napi_env env, CfCtx *&context, bool freeCertFlag = false)
99 {
100     if (context == nullptr) {
101         return;
102     }
103 
104     FreeAsyncContext(env, context->async);
105 
106     if (context->cfRef != nullptr) {
107         napi_delete_reference(env, context->cfRef);
108         context->cfRef = nullptr;
109     }
110     if (context->certChainValidateParamsRef != nullptr) {
111         napi_delete_reference(env, context->certChainValidateParamsRef);
112         context->certChainValidateParamsRef = nullptr;
113     }
114 
115     if (context->encodingBlob != nullptr) {
116         CfEncodingBlobDataFree(context->encodingBlob);
117         CF_FREE_PTR(context->encodingBlob);
118     }
119 
120     FreeTrustAnchorArray(context->trustAnchorArray, freeCertFlag);
121     FreeX509CertChainValidateParams(context->params);
122     FreeX509CertChainValidateResult(context->result, freeCertFlag);
123 
124     CfBlobFree(&(context->keyStore));
125     CfBlobDataClearAndFree(context->pwd);
126     CfFree(context->pwd);
127     context->pwd = nullptr;
128 
129     CF_FREE_PTR(context);
130 }
131 
CreateCertChainJSInstance(napi_env env)132 static napi_value CreateCertChainJSInstance(napi_env env)
133 {
134     napi_value constructor = nullptr;
135     napi_value instance = nullptr;
136     napi_get_reference_value(env, NapiX509CertChain::classRef_, &constructor);
137     napi_new_instance(env, constructor, 0, nullptr, &instance);
138     return instance;
139 }
140 
CreateCallbackAndPromise(napi_env env,CfCtx * context,size_t argc,size_t maxCount,napi_value callbackValue)141 static bool CreateCallbackAndPromise(
142     napi_env env, CfCtx *context, size_t argc, size_t maxCount, napi_value callbackValue)
143 {
144     context->async->asyncType = GetAsyncType(env, argc, maxCount, callbackValue);
145     if (context->async->asyncType == ASYNC_TYPE_CALLBACK) {
146         if (!CertGetCallbackFromJSParams(env, callbackValue, &context->async->callback)) {
147             LOGE("x509 certificate: get callback failed!");
148             return false;
149         }
150     } else {
151         napi_create_promise(env, &context->async->deferred, &context->async->promise);
152     }
153     return true;
154 }
155 
CreateCertChainExecute(napi_env env,void * data)156 static void CreateCertChainExecute(napi_env env, void *data)
157 {
158     CfCtx *context = static_cast<CfCtx *>(data);
159     context->async->errCode = HcfCertChainCreate(context->encodingBlob, nullptr, &context->certChain);
160     if (context->async->errCode != CF_SUCCESS) {
161         context->async->errMsg = "create cert chain failed";
162     }
163 }
164 
BuildX509CertChainExecute(napi_env env,void * data)165 static void BuildX509CertChainExecute(napi_env env, void *data)
166 {
167     CfCtx *context = static_cast<CfCtx *>(data);
168     context->async->errCode = HcfCertChainBuildResultCreate(context->buildParams, &context->buildResult);
169     if (context->async->errCode != CF_SUCCESS) {
170         context->async->errMsg = "create cert chain failed";
171         return;
172     }
173     HcfCertChain *certChain = context->buildResult->certChain;
174     context->async->errCode = certChain->validate(
175         certChain, &(context->buildParams->validateParameters), &(context->buildResult->validateResult));
176     if (context->async->errCode != CF_SUCCESS) {
177         context->async->errMsg = "validate failed";
178         CfObjDestroy(context->buildResult->certChain);
179         context->buildResult->certChain = nullptr;
180     }
181 }
182 
BuildCreateInstance(napi_env env,HcfCertChain * certChain)183 static napi_value BuildCreateInstance(napi_env env, HcfCertChain *certChain)
184 {
185     napi_value instance = CreateCertChainJSInstance(env);
186     NapiX509CertChain *napiObject = new (std::nothrow) NapiX509CertChain(certChain);
187     if (napiObject == nullptr) {
188         LOGE("new napi object failed.");
189         return nullptr;
190     }
191     napi_status status = napi_wrap(
192         env, instance, napiObject,
193         [](napi_env env, void *data, void *hint) {
194             NapiX509CertChain *certchain = static_cast<NapiX509CertChain *>(data);
195             delete certchain;
196             return;
197         },
198         nullptr, nullptr);
199     if (status != napi_ok) {
200         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_NAPI, "failed to wrap obj!"));
201         LOGE("failed to wrap obj!");
202         delete napiObject;
203         return nullptr;
204     }
205     return instance;
206 }
207 
CreateCertChainComplete(napi_env env,napi_status status,void * data)208 static void CreateCertChainComplete(napi_env env, napi_status status, void *data)
209 {
210     CfCtx *context = static_cast<CfCtx *>(data);
211     if (context->async->errCode != CF_SUCCESS) {
212         ReturnJSResult(env, context->async, nullptr);
213         DeleteCertChainContext(env, context, false);
214         return;
215     }
216 
217     napi_value instance = BuildCreateInstance(env, context->certChain);
218     if (instance == nullptr) {
219         context->async->errCode = CF_ERR_MALLOC;
220         context->async->errMsg = "Failed to create napi cert chain class";
221         LOGE("Failed to create napi cert chain class");
222         CfObjDestroy(context->certChain);
223         context->certChain = nullptr;
224     }
225     ReturnJSResult(env, context->async, instance);
226     DeleteCertChainContext(env, context);
227 }
228 
BuildCreateInstanceByBulidRlt(napi_env env,CfCtx * ctx)229 static napi_value BuildCreateInstanceByBulidRlt(napi_env env, CfCtx *ctx)
230 {
231     napi_value returnValue = nullptr;
232     napi_create_object(env, &returnValue);
233     if (ctx->buildResult != nullptr) {
234         napi_value insCertChain = BuildCreateInstance(env, ctx->buildResult->certChain);
235         if (insCertChain == nullptr) {
236             LOGE("Build cert chain instance failed!");
237             return nullptr;
238         }
239         napi_set_named_property(env, returnValue, CERT_CHAIN_BUILD_RESULT_TAG_CERTCHAIN.c_str(), insCertChain);
240 
241         napi_value insValitateRes = BuildX509CertChainValidateResultJS(env, &(ctx->buildResult->validateResult));
242         if (insValitateRes == nullptr) {
243             LOGE("Build cert validate result failed!");
244             return nullptr;
245         }
246         napi_set_named_property(env, returnValue, CERT_CHAIN_BUILD_RESULT_TAG_VALIDATERESULT.c_str(), insValitateRes);
247     }
248 
249     return returnValue;
250 }
251 
BuildX509CertChainComplete(napi_env env,napi_status status,void * data)252 static void BuildX509CertChainComplete(napi_env env, napi_status status, void *data)
253 {
254     CfCtx *context = static_cast<CfCtx *>(data);
255     if (context->async->errCode != CF_SUCCESS) {
256         ReturnJSResult(env, context->async, nullptr);
257         DeleteCertChainContext(env, context, false);
258         return;
259     }
260 
261     napi_value instance = BuildCreateInstanceByBulidRlt(env, context);
262     if (instance == nullptr) {
263         context->async->errCode = CF_ERR_MALLOC;
264         context->async->errMsg = "Failed to create napi cert chain class";
265         LOGE("Failed to create napi cert chain class");
266         CfObjDestroy(context->buildResult->certChain);
267         context->certChain = nullptr;
268     }
269     ReturnJSResult(env, context->async, instance);
270     DeleteCertChainContext(env, context);
271 }
272 
CreateCertChainAsyncWork(napi_env env,CfCtx * context)273 static napi_value CreateCertChainAsyncWork(napi_env env, CfCtx *context)
274 {
275     napi_create_async_work(env, nullptr, GetResourceName(env, "createX509CertChain"), CreateCertChainExecute,
276         CreateCertChainComplete, static_cast<void *>(context), &context->async->asyncWork);
277 
278     napi_queue_async_work(env, context->async->asyncWork);
279     if (context->async->asyncType == ASYNC_TYPE_PROMISE) {
280         return context->async->promise;
281     } else {
282         return NapiGetNull(env);
283     }
284 }
285 
CreateCertChainExtAsyncWork(napi_env env,CfCtx * context)286 static napi_value CreateCertChainExtAsyncWork(napi_env env, CfCtx *context)
287 {
288     napi_create_async_work(env, nullptr, GetResourceName(env, "buildX509CertChain"), BuildX509CertChainExecute,
289         BuildX509CertChainComplete, static_cast<void *>(context), &context->async->asyncWork);
290 
291     napi_queue_async_work(env, context->async->asyncWork);
292     if (context->async->asyncType == ASYNC_TYPE_PROMISE) {
293         return context->async->promise;
294     } else {
295         return NapiGetNull(env);
296     }
297 }
298 
ValidateExecute(napi_env env,void * data)299 static void ValidateExecute(napi_env env, void *data)
300 {
301     CfCtx *context = static_cast<CfCtx *>(data);
302     context->async->errCode = context->certChain->validate(context->certChain, &context->params, &context->result);
303     if (context->async->errCode != CF_SUCCESS) {
304         context->async->errMsg = "create cert chain failed";
305     }
306 }
307 
ValidateComplete(napi_env env,napi_status status,void * data)308 static void ValidateComplete(napi_env env, napi_status status, void *data)
309 {
310     CfCtx *context = static_cast<CfCtx *>(data);
311     if (context->async->errCode != CF_SUCCESS) {
312         ReturnJSResult(env, context->async, nullptr);
313         DeleteCertChainContext(env, context, false);
314         return;
315     }
316     napi_value instance = BuildX509CertChainValidateResultJS(env, &context->result);
317     if (instance == nullptr) {
318         LOGE("validate ret failed");
319         context->async->errCode = CF_ERR_MALLOC;
320         context->async->errMsg = "build return obj failed!";
321         ReturnJSResult(env, context->async, nullptr);
322         DeleteCertChainContext(env, context, true);
323         return;
324     }
325 
326     ReturnJSResult(env, context->async, instance);
327     DeleteCertChainContext(env, context);
328 }
329 
ValidateAsyncWork(napi_env env,CfCtx * context)330 static napi_value ValidateAsyncWork(napi_env env, CfCtx *context)
331 {
332     napi_create_async_work(env, nullptr, GetResourceName(env, "Validate"), ValidateExecute, ValidateComplete,
333         static_cast<void *>(context), &context->async->asyncWork);
334 
335     napi_queue_async_work(env, context->async->asyncWork);
336     if (context->async->asyncType == ASYNC_TYPE_PROMISE) {
337         return context->async->promise;
338     } else {
339         return NapiGetNull(env);
340     }
341 }
342 
Validate(napi_env env,napi_callback_info info)343 napi_value NapiX509CertChain::Validate(napi_env env, napi_callback_info info)
344 {
345     size_t argc = ARGS_SIZE_TWO;
346     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
347     napi_value thisVar = nullptr;
348     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
349     if (!CertCheckArgsCount(env, argc, ARGS_SIZE_TWO, false)) {
350         LOGE("check args count failed.");
351         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "check args count failed!"));
352         return nullptr;
353     }
354 
355     CfCtx *context = BuildCertChainContext();
356     if (context == nullptr) {
357         LOGE("malloc context failed.");
358         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc context failed!"));
359         return nullptr;
360     }
361 
362     if (!CreateCallbackAndPromise(env, context, argc, ARGS_SIZE_TWO, argv[PARAM1])) {
363         DeleteCertChainContext(env, context);
364         LOGE("CreateCallbackAndPromise failed!");
365         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "CreateCallbackAndPromise failed!"));
366         return nullptr;
367     }
368     context->certChainClass = this;
369     context->certChain = GetCertChain();
370     if (!BuildX509CertChainValidateParams(env, argv[PARAM0], context->params)) {
371         LOGE("BuildX509CertChainValidateParams failed!");
372         DeleteCertChainContext(env, context);
373         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "BuildX509CertChainValidateParams failed!"));
374         return nullptr;
375     }
376 
377     if (napi_create_reference(env, thisVar, 1, &context->cfRef) != napi_ok) {
378         LOGE("create reference failed!");
379         DeleteCertChainContext(env, context);
380         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "Create reference failed!"));
381         return nullptr;
382     }
383     if (napi_create_reference(env, argv[PARAM0], 1, &context->certChainValidateParamsRef) != napi_ok) {
384         LOGE("create param ref failed!");
385         DeleteCertChainContext(env, context);
386         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "create param ref failed!"));
387         return nullptr;
388     }
389 
390     return ValidateAsyncWork(env, context);
391 }
392 
ToString(napi_env env,napi_callback_info info)393 napi_value NapiX509CertChain::ToString(napi_env env, napi_callback_info info)
394 {
395     HcfCertChain *certChain = GetCertChain();
396     CfBlob blob = { 0, nullptr };
397     CfResult result = certChain->toString(certChain, &blob);
398     if (result != CF_SUCCESS) {
399         LOGE("toString failed!");
400         napi_throw(env, CertGenerateBusinessError(env, result, "toString failed"));
401         return nullptr;
402     }
403 
404     napi_value returnBlob = nullptr;
405     napi_create_string_utf8(env, reinterpret_cast<char *>(blob.data), blob.size, &returnBlob);
406     CfBlobDataFree(&blob);
407     return returnBlob;
408 }
409 
HashCode(napi_env env,napi_callback_info info)410 napi_value NapiX509CertChain::HashCode(napi_env env, napi_callback_info info)
411 {
412     HcfCertChain *certChain = GetCertChain();
413     CfBlob blob = { 0, nullptr };
414     CfResult result = certChain->hashCode(certChain, &blob);
415     if (result != CF_SUCCESS) {
416         LOGE("hashCode failed!");
417         napi_throw(env, CertGenerateBusinessError(env, result, "hashCode failed"));
418         return nullptr;
419     }
420     napi_value returnBlob = ConvertBlobToUint8ArrNapiValue(env, &blob);
421     CfBlobDataFree(&blob);
422     return returnBlob;
423 }
424 
CreateX509CertChainByArray(napi_env env,napi_value param)425 static napi_value CreateX509CertChainByArray(napi_env env, napi_value param)
426 {
427     HcfX509CertificateArray certs = { nullptr, 0 };
428     if (param != nullptr && !GetArrayCertFromNapiValue(env, param, &certs, false)) {
429         LOGE("get array cert from data failed!");
430         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get cert arr failed!"));
431         return nullptr;
432     }
433 
434     HcfCertChain *certChain = nullptr;
435     CfResult res = HcfCertChainCreate(nullptr, &certs, &certChain);
436     if (res != CF_SUCCESS) {
437         LOGE("HcfCertChainCreate failed!");
438         CF_FREE_PTR(certs.data);
439         napi_throw(env, CertGenerateBusinessError(env, res, "create cert chain by arr failed!"));
440         return nullptr;
441     }
442     napi_value instance = BuildCreateInstance(env, certChain);
443     if (instance == nullptr) {
444         LOGE("BuildCreateInstance failed!");
445         CfObjDestroy(certChain);
446         CF_FREE_PTR(certs.data);
447         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "build create instance failed!"));
448         return nullptr;
449     }
450     CF_FREE_PTR(certs.data);
451     return instance;
452 }
453 
CreateX509CertChainByEncodingBlob(napi_env env,size_t argc,napi_value param1,napi_value param2)454 static napi_value CreateX509CertChainByEncodingBlob(napi_env env, size_t argc, napi_value param1, napi_value param2)
455 {
456     if (!CertCheckArgsCount(env, argc, ARGS_SIZE_TWO, false)) {
457         LOGE("CertCheckArgsCount failed");
458         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "CertCheckArgsCount failed!"));
459         return nullptr;
460     }
461     CfCtx *context = BuildCertChainContext();
462     if (context == nullptr) {
463         LOGE("context is nullptr");
464         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "context is nullptr!"));
465         return nullptr;
466     }
467 
468     if (!CreateCallbackAndPromise(env, context, argc, ARGS_SIZE_TWO, param2)) {
469         LOGE("Create Callback Promise failed");
470         DeleteCertChainContext(env, context);
471         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "Create Callback Promise failed!"));
472         return nullptr;
473     }
474     if (!GetEncodingBlobFromValue(env, param1, &context->encodingBlob)) {
475         LOGE("Get Encoding Blob failed");
476         DeleteCertChainContext(env, context);
477         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "Get Encoding Blob failed!"));
478         return nullptr;
479     }
480 
481     return CreateCertChainAsyncWork(env, context);
482 }
483 
NapiCreateX509CertChain(napi_env env,napi_callback_info info)484 napi_value NapiCreateX509CertChain(napi_env env, napi_callback_info info)
485 {
486     size_t argc = ARGS_SIZE_TWO;
487     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
488     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
489 
490     bool flag = false;
491     napi_is_array(env, argv[PARAM0], &flag);
492     napi_value instance = nullptr;
493     if (flag) {
494         if (argc != ARGS_SIZE_ONE) {
495             LOGE("arg size is not correct");
496             napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "arg size is not correct!"));
497             return nullptr;
498         }
499         LOGI("NapiCreateX509CertChain : Array<X509Cert>!");
500         instance = CreateX509CertChainByArray(env, argv[PARAM0]);
501     } else {
502         LOGI("NapiCreateX509CertChain : inStream: EncodingBlob!");
503         instance = CreateX509CertChainByEncodingBlob(env, argc, argv[PARAM0], argv[PARAM1]);
504     }
505     return instance;
506 }
507 
CreateTrustAnchorsWithKeyStoreExecute(napi_env env,void * data)508 static void CreateTrustAnchorsWithKeyStoreExecute(napi_env env, void *data)
509 {
510     CfCtx *context = static_cast<CfCtx *>(data);
511     if (context == nullptr) {
512         LOGE("context is nullptr");
513         return;
514     }
515     context->async->errCode =
516         HcfCreateTrustAnchorWithKeyStore(context->keyStore, context->pwd, &context->trustAnchorArray);
517     if (context->async->errCode != CF_SUCCESS) {
518         context->async->errMsg = "Failed to create trust anchor from p12!";
519     }
520 }
521 
ConvertX509CertToNapiValue(napi_env env,HcfX509Certificate * cert)522 static napi_value ConvertX509CertToNapiValue(napi_env env, HcfX509Certificate *cert)
523 {
524     if (cert == nullptr) {
525         LOGE("ConvertX509CertToNapiValue:cert is nullptr.");
526         return nullptr;
527     }
528     CfObject *certObj = nullptr;
529     CfResult res = GetCertObject(cert, &certObj);
530     if (res != CF_SUCCESS) {
531         LOGE("GetCertObject failed.");
532         return nullptr;
533     }
534     NapiX509Certificate *x509Cert = new (std::nothrow) NapiX509Certificate(cert, certObj);
535     if (x509Cert == nullptr) {
536         LOGE("new x509Cert failed!");
537         certObj->destroy(&certObj);
538         certObj = nullptr;
539         return nullptr;
540     }
541     napi_value instance = NapiX509Certificate::CreateX509Cert(env);
542     napi_status status = napi_wrap(
543         env, instance, x509Cert,
544         [](napi_env env, void *data, void *hint) {
545             NapiX509Certificate *certClass = static_cast<NapiX509Certificate *>(data);
546             delete certClass;
547             return;
548         },
549         nullptr, nullptr);
550     if (status != napi_ok) {
551         LOGE("Failed to wrap x509Cert obj!");
552         delete x509Cert;
553         return nullptr;
554     }
555 
556     return instance;
557 }
558 
ConvertBlobToUint8ArrayNapiValue(napi_env env,CfBlob * blob)559 static napi_value ConvertBlobToUint8ArrayNapiValue(napi_env env, CfBlob *blob)
560 {
561     if (blob == nullptr) {
562         LOGE("ConvertCfBlobToNapiValue:blob is nullptr.");
563         return nullptr;
564     }
565     uint8_t *buffer = static_cast<uint8_t *>(CfMalloc(blob->size, 0));
566     if (buffer == nullptr) {
567         LOGE("malloc uint8 array buffer failed!");
568         return nullptr;
569     }
570 
571     if (memcpy_s(buffer, blob->size, blob->data, blob->size) != EOK) {
572         LOGE("memcpy_s data to buffer failed!");
573         CfFree(buffer);
574         buffer = nullptr;
575         return nullptr;
576     }
577 
578     napi_value outBuffer = nullptr;
579     napi_status status = napi_create_external_arraybuffer(
580         env, buffer, blob->size, [](napi_env env, void *data, void *hint) { CfFree(data); }, nullptr, &outBuffer);
581     if (status != napi_ok) {
582         LOGE("create uint8 array buffer failed!");
583         CfFree(buffer);
584         buffer = nullptr;
585         return nullptr;
586     }
587     buffer = nullptr;
588 
589     napi_value outData = nullptr;
590     napi_create_typedarray(env, napi_uint8_array, blob->size, outBuffer, 0, &outData);
591     return outData;
592 }
593 
BuildCreateInstanceByTrustAnchorArray(napi_env env,HcfX509TrustAnchorArray * trustAnchorArray)594 static napi_value BuildCreateInstanceByTrustAnchorArray(napi_env env, HcfX509TrustAnchorArray *trustAnchorArray)
595 {
596     if (trustAnchorArray == nullptr) {
597         LOGE("Input data is null!");
598         return nullptr;
599     }
600     napi_value instance;
601     napi_create_array(env, &instance);
602     if (instance == nullptr) {
603         LOGE("Create return instance failed!");
604         return nullptr;
605     }
606     int elementIdx = 0;
607     for (uint32_t i = 0; i < trustAnchorArray->count; ++i) {
608         napi_value element = NapiX509Certificate::CreateX509Cert(env);
609         if (element == nullptr) {
610             LOGE("Create x509Cert failed!");
611             return nullptr;
612         }
613         napi_value valueCACert = ConvertX509CertToNapiValue(env, trustAnchorArray->data[i]->CACert);
614         if (valueCACert == nullptr) {
615             LOGI("The CACert value is null, return to js is an enpty object!");
616         } else {
617             trustAnchorArray->data[i]->CACert = nullptr;
618         }
619         napi_set_named_property(env, element, CERT_CHAIN_TRUSTANCHOR_TAG_CACERT.c_str(), valueCACert);
620 
621         napi_value valuePubKey = ConvertBlobToUint8ArrayNapiValue(env, trustAnchorArray->data[i]->CAPubKey);
622         if (valuePubKey == nullptr) {
623             LOGI("The PubKey value is null, return to js is an enpty object!");
624         }
625         napi_set_named_property(env, element, CERT_CHAIN_TRUSTANCHOR_TAG_CAPUBKEY.c_str(), valuePubKey);
626 
627         napi_value valueSub = ConvertBlobToUint8ArrayNapiValue(env, trustAnchorArray->data[i]->CASubject);
628         if (valueSub == nullptr) {
629             LOGI("The CASubject value is null, return to js is an enpty object!");
630         }
631         napi_set_named_property(env, element, CERT_CHAIN_TRUSTANCHOR_TAG_CASUBJECT.c_str(), valueSub);
632 
633         napi_value valueName = ConvertBlobToUint8ArrayNapiValue(env, trustAnchorArray->data[i]->nameConstraints);
634         if (valueName == nullptr) {
635             LOGI("The nameConsteaints value is null, return to js is an enpty object!");
636         }
637         napi_set_named_property(env, element, CERT_MATCH_TAG_NAME_CONSTRAINTS.c_str(), valueName);
638 
639         if (element != nullptr) {
640             napi_set_element(env, instance, elementIdx++, element);
641         }
642     }
643     return instance;
644 }
645 
CreateTrustAnchorsWithKeyStoreComplete(napi_env env,napi_status status,void * data)646 static void CreateTrustAnchorsWithKeyStoreComplete(napi_env env, napi_status status, void *data)
647 {
648     CfCtx *context = static_cast<CfCtx *>(data);
649     if (context->async->errCode != CF_SUCCESS) {
650         ReturnJSResult(env, context->async, nullptr);
651         DeleteCertChainContext(env, context, false);
652         return;
653     }
654     napi_value instance = BuildCreateInstanceByTrustAnchorArray(env, context->trustAnchorArray);
655     if (instance == nullptr) {
656         context->async->errCode = CF_ERR_MALLOC;
657         context->async->errMsg = "Failed to create trust anchor with KeyStore";
658         LOGE("Failed to create trust anchor with KeyStore");
659     }
660     ReturnJSResult(env, context->async, instance);
661     DeleteCertChainContext(env, context, true);
662 }
663 
CreateTrustAnchorsWithKeyStoreAsyncWork(napi_env env,CfCtx * context)664 static napi_value CreateTrustAnchorsWithKeyStoreAsyncWork(napi_env env, CfCtx *context)
665 {
666     napi_create_async_work(env, nullptr, GetResourceName(env, "createTrustAnchorsWithKeyStore"),
667         CreateTrustAnchorsWithKeyStoreExecute, CreateTrustAnchorsWithKeyStoreComplete, static_cast<void *>(context),
668         &context->async->asyncWork);
669 
670     napi_queue_async_work(env, context->async->asyncWork);
671     if (context->async->asyncType == ASYNC_TYPE_PROMISE) {
672         return context->async->promise;
673     } else {
674         return NapiGetNull(env);
675     }
676 }
677 
CreateTrustAnchorsWithKeyStore(napi_env env,size_t argc,napi_value param1,napi_value param2)678 static napi_value CreateTrustAnchorsWithKeyStore(napi_env env, size_t argc, napi_value param1, napi_value param2)
679 {
680     if (!CertCheckArgsCount(env, argc, ARGS_SIZE_TWO, false)) {
681         LOGE("CertCheckArgsCount failed");
682         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "CertCheckArgsCount failed!"));
683         return nullptr;
684     }
685     CfCtx *context = BuildCertChainContext();
686     if (context == nullptr) {
687         LOGE("context is nullptr");
688         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "context is nullptr!"));
689         return nullptr;
690     }
691 
692     context->async->asyncType = GetAsyncType(env, argc, ARGS_SIZE_TWO, nullptr);
693     if (context->async->asyncType == ASYNC_TYPE_CALLBACK) {
694         LOGE("ASYNC_TYPE_CALLBACK is not supported.");
695         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "ASYNC_TYPE_CALLBACK is not supported."));
696         DeleteCertChainContext(env, context);
697         return nullptr;
698     }
699     napi_create_promise(env, &context->async->deferred, &context->async->promise);
700 
701     context->keyStore = CertGetBlobFromUint8ArrJSParams(env, param1);
702     if (context->keyStore == nullptr) {
703         DeleteCertChainContext(env, context);
704         return nullptr;
705     }
706     context->pwd = CertGetBlobFromStringJSParams(env, param2);
707     if (context->pwd == nullptr) {
708         DeleteCertChainContext(env, context);
709         return nullptr;
710     }
711 
712     return CreateTrustAnchorsWithKeyStoreAsyncWork(env, context);
713 }
714 
NapiCreateTrustAnchorsWithKeyStore(napi_env env,napi_callback_info info)715 napi_value NapiCreateTrustAnchorsWithKeyStore(napi_env env, napi_callback_info info)
716 {
717     size_t argc = ARGS_SIZE_TWO;
718     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
719     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
720     napi_value instance = CreateTrustAnchorsWithKeyStore(env, argc, argv[PARAM0], argv[PARAM1]);
721     return instance;
722 }
723 
GetP12ConfFromValue(napi_env env,napi_value arg,HcfParsePKCS12Conf * conf)724 static bool GetP12ConfFromValue(napi_env env, napi_value arg, HcfParsePKCS12Conf *conf)
725 {
726     conf->isPem = true;
727     conf->isGetPriKey = true;
728     conf->isGetCert = true;
729     conf->isGetOtherCerts = false;
730 
731     if (!GetIsPemFromStringNapiValue(env, arg, conf->isPem, CERT_CHAIN_PKCS12_TAG_PRIKEY_FORMAT.c_str())) {
732         return false;
733     }
734     if (!GetBoolFromNapiValue(env, arg, conf->isGetPriKey, CERT_CHAIN_PKCS12_TAG_NEEDS_PRIVATE_KEY.c_str())) {
735         return false;
736     }
737     if (!GetBoolFromNapiValue(env, arg, conf->isGetCert, CERT_CHAIN_PKCS12_TAG_NEEDS_CERT.c_str())) {
738         return false;
739     }
740     if (!GetBoolFromNapiValue(env, arg, conf->isGetOtherCerts, CERT_CHAIN_PKCS12_TAG_NEEDS_OTHER_CERTS.c_str())) {
741         return false;
742     }
743 
744     napi_value obj = GetProp(env, arg, CERT_CHAIN_PKCS12_TAG_PASSWORD.c_str());
745     if (obj == nullptr) {
746         LOGE("Failed to get p12 conf!");
747         return false;
748     }
749 
750     conf->pwd = CertGetBlobFromStringJSParams(env, obj);
751     if (conf->pwd == nullptr) {
752         LOGE("Out is nullptr");
753         return false;
754     }
755 
756     return true;
757 }
758 
FreeP12Collection(HcfX509P12Collection * collection)759 static void FreeP12Collection(HcfX509P12Collection *collection)
760 {
761     if (collection == nullptr) {
762         return;
763     }
764     if (collection->otherCerts != nullptr && collection->otherCertsCount != 0) {
765         for (uint32_t i = 0; i < collection->otherCertsCount; i++) {
766             if (collection->otherCerts[i] != nullptr) {
767                 CfFree(collection->otherCerts[i]);
768                 collection->otherCerts[i] = nullptr;
769             }
770         }
771         CfFree(collection->otherCerts);
772         collection->otherCerts = nullptr;
773     }
774 
775     if (collection->cert != nullptr) {
776         CfFree(collection->cert);
777         collection->cert = nullptr;
778     }
779 
780     if (collection->prikey != nullptr && collection->prikey->data != nullptr) {
781         CfFree(collection->prikey->data);
782         collection->prikey->data = nullptr;
783         CfFree(collection->prikey);
784         collection->prikey = nullptr;
785     }
786 
787     CfFree(collection);
788 }
789 
FreeHcfParsePKCS12Conf(HcfParsePKCS12Conf * conf)790 static void FreeHcfParsePKCS12Conf(HcfParsePKCS12Conf *conf)
791 {
792     if (conf == nullptr) {
793         return;
794     }
795     CfBlobFree(&conf->pwd);
796     CfFree(conf);
797 }
798 
ConvertBlobToStringNapiValue(napi_env env,CfBlob * blob)799 static napi_value ConvertBlobToStringNapiValue(napi_env env, CfBlob *blob)
800 {
801     uint32_t len = blob->size;
802     char *returnString = static_cast<char *>(CfMalloc(len, 0));
803     if (returnString == nullptr) {
804         LOGE("Failed to malloc return string.");
805         return nullptr;
806     }
807 
808     (void)memcpy_s(returnString, len, blob->data, len);
809     napi_value instance = nullptr;
810     napi_create_string_utf8(env, returnString, len, &instance);
811     CfFree(returnString);
812     returnString = nullptr;
813     return instance;
814 }
815 
ConvertPkeyToInstance(napi_env env,HcfX509P12Collection * p12Collection)816 static napi_value ConvertPkeyToInstance(napi_env env, HcfX509P12Collection *p12Collection)
817 {
818     if (p12Collection->isPem) {
819         return ConvertBlobToStringNapiValue(env, p12Collection->prikey);
820     }
821 
822     return ConvertBlobToUint8ArrayNapiValue(env, p12Collection->prikey);
823 }
824 
BuildCreateInstanceByP12Collection(napi_env env,HcfX509P12Collection * p12Collection)825 static napi_value BuildCreateInstanceByP12Collection(napi_env env, HcfX509P12Collection *p12Collection)
826 {
827     napi_value instance;
828     napi_create_array(env, &instance);
829     if (instance == nullptr) {
830         LOGE("Create return instance failed!");
831         return nullptr;
832     }
833 
834     if (p12Collection->cert != nullptr) {
835         napi_value certInstance = ConvertCertToNapiValue(env, p12Collection->cert);
836         if (certInstance == nullptr) {
837             LOGE("certInstance is nullptr");
838             return nullptr;
839         }
840         napi_set_named_property(env, instance, CERT_CHAIN_PKCS12_TAG_CERT.c_str(), certInstance);
841     }
842 
843     if (p12Collection->prikey != nullptr) {
844         napi_value pkeyInstance = ConvertPkeyToInstance(env, p12Collection);
845         if (pkeyInstance == nullptr) {
846             LOGE("pkeyInstance is nullptr");
847             return nullptr;
848         }
849         napi_set_named_property(env, instance, CERT_CHAIN_PKCS12_TAG_PRIKEY.c_str(), pkeyInstance);
850     }
851 
852     if (p12Collection->otherCerts == nullptr || p12Collection->otherCertsCount <= 0) {
853         return instance;
854     }
855 
856     HcfX509CertificateArray certs = { p12Collection->otherCerts, p12Collection->otherCertsCount };
857     napi_value otherCertsInstance = ConvertCertArrToNapiValue(env, &certs);
858     if (otherCertsInstance == nullptr) {
859         LOGE("convert other certs to instance failed!");
860         return nullptr;
861     }
862     napi_set_named_property(env, instance, CERT_CHAIN_PKCS12_TAG_OTHER_CERTS.c_str(), otherCertsInstance);
863 
864     return instance;
865 }
866 
ParsePKCS12WithKeyStore(napi_env env,size_t argc,napi_value param0,napi_value param1)867 static napi_value ParsePKCS12WithKeyStore(napi_env env, size_t argc, napi_value param0, napi_value param1)
868 {
869     CfBlob *keyStore = CertGetBlobFromUint8ArrJSParams(env, param0);
870     if (keyStore == nullptr) {
871         LOGE("Failed to get pkcs12!");
872         return nullptr;
873     }
874     HcfParsePKCS12Conf *conf = static_cast<HcfParsePKCS12Conf *>(CfMalloc(sizeof(HcfParsePKCS12Conf), 0));
875     if (conf == nullptr) {
876         CfBlobFree(&keyStore);
877         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "Failed to malloc conf"));
878         LOGE("Failed to malloc conf!");
879         return nullptr;
880     };
881 
882     if (!GetP12ConfFromValue(env, param1, conf)) {
883         CfBlobFree(&keyStore);
884         FreeHcfParsePKCS12Conf(conf);
885         conf = nullptr;
886         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "Failed to get conf"));
887         LOGE("Failed to get conf!");
888         return nullptr;
889     }
890 
891     HcfX509P12Collection *p12Collection = nullptr;
892     CfResult ret = HcfParsePKCS12(keyStore, conf, &p12Collection);
893     if (ret != CF_SUCCESS) {
894         CfBlobFree(&keyStore);
895         FreeHcfParsePKCS12Conf(conf);
896         conf = nullptr;
897         napi_throw(env, CertGenerateBusinessError(env, ret, "Failed to parse pkcs12"));
898         LOGE("Failed to parse pkcs12!");
899         return nullptr;
900     }
901 
902     napi_value instance = BuildCreateInstanceByP12Collection(env, p12Collection);
903     if (instance == nullptr) {
904         CfBlobFree(&keyStore);
905         FreeHcfParsePKCS12Conf(conf);
906         conf = nullptr;
907         FreeP12Collection(p12Collection);
908         p12Collection = nullptr;
909         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "Failed to build instance"));
910         LOGE("Failed to build instance!");
911         return nullptr;
912     }
913     CfBlobFree(&keyStore);
914     FreeHcfParsePKCS12Conf(conf);
915     conf = nullptr;
916     CfBlobFree(&p12Collection->prikey);
917     CfFree(p12Collection);
918     p12Collection = nullptr;
919     return instance;
920 }
921 
NapiParsePKCS12(napi_env env,napi_callback_info info)922 napi_value NapiParsePKCS12(napi_env env, napi_callback_info info)
923 {
924     size_t argc = ARGS_SIZE_TWO;
925     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
926     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
927     if (argc != ARGS_SIZE_TWO) {
928         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "invalid params count"));
929         LOGE("invalid params count!");
930         return nullptr;
931     }
932     napi_value instance = ParsePKCS12WithKeyStore(env, argc, argv[PARAM0], argv[PARAM1]);
933     return instance;
934 }
935 
GetCertMatchParameters(napi_env env,napi_value obj,HcfX509CertChainBuildParameters ** buildParams)936 bool GetCertMatchParameters(napi_env env, napi_value obj, HcfX509CertChainBuildParameters **buildParams)
937 {
938     napi_value data = nullptr;
939     napi_status status = napi_get_named_property(env, obj, CERT_TAG_CERT_MATCH_PARAMS.c_str(), &data);
940     if (status != napi_ok) {
941         LOGE("failed to get cert match params!");
942         return false;
943     }
944     HcfX509CertMatchParams *param = &((*buildParams)->certMatchParameters);
945     if (!BuildX509CertMatchParams(env, data, param)) {
946         LOGE("BuildX509CertMatchParams failed!");
947         return false;
948     }
949     return true;
950 }
951 
GetMaxlength(napi_env env,napi_value obj,HcfX509CertChainBuildParameters ** buildParams)952 bool GetMaxlength(napi_env env, napi_value obj, HcfX509CertChainBuildParameters **buildParams)
953 {
954     napi_value data = nullptr;
955     napi_status status = napi_get_named_property(env, obj, CERT_TAG_MAX_LENGTH.c_str(), &data);
956     if (status != napi_ok) {
957         LOGE("failed to get max length!");
958         return false;
959     }
960     napi_valuetype valueType;
961     napi_typeof(env, data, &valueType);
962     if ((valueType != napi_number) && (valueType != napi_undefined) && (valueType != napi_null)) {
963         LOGE("%{public}s valueType is null or undefined.", CERT_TAG_MAX_LENGTH.c_str());
964         return false;
965     }
966     napi_get_value_uint32(env, data, reinterpret_cast<uint32_t *>(&((*buildParams)->maxlength)));
967     return true;
968 }
969 
GetValidateParameters(napi_env env,napi_value obj,HcfX509CertChainBuildParameters ** buildParams)970 bool GetValidateParameters(napi_env env, napi_value obj, HcfX509CertChainBuildParameters **buildParams)
971 {
972     napi_value data = nullptr;
973     napi_status status = napi_get_named_property(env, obj, CERT_TAG_VALIDATE_PARAMS.c_str(), &data);
974     if (status != napi_ok) {
975         LOGE("failed to get cert validate params!");
976         return false;
977     }
978     if (!BuildX509CertChainValidateParams(env, data, (*buildParams)->validateParameters)) {
979         LOGE("BuildX509CertChainValidateParams failed!");
980         return false;
981     }
982     return true;
983 }
984 
FreeHcfX509CertChainBuildParameters(HcfX509CertChainBuildParameters * param)985 static void FreeHcfX509CertChainBuildParameters(HcfX509CertChainBuildParameters *param)
986 {
987     if (param == nullptr) {
988         return;
989     }
990     FreeX509CertMatchParamsInner(&param->certMatchParameters);
991     FreeX509CertChainValidateParams(param->validateParameters);
992     CfFree(param);
993 }
994 
GetChainBuildParametersFromValue(napi_env env,napi_value obj,HcfX509CertChainBuildParameters ** buildParams)995 bool GetChainBuildParametersFromValue(napi_env env, napi_value obj, HcfX509CertChainBuildParameters **buildParams)
996 {
997     HcfX509CertChainBuildParameters *buildParam =
998         static_cast<HcfX509CertChainBuildParameters *>(CfMalloc(sizeof(HcfX509CertChainBuildParameters), 0));
999     if (buildParam == nullptr) {
1000         LOGE("malloc cert chain build parameters failed!");
1001         return false;
1002     }
1003     buildParam->maxlength = -1;
1004 
1005     if (!GetCertMatchParameters(env, obj, &buildParam)) {
1006         LOGE("failed to get cert match parameters!");
1007         FreeHcfX509CertChainBuildParameters(buildParam);
1008         buildParam = nullptr;
1009         return false;
1010     }
1011     if (!GetMaxlength(env, obj, &buildParam)) {
1012         LOGE("failed to get max length!");
1013         FreeHcfX509CertChainBuildParameters(buildParam);
1014         buildParam = nullptr;
1015         return false;
1016     }
1017     if (!GetValidateParameters(env, obj, &buildParam)) {
1018         LOGE("failed to get validate parameters!");
1019         FreeHcfX509CertChainBuildParameters(buildParam);
1020         buildParam = nullptr;
1021         return false;
1022     }
1023 
1024     *buildParams = buildParam;
1025     return true;
1026 }
1027 
CreateX509CertChainExtReturn(napi_env env,size_t argc,napi_value param)1028 static napi_value CreateX509CertChainExtReturn(napi_env env, size_t argc, napi_value param)
1029 {
1030     if (!CertCheckArgsCount(env, argc, ARGS_SIZE_ONE, false)) {
1031         LOGE("CertCheckArgsCount failed");
1032         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "CertCheckArgsCount failed!"));
1033         return nullptr;
1034     }
1035     CfCtx *context = BuildCertChainContext();
1036     if (context == nullptr) {
1037         LOGE("context is nullptr");
1038         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "context is nullptr!"));
1039         return nullptr;
1040     }
1041 
1042     if (!CreateCallbackAndPromise(env, context, argc, ARGS_SIZE_ONE, nullptr)) {
1043         LOGE("Create Callback Promise failed");
1044         DeleteCertChainContext(env, context);
1045         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "Create Callback Promise failed!"));
1046         return nullptr;
1047     }
1048     if (napi_create_reference(env, param, 1, &context->async->paramRef) != napi_ok) {
1049         LOGE("create param ref failed!");
1050         DeleteCertChainContext(env, context);
1051         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "Create param ref failed"));
1052         return nullptr;
1053     }
1054     if (!GetChainBuildParametersFromValue(env, param, &context->buildParams)) {
1055         LOGE("Get Cert Chain Build Parameters failed!");
1056         DeleteCertChainContext(env, context);
1057         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "Get Cert Chain Build Parameters failed!"));
1058         return nullptr;
1059     }
1060 
1061     return CreateCertChainExtAsyncWork(env, context);
1062 }
1063 
NapiBuildX509CertChain(napi_env env,napi_callback_info info)1064 napi_value NapiBuildX509CertChain(napi_env env, napi_callback_info info)
1065 {
1066     size_t argc = ARGS_SIZE_ONE;
1067     napi_value argv[ARGS_SIZE_ONE] = { nullptr };
1068     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1069 
1070     napi_value instance = nullptr;
1071     instance = CreateX509CertChainExtReturn(env, argc, argv[PARAM0]);
1072     return instance;
1073 }
1074 
NapiGetCertList(napi_env env,napi_callback_info info)1075 napi_value NapiGetCertList(napi_env env, napi_callback_info info)
1076 {
1077     napi_value thisVar = nullptr;
1078     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
1079     NapiX509CertChain *napiCertChainObj = nullptr;
1080     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiCertChainObj));
1081     if (napiCertChainObj == nullptr) {
1082         LOGE("napi cert chain object is nullptr!");
1083         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "napi cert chain object is nullptr!"));
1084         return nullptr;
1085     }
1086     HcfCertChain *certChain = napiCertChainObj->GetCertChain();
1087     HcfX509CertificateArray certs = { nullptr, 0 };
1088     CfResult res = certChain->getCertList(certChain, &certs);
1089     if (res != CF_SUCCESS) {
1090         LOGE("napi getCertList failed!");
1091         napi_throw(env, CertGenerateBusinessError(env, res, "get cert list failed!"));
1092         return nullptr;
1093     }
1094     napi_value instance = ConvertCertArrToNapiValue(env, &certs);
1095     if (instance == nullptr) {
1096         LOGE("convert arr to instance failed!");
1097         FreeCertArrayData(&certs);
1098         napi_throw(env, CertGenerateBusinessError(env, res, "convert arr to instance failed!"));
1099         return nullptr;
1100     }
1101     CF_FREE_PTR(certs.data);
1102     return instance;
1103 }
1104 
NapiValidate(napi_env env,napi_callback_info info)1105 napi_value NapiValidate(napi_env env, napi_callback_info info)
1106 {
1107     napi_value thisVar = nullptr;
1108     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
1109     NapiX509CertChain *napiCertChainObj = nullptr;
1110     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiCertChainObj));
1111     if (napiCertChainObj == nullptr) {
1112         LOGE("napi cert chain object is nullptr!");
1113         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "napi cert chain object is nullptr!"));
1114         return nullptr;
1115     }
1116     return napiCertChainObj->Validate(env, info);
1117 }
1118 
NapiToString(napi_env env,napi_callback_info info)1119 napi_value NapiToString(napi_env env, napi_callback_info info)
1120 {
1121     napi_value thisVar = nullptr;
1122     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
1123     NapiX509CertChain *napiCertChainObj = nullptr;
1124     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiCertChainObj));
1125     if (napiCertChainObj == nullptr) {
1126         LOGE("napi cert chain object is nullptr!");
1127         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "napi cert chain object is nullptr!"));
1128         return nullptr;
1129     }
1130     return napiCertChainObj->ToString(env, info);
1131 }
1132 
NapiHashCode(napi_env env,napi_callback_info info)1133 napi_value NapiHashCode(napi_env env, napi_callback_info info)
1134 {
1135     napi_value thisVar = nullptr;
1136     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
1137     NapiX509CertChain *napiCertChainObj = nullptr;
1138     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiCertChainObj));
1139     if (napiCertChainObj == nullptr) {
1140         LOGE("napi cert chain object is nullptr!");
1141         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "napi cert chain object is nullptr!"));
1142         return nullptr;
1143     }
1144     return napiCertChainObj->HashCode(env, info);
1145 }
1146 
CertChainConstructor(napi_env env,napi_callback_info info)1147 static napi_value CertChainConstructor(napi_env env, napi_callback_info info)
1148 {
1149     napi_value thisVar = nullptr;
1150     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
1151     return thisVar;
1152 }
1153 
Constructor(napi_env env,napi_callback_info info)1154 napi_value NapiX509CertChain::Constructor(napi_env env, napi_callback_info info)
1155 {
1156     return CertChainConstructor(env, info);
1157 }
1158 
ConvertToJsCertChain(napi_env env)1159 napi_value NapiX509CertChain::ConvertToJsCertChain(napi_env env)
1160 {
1161     napi_value instance;
1162     napi_value constructor = nullptr;
1163     napi_get_reference_value(env, classRef_, &constructor);
1164     napi_new_instance(env, constructor, 0, nullptr, &instance);
1165 
1166     return instance;
1167 }
1168 
Constructor(napi_env env,napi_callback_info info)1169 napi_value NapiX509CertChainBulidResult::Constructor(napi_env env, napi_callback_info info)
1170 {
1171     return CertChainConstructor(env, info);
1172 }
1173 
ConvertToJsBuildResult(napi_env env)1174 napi_value NapiX509CertChainBulidResult::ConvertToJsBuildResult(napi_env env)
1175 {
1176     napi_value instance;
1177     napi_value constructor = nullptr;
1178     napi_get_reference_value(env, classRef_, &constructor);
1179     napi_new_instance(env, constructor, 0, nullptr, &instance);
1180 
1181     if (this->buildResult_ != nullptr && this->buildResult_->certChain != nullptr) {
1182         NapiX509CertChain *napiObject = new (std::nothrow) NapiX509CertChain(this->buildResult_->certChain);
1183         if (napiObject == nullptr) {
1184             LOGE("new napi object failed.");
1185             return nullptr;
1186         }
1187         napi_value certChain = napiObject->ConvertToJsCertChain(env);
1188         napi_status status = napi_wrap(
1189             env, certChain, napiObject,
1190             [](napi_env env, void *data, void *hint) {
1191                 NapiX509CertChain *napiObject = static_cast<NapiX509CertChain *>(data);
1192                 delete napiObject;
1193                 return;
1194             },
1195             nullptr, nullptr);
1196         if (status != napi_ok) {
1197             LOGE("failed to wrap certChain obj!");
1198             delete napiObject;
1199             return nullptr;
1200         }
1201         napi_set_named_property(env, instance, "certChain", certChain);
1202     }
1203 
1204     if (this->buildResult_ != nullptr) {
1205         napi_value validateResult = BuildX509CertChainValidateResultJS(env, &(this->buildResult_->validateResult));
1206         napi_set_named_property(env, instance, "validateResult", validateResult);
1207     }
1208     return instance;
1209 }
1210 
DefineX509CertChainJsClass(napi_env env,napi_value exports)1211 void NapiX509CertChain::DefineX509CertChainJsClass(napi_env env, napi_value exports)
1212 {
1213     napi_property_descriptor desc[] = {
1214         DECLARE_NAPI_FUNCTION("createX509CertChain", NapiCreateX509CertChain),
1215         DECLARE_NAPI_FUNCTION("createTrustAnchorsWithKeyStore", NapiCreateTrustAnchorsWithKeyStore),
1216         DECLARE_NAPI_FUNCTION("parsePkcs12", NapiParsePKCS12),
1217     };
1218     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
1219 
1220     napi_property_descriptor CertChainDesc[] = {
1221         DECLARE_NAPI_FUNCTION("getCertList", NapiGetCertList),
1222         DECLARE_NAPI_FUNCTION("validate", NapiValidate),
1223         DECLARE_NAPI_FUNCTION("toString", NapiToString),
1224         DECLARE_NAPI_FUNCTION("hashCode", NapiHashCode),
1225     };
1226 
1227     napi_value constructor = nullptr;
1228     napi_define_class(env, "X509CertChain", NAPI_AUTO_LENGTH, CertChainConstructor, nullptr,
1229         sizeof(CertChainDesc) / sizeof(CertChainDesc[0]), CertChainDesc, &constructor);
1230     napi_create_reference(env, constructor, 1, &classRef_);
1231 }
1232 
DefineX509CertChainBuildResultJsClass(napi_env env,napi_value exports)1233 void NapiX509CertChainBulidResult::DefineX509CertChainBuildResultJsClass(napi_env env, napi_value exports)
1234 {
1235     napi_property_descriptor desc[] = { DECLARE_NAPI_FUNCTION("buildX509CertChain", NapiBuildX509CertChain) };
1236     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
1237 
1238     napi_property_descriptor CertChainBuildResultDesc[] = {};
1239     napi_value constructor = nullptr;
1240     napi_define_class(env, "CertChainBuildResult", NAPI_AUTO_LENGTH, NapiX509CertChainBulidResult::Constructor, nullptr,
1241         sizeof(CertChainBuildResultDesc) / sizeof(CertChainBuildResultDesc[0]), CertChainBuildResultDesc, &constructor);
1242     napi_create_reference(env, constructor, 1, &classRef_);
1243 }
1244 } // namespace CertFramework
1245 } // namespace OHOS
1246