• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *    http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "cm_napi_sign_verify.h"
17 
18 #include "securec.h"
19 
20 #include "cert_manager_api.h"
21 #include "cm_log.h"
22 #include "cm_mem.h"
23 #include "cm_type.h"
24 #include "cm_napi_common.h"
25 
26 namespace CMNapi {
27 namespace {
28 constexpr int CM_NAPI_INIT_ARGS_CNT = 3;
29 constexpr int CM_NAPI_UPDATE_ARGS_CNT = 3;
30 constexpr int CM_NAPI_FINISH_ARGS_CNT = 3;
31 constexpr int CM_NAPI_ABORT_ARGS_CNT = 2;
32 
33 constexpr int CM_NAPI_CALLBACK_ARG_CNT = 1;
34 constexpr int CM_NAPI_SIGNATURE_ARG_CNT = 1;
35 
36 constexpr uint32_t OUT_SIGNATURE_SIZE = 1000;
37 constexpr uint32_t OUT_HANLDE_SIZE = 8;
38 } // namespace
39 
40 struct SignVerifyAsyncContextT {
41     napi_async_work asyncWork = nullptr;
42     napi_deferred deferred = nullptr;
43     napi_ref callback = nullptr;
44 
45     int32_t errCode = 0;
46     bool isSign = false;
47     struct CmBlob *authUri = nullptr;
48     struct CmBlob *handle = nullptr;
49     struct CmBlob *inData = nullptr;
50     struct CmBlob *signature = nullptr;
51     struct CmSignatureSpec *spec = nullptr;
52 };
53 using SignVerifyAsyncContext = SignVerifyAsyncContextT *;
54 
InitSignVerifyAsyncContext(void)55 static SignVerifyAsyncContext InitSignVerifyAsyncContext(void)
56 {
57     SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(CmMalloc(sizeof(SignVerifyAsyncContextT)));
58     if (context != nullptr) {
59         (void)memset_s(context, sizeof(SignVerifyAsyncContextT), 0, sizeof(SignVerifyAsyncContextT));
60     }
61     return context;
62 }
63 
FreeSignVerifyAsyncContext(napi_env env,SignVerifyAsyncContext & context)64 static void FreeSignVerifyAsyncContext(napi_env env, SignVerifyAsyncContext &context)
65 {
66     if (context == nullptr) {
67         return;
68     }
69 
70     DeleteNapiContext(env, context->asyncWork, context->callback);
71     FreeCmBlob(context->authUri);
72     FreeCmBlob(context->handle);
73     FreeCmBlob(context->inData);
74     FreeCmBlob(context->signature);
75     CM_FREE_PTR(context->spec);
76     CM_FREE_PTR(context);
77 }
78 
ParseSpec(napi_env env,napi_value object,CmSignatureSpec * & spec)79 static napi_value ParseSpec(napi_env env, napi_value object, CmSignatureSpec *&spec)
80 {
81     napi_valuetype type = napi_undefined;
82     NAPI_CALL(env, napi_typeof(env, object, &type));
83     if (type != napi_object) {
84         CM_LOG_E("type of param spec is not object");
85         return nullptr;
86     }
87 
88     napi_value purpose = nullptr;
89     napi_status status = napi_get_named_property(env, object, "purpose", &purpose);
90     if (status != napi_ok || purpose == nullptr) {
91         CM_LOG_E("get purpose failed");
92         return nullptr;
93     }
94 
95     NAPI_CALL(env, napi_typeof(env, purpose, &type));
96     if (type != napi_number) {
97         CM_LOG_E("type of param purpose is not number");
98         return nullptr;
99     }
100 
101     uint32_t purposeValue = 0;
102     status = napi_get_value_uint32(env, purpose, &purposeValue);
103     if (status != napi_ok) {
104         CM_LOG_E("get purpose value failed");
105         return nullptr;
106     }
107 
108     spec = static_cast<CmSignatureSpec *>(CmMalloc(sizeof(CmSignatureSpec)));
109     if (spec == nullptr) {
110         CM_LOG_E("malloc spec struct failed");
111         return nullptr;
112     }
113     spec->purpose = purposeValue;
114     spec->padding = CM_PADDING_PSS;
115     spec->digest = CM_DIGEST_SHA256;
116 
117     return GetInt32(env, 0);
118 }
119 
GetBlob(napi_env env,napi_value object,CmBlob * & blob)120 static napi_value GetBlob(napi_env env, napi_value object, CmBlob *&blob)
121 {
122     blob = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
123     if (blob == nullptr) {
124         CM_LOG_E("malloc blob failed");
125         return nullptr;
126     }
127     (void)memset_s(blob, sizeof(CmBlob), 0, sizeof(CmBlob));
128 
129     napi_value result = GetUint8Array(env, object, *blob);
130     if (result == nullptr) {
131         CM_LOG_E("parse blob data failed");
132         return nullptr;
133     }
134 
135     return GetInt32(env, 0);
136 }
137 
ParseCMInitParams(napi_env env,napi_callback_info info,SignVerifyAsyncContext context)138 static napi_value ParseCMInitParams(napi_env env, napi_callback_info info, SignVerifyAsyncContext context)
139 {
140     size_t argc = CM_NAPI_INIT_ARGS_CNT;
141     napi_value argv[CM_NAPI_INIT_ARGS_CNT] = { nullptr };
142     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
143 
144     if ((argc != CM_NAPI_INIT_ARGS_CNT) && (argc != (CM_NAPI_INIT_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
145         ThrowParamsError(env, PARAM_ERROR, "init arguments count invalid");
146         CM_LOG_E("init arguments count is not expected");
147         return nullptr;
148     }
149 
150     size_t index = 0;
151     napi_value result = ParseString(env, argv[index], context->authUri);
152     if (result == nullptr) {
153         ThrowParamsError(env, PARAM_ERROR, "get authUri type error");
154         CM_LOG_E("get uri failed when using init function");
155         return nullptr;
156     }
157 
158     index++;
159     result = ParseSpec(env, argv[index], context->spec);
160     if (result == nullptr) {
161         ThrowParamsError(env, PARAM_ERROR, "get spec type error");
162         CM_LOG_E("get sepc failed when using init function");
163         return nullptr;
164     }
165 
166     index++;
167     if (index < argc) {
168         context->callback = GetCallback(env, argv[index]);
169         if (context->callback == nullptr) {
170             ThrowParamsError(env, PARAM_ERROR, "Get callback type error");
171             CM_LOG_E("get callback function failed when using init function");
172             return nullptr;
173         }
174     }
175 
176     return GetInt32(env, 0);
177 }
178 
ParseCMUpdateParams(napi_env env,napi_callback_info info,SignVerifyAsyncContext context)179 static napi_value ParseCMUpdateParams(napi_env env, napi_callback_info info, SignVerifyAsyncContext context)
180 {
181     size_t argc = CM_NAPI_UPDATE_ARGS_CNT;
182     napi_value argv[CM_NAPI_UPDATE_ARGS_CNT] = { nullptr };
183     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
184 
185     if ((argc != CM_NAPI_UPDATE_ARGS_CNT) && (argc != (CM_NAPI_UPDATE_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
186         ThrowParamsError(env, PARAM_ERROR, "update arguments count invalid");
187         CM_LOG_E("update arguments count is not expected");
188         return nullptr;
189     }
190 
191     size_t index = 0;
192     napi_value result = GetBlob(env, argv[index], context->handle);
193     if (result == nullptr) {
194         ThrowParamsError(env, PARAM_ERROR, "get handle type error");
195         CM_LOG_E("get handle failed when using update function");
196         return nullptr;
197     }
198 
199     index++;
200     result = GetBlob(env, argv[index], context->inData);
201     if (result == nullptr) {
202         ThrowParamsError(env, PARAM_ERROR, "get inData type error");
203         CM_LOG_E("get inData failed when using update function");
204         return nullptr;
205     }
206 
207     index++;
208     if (index < argc) {
209         context->callback = GetCallback(env, argv[index]);
210         if (context->callback == nullptr) {
211             ThrowParamsError(env, PARAM_ERROR, "get callback type error");
212             CM_LOG_E("get callback function failed when using update function");
213             return nullptr;
214         }
215     }
216 
217     return GetInt32(env, 0);
218 }
219 
MallocFinishOutData(napi_env env,SignVerifyAsyncContext context)220 static napi_value MallocFinishOutData(napi_env env, SignVerifyAsyncContext context)
221 {
222     context->signature = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
223     if (context->signature == nullptr) { /* signature will free after all process */
224         CM_LOG_E("malloc outData failed when process sign finish");
225         ThrowParamsError(env, PARAM_ERROR, "malloc failed");
226         return nullptr;
227     }
228     (void)memset_s(context->signature, sizeof(CmBlob), 0, sizeof(CmBlob));
229 
230     uint8_t *data = static_cast<uint8_t *>(CmMalloc(OUT_SIGNATURE_SIZE));
231     if (data == nullptr) {
232         CM_LOG_E("malloc outData.data failed when process sign finish");
233         ThrowParamsError(env, PARAM_ERROR, "malloc failed");
234         return nullptr;
235     }
236     (void)memset_s(data, OUT_SIGNATURE_SIZE, 0, OUT_SIGNATURE_SIZE);
237 
238     context->signature->data = data;
239     context->signature->size = OUT_SIGNATURE_SIZE;
240     return GetInt32(env, 0);
241 }
242 
ProcessFinishOneParam(napi_env env,SignVerifyAsyncContext context)243 static napi_value ProcessFinishOneParam(napi_env env, SignVerifyAsyncContext context)
244 {
245     /* promise: sign */
246     context->isSign = true;
247     return MallocFinishOutData(env, context);
248 }
249 
CheckIsCallback(napi_env env,napi_value object,bool & isFunc)250 static int32_t CheckIsCallback(napi_env env, napi_value object, bool &isFunc)
251 {
252     isFunc = false;
253     napi_valuetype valueType = napi_undefined;
254     napi_status status = napi_typeof(env, object, &valueType);
255     if (status != napi_ok) {
256         CM_LOG_E("could not get object type");
257         return CMR_ERROR_INVALID_ARGUMENT;
258     }
259 
260     if (valueType == napi_function) {
261         isFunc = true;
262     }
263     return CM_SUCCESS;
264 }
265 
ProcessFinishTwoParam(napi_env env,napi_value * argv,SignVerifyAsyncContext context,size_t curIndex,size_t maxIndex)266 static napi_value ProcessFinishTwoParam(napi_env env, napi_value *argv, SignVerifyAsyncContext context,
267     size_t curIndex, size_t maxIndex)
268 {
269     curIndex++;
270     if (curIndex >= maxIndex) {
271         return nullptr; /* not possible */
272     }
273 
274     /*
275      * check wether arg 2 is callback: if true, get callback function and return: callback sign.
276      * else is promise verify, then get arg 2 as signature
277      */
278     bool isFunc = false;
279     int32_t ret = CheckIsCallback(env, argv[curIndex], isFunc);
280     if (ret != CM_SUCCESS) {
281         return nullptr;
282     }
283 
284     napi_value result = nullptr;
285     if (isFunc) {
286         /* callback: sign */
287         context->isSign = true;
288         result = MallocFinishOutData(env, context);
289         if (result == nullptr) {
290             return nullptr;
291         }
292 
293         context->callback = GetCallback(env, argv[curIndex]); /* return if arg 2 is callback */
294         if (context->callback == nullptr) {
295             ThrowParamsError(env, PARAM_ERROR, "sign: get callback type error");
296             CM_LOG_E("arg2 is callback: get sign callback function failed when using finish function");
297             return nullptr;
298         }
299         return GetInt32(env, 0);
300     }
301 
302     /* promise verify */
303     context->isSign = false;
304     result = GetBlob(env, argv[curIndex], context->signature);
305     if (result == nullptr) {
306         ThrowParamsError(env, PARAM_ERROR, "get signature type error");
307         CM_LOG_E("get signature failed when process promise verify");
308         return nullptr;
309     }
310 
311     return GetInt32(env, 0);
312 }
313 
ProcessFinishThreeParam(napi_env env,napi_value * argv,SignVerifyAsyncContext context,size_t curIndex,size_t maxIndex)314 static napi_value ProcessFinishThreeParam(napi_env env, napi_value *argv, SignVerifyAsyncContext context,
315     size_t curIndex, size_t maxIndex)
316 {
317     /* callback: verify */
318     context->isSign = false;
319 
320     curIndex++;
321     if (curIndex >= maxIndex) {
322         return nullptr; /* not possible */
323     }
324 
325     napi_value result = GetBlob(env, argv[curIndex], context->signature);
326     if (result == nullptr) {
327         ThrowParamsError(env, PARAM_ERROR, "get signature type error");
328         CM_LOG_E("get signature failed when process callback verify");
329         return nullptr;
330     }
331 
332     curIndex++;
333     if (curIndex >= maxIndex) {
334         return nullptr; /* not possible */
335     }
336 
337     context->callback = GetCallback(env, argv[curIndex]);
338     if (context->callback == nullptr) {
339         ThrowParamsError(env, PARAM_ERROR, "verify: get callback type error");
340         CM_LOG_E("get verify callback function failed when using finish function");
341         return nullptr;
342     }
343 
344     return GetInt32(env, 0);
345 }
346 
ParseCMFinishParams(napi_env env,napi_callback_info info,SignVerifyAsyncContext context)347 static napi_value ParseCMFinishParams(napi_env env, napi_callback_info info, SignVerifyAsyncContext context)
348 {
349     size_t argc = CM_NAPI_FINISH_ARGS_CNT;
350     napi_value argv[CM_NAPI_FINISH_ARGS_CNT] = { nullptr };
351     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
352 
353     if ((argc != CM_NAPI_FINISH_ARGS_CNT) && (argc != (CM_NAPI_FINISH_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT)) &&
354         (argc != (CM_NAPI_FINISH_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT - CM_NAPI_SIGNATURE_ARG_CNT))) {
355         ThrowParamsError(env, PARAM_ERROR, "finish arguments count invalid");
356         CM_LOG_E("finish arguments count is not expected");
357         return nullptr;
358     }
359 
360     size_t index = 0;
361     napi_value result = GetBlob(env, argv[index], context->handle);
362     if (result == nullptr) {
363         ThrowParamsError(env, PARAM_ERROR, "get handle type error");
364         CM_LOG_E("get handle failed when using finish function");
365         return nullptr;
366     }
367 
368     if (argc == CM_NAPI_FINISH_ARGS_CNT) {
369         return ProcessFinishThreeParam(env, argv, context, index, argc);
370     } else if (argc == (CM_NAPI_FINISH_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT)) {
371         return ProcessFinishTwoParam(env, argv, context, index, argc);
372     } else {
373  /* only this 3 types */
374         return ProcessFinishOneParam(env, context);
375     }
376 }
377 
ParseCMAbortParams(napi_env env,napi_callback_info info,SignVerifyAsyncContext context)378 static napi_value ParseCMAbortParams(napi_env env, napi_callback_info info, SignVerifyAsyncContext context)
379 {
380     size_t argc = CM_NAPI_ABORT_ARGS_CNT;
381     napi_value argv[CM_NAPI_ABORT_ARGS_CNT] = { nullptr };
382     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
383 
384     if ((argc != CM_NAPI_ABORT_ARGS_CNT) && (argc != (CM_NAPI_ABORT_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
385         ThrowParamsError(env, PARAM_ERROR, "abort arguments count invalid");
386         CM_LOG_E("abort arguments count is not expected");
387         return nullptr;
388     }
389 
390     size_t index = 0;
391     napi_value result = GetBlob(env, argv[index], context->handle);
392     if (result == nullptr) {
393         ThrowParamsError(env, PARAM_ERROR, "get handle type error");
394         CM_LOG_E("get handle failed when using abort function");
395         return nullptr;
396     }
397 
398     index++;
399     if (index < argc) {
400         context->callback = GetCallback(env, argv[index]);
401         if (context->callback == nullptr) {
402             ThrowParamsError(env, PARAM_ERROR, "get callback type error");
403             CM_LOG_E("get callback function failed when using abort function");
404             return nullptr;
405         }
406     }
407 
408     return GetInt32(env, 0);
409 }
410 
InitExecute(napi_env env,void * data)411 static void InitExecute(napi_env env, void *data)
412 {
413     SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
414     context->handle = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
415     if (context->handle == nullptr) {
416         CM_LOG_E("malloc handle out failed");
417         context->errCode = CMR_ERROR_MALLOC_FAIL;
418         return;
419     }
420     (void)memset_s(context->handle, sizeof(CmBlob), 0, sizeof(CmBlob));
421 
422     context->handle->data = static_cast<uint8_t *>(CmMalloc(OUT_HANLDE_SIZE));
423     if (context->handle->data == nullptr) {
424         CM_LOG_E("malloc handle.data failed");
425         context->errCode = CMR_ERROR_MALLOC_FAIL;
426         return;
427     }
428     (void)memset_s(context->handle->data, OUT_HANLDE_SIZE, 0, OUT_HANLDE_SIZE);
429     context->handle->size = OUT_HANLDE_SIZE;
430 
431     context->errCode = CmInit(context->authUri, context->spec, context->handle);
432 }
433 
GenerateArrayBuffer(napi_env env,uint8_t * data,uint32_t size)434 static napi_value GenerateArrayBuffer(napi_env env, uint8_t *data, uint32_t size)
435 {
436     uint8_t *tempBuf = static_cast<uint8_t *>(CmMalloc(size));
437     if (tempBuf == nullptr) {
438         CM_LOG_E("malloc outbuf failed");
439         return nullptr;
440     }
441     (void)memcpy_s(tempBuf, size, data, size);
442 
443     napi_value outBuffer = nullptr;
444     napi_status status = napi_create_external_arraybuffer(
445         env, tempBuf, size, [](napi_env env, void *data, void *hint) { CmFree(data); }, nullptr, &outBuffer);
446     if (status == napi_ok) {
447         tempBuf = nullptr; /* free by finalize callback */
448     } else {
449         CM_LOG_E("create external array buffer failed");
450         CM_FREE_PTR(tempBuf);
451         GET_AND_THROW_LAST_ERROR((env));
452     }
453 
454     return outBuffer;
455 }
456 
ConvertResultHandle(napi_env env,const CmBlob * handle)457 static napi_value ConvertResultHandle(napi_env env, const CmBlob *handle)
458 {
459     napi_value result = nullptr;
460     NAPI_CALL(env, napi_create_object(env, &result));
461 
462     napi_value handleNapi = nullptr;
463     napi_value handleBuf = GenerateArrayBuffer(env, handle->data, handle->size);
464     if (handleBuf != nullptr) {
465         NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, handle->size, handleBuf, 0, &handleNapi));
466     } else {
467         handleNapi = GetNull(env);
468     }
469     NAPI_CALL(env, napi_set_named_property(env, result, "handle", handleNapi));
470 
471     return result;
472 }
473 
InitComplete(napi_env env,napi_status status,void * data)474 static void InitComplete(napi_env env, napi_status status, void *data)
475 {
476     SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
477     napi_value result[RESULT_NUMBER] = { nullptr };
478     if (context->errCode == CM_SUCCESS) {
479         napi_create_uint32(env, 0, &result[0]);
480         result[1] = ConvertResultHandle(env, context->handle);
481     } else {
482         result[0] = GenerateBusinessError(env, context->errCode, "init failed");
483         napi_get_undefined(env, &result[1]);
484     }
485 
486     if (context->deferred != nullptr) {
487         GeneratePromise(env, context->deferred, context->errCode, result, sizeof(result));
488     } else {
489         GenerateCallback(env, context->callback, result, sizeof(result));
490     }
491     FreeSignVerifyAsyncContext(env, context);
492 }
493 
UpdateExecute(napi_env env,void * data)494 static void UpdateExecute(napi_env env, void *data)
495 {
496     SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
497     context->errCode = CmUpdate(context->handle, context->inData);
498 }
499 
UpdateOrAbortComplete(napi_env env,napi_status status,void * data)500 static void UpdateOrAbortComplete(napi_env env, napi_status status, void *data)
501 {
502     SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
503     napi_value result[RESULT_NUMBER] = { nullptr };
504     if (context->errCode == CM_SUCCESS) {
505         napi_create_uint32(env, 0, &result[0]);
506         napi_get_boolean(env, true, &result[1]);
507     } else {
508         result[0] = GenerateBusinessError(env, context->errCode, "update or abort process failed");
509         napi_get_undefined(env, &result[1]);
510     }
511 
512     if (context->deferred != nullptr) {
513         GeneratePromise(env, context->deferred, context->errCode, result, sizeof(result));
514     } else {
515         GenerateCallback(env, context->callback, result, sizeof(result));
516     }
517     FreeSignVerifyAsyncContext(env, context);
518 }
519 
FinishExecute(napi_env env,void * data)520 static void FinishExecute(napi_env env, void *data)
521 {
522     SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
523     if (context->isSign) {
524         CmBlob inData = { 0, nullptr };
525         context->errCode = CmFinish(context->handle, &inData, context->signature);
526         return;
527     }
528 
529     CmBlob outData = { 0, nullptr };
530     context->errCode = CmFinish(context->handle, context->signature, &outData);
531 }
532 
ConvertResultSignature(napi_env env,bool isSign,const CmBlob * sign)533 static napi_value ConvertResultSignature(napi_env env, bool isSign, const CmBlob *sign)
534 {
535     napi_value result = nullptr;
536     NAPI_CALL(env, napi_create_object(env, &result));
537 
538     napi_value signResultNapi = nullptr;
539     if (isSign) {
540         napi_value signBuf = GenerateArrayBuffer(env, sign->data, sign->size);
541         if (signBuf != nullptr) {
542             NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, sign->size, signBuf, 0, &signResultNapi));
543         } else {
544             signResultNapi = GetNull(env);
545         }
546     } else {
547         signResultNapi = GetNull(env);
548     }
549     NAPI_CALL(env, napi_set_named_property(env, result, "outData", signResultNapi));
550 
551     return result;
552 }
553 
FinishComplete(napi_env env,napi_status status,void * data)554 static void FinishComplete(napi_env env, napi_status status, void *data)
555 {
556     SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
557     napi_value result[RESULT_NUMBER] = { nullptr };
558     if (context->errCode == CM_SUCCESS) {
559         napi_create_uint32(env, 0, &result[0]);
560         result[1] = ConvertResultSignature(env, context->isSign, context->signature);
561     } else {
562         result[0] = GenerateBusinessError(env, context->errCode, "finish failed");
563         napi_get_undefined(env, &result[1]);
564     }
565 
566     if (context->deferred != nullptr) {
567         GeneratePromise(env, context->deferred, context->errCode, result, sizeof(result));
568     } else {
569         GenerateCallback(env, context->callback, result, sizeof(result));
570     }
571     FreeSignVerifyAsyncContext(env, context);
572 }
573 
AbortExecute(napi_env env,void * data)574 static void AbortExecute(napi_env env, void *data)
575 {
576     SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
577     context->errCode = CmAbort(context->handle);
578 }
579 
CMInitAsyncWork(napi_env env,SignVerifyAsyncContext context)580 static napi_value CMInitAsyncWork(napi_env env, SignVerifyAsyncContext context)
581 {
582     napi_value promise = nullptr;
583     GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
584 
585     napi_value resourceName = nullptr;
586     NAPI_CALL(env, napi_create_string_latin1(env, "cminit", NAPI_AUTO_LENGTH, &resourceName));
587 
588     NAPI_CALL(env, napi_create_async_work(
589         env, nullptr, resourceName,
590         InitExecute,
591         InitComplete,
592         static_cast<void *>(context),
593         &context->asyncWork));
594 
595     napi_status status = napi_queue_async_work(env, context->asyncWork);
596     if (status != napi_ok) {
597         ThrowParamsError(env, PARAM_ERROR, "queue async work error");
598         CM_LOG_E("queue async work failed when using init function");
599         return nullptr;
600     }
601     return promise;
602 }
603 
CMUpdateAsyncWork(napi_env env,SignVerifyAsyncContext context)604 static napi_value CMUpdateAsyncWork(napi_env env, SignVerifyAsyncContext context)
605 {
606     napi_value promise = nullptr;
607     GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
608 
609     napi_value resourceName = nullptr;
610     NAPI_CALL(env, napi_create_string_latin1(env, "cmupdate", NAPI_AUTO_LENGTH, &resourceName));
611 
612     NAPI_CALL(env, napi_create_async_work(
613         env, nullptr, resourceName,
614         UpdateExecute,
615         UpdateOrAbortComplete,
616         static_cast<void *>(context),
617         &context->asyncWork));
618 
619     napi_status status = napi_queue_async_work(env, context->asyncWork);
620     if (status != napi_ok) {
621         ThrowParamsError(env, PARAM_ERROR, "queue async work error");
622         CM_LOG_E("queue async work failed when using update function");
623         return nullptr;
624     }
625     return promise;
626 }
627 
CMFinishAsyncWork(napi_env env,SignVerifyAsyncContext context)628 static napi_value CMFinishAsyncWork(napi_env env, SignVerifyAsyncContext context)
629 {
630     napi_value promise = nullptr;
631     GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
632 
633     napi_value resourceName = nullptr;
634     NAPI_CALL(env, napi_create_string_latin1(env, "cmfinish", NAPI_AUTO_LENGTH, &resourceName));
635 
636     NAPI_CALL(env, napi_create_async_work(
637         env, nullptr, resourceName,
638         FinishExecute,
639         FinishComplete,
640         static_cast<void *>(context),
641         &context->asyncWork));
642 
643     napi_status status = napi_queue_async_work(env, context->asyncWork);
644     if (status != napi_ok) {
645         ThrowParamsError(env, PARAM_ERROR, "queue async work error");
646         CM_LOG_E("queue async work failed when using finish function");
647         return nullptr;
648     }
649     return promise;
650 }
651 
CMAbortAsyncWork(napi_env env,SignVerifyAsyncContext context)652 static napi_value CMAbortAsyncWork(napi_env env, SignVerifyAsyncContext context)
653 {
654     napi_value promise = nullptr;
655     GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
656 
657     napi_value resourceName = nullptr;
658     NAPI_CALL(env, napi_create_string_latin1(env, "cmabort", NAPI_AUTO_LENGTH, &resourceName));
659 
660     NAPI_CALL(env, napi_create_async_work(
661         env, nullptr, resourceName,
662         AbortExecute,
663         UpdateOrAbortComplete,
664         static_cast<void *>(context),
665         &context->asyncWork));
666 
667     napi_status status = napi_queue_async_work(env, context->asyncWork);
668     if (status != napi_ok) {
669         ThrowParamsError(env, PARAM_ERROR, "queue async work error");
670         CM_LOG_E("queue async work failed when using abort function");
671         return nullptr;
672     }
673     return promise;
674 }
675 
CMNapiInit(napi_env env,napi_callback_info info)676 napi_value CMNapiInit(napi_env env, napi_callback_info info)
677 {
678     SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
679     if (context == nullptr) {
680         CM_LOG_E("init cm init context failed");
681         return nullptr;
682     }
683 
684     napi_value result = ParseCMInitParams(env, info, context);
685     if (result == nullptr) {
686         CM_LOG_E("parse cm init params failed");
687         FreeSignVerifyAsyncContext(env, context);
688         return nullptr;
689     }
690 
691     result = CMInitAsyncWork(env, context);
692     if (result == nullptr) {
693         CM_LOG_E("start cm init async work failed");
694         FreeSignVerifyAsyncContext(env, context);
695         return nullptr;
696     }
697 
698     return result;
699 }
700 
CMNapiUpdate(napi_env env,napi_callback_info info)701 napi_value CMNapiUpdate(napi_env env, napi_callback_info info)
702 {
703     SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
704     if (context == nullptr) {
705         CM_LOG_E("init cm update context failed");
706         return nullptr;
707     }
708 
709     napi_value result = ParseCMUpdateParams(env, info, context);
710     if (result == nullptr) {
711         CM_LOG_E("parse cm update params failed");
712         FreeSignVerifyAsyncContext(env, context);
713         return nullptr;
714     }
715 
716     result = CMUpdateAsyncWork(env, context);
717     if (result == nullptr) {
718         CM_LOG_E("start cm update async work failed");
719         FreeSignVerifyAsyncContext(env, context);
720         return nullptr;
721     }
722 
723     return result;
724 }
725 
CMNapiFinish(napi_env env,napi_callback_info info)726 napi_value CMNapiFinish(napi_env env, napi_callback_info info)
727 {
728     SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
729     if (context == nullptr) {
730         CM_LOG_E("init cm finish context failed");
731         return nullptr;
732     }
733 
734     napi_value result = ParseCMFinishParams(env, info, context);
735     if (result == nullptr) {
736         CM_LOG_E("parse cm finish params failed");
737         FreeSignVerifyAsyncContext(env, context);
738         return nullptr;
739     }
740 
741     result = CMFinishAsyncWork(env, context);
742     if (result == nullptr) {
743         CM_LOG_E("start cm finish async work failed");
744         FreeSignVerifyAsyncContext(env, context);
745         return nullptr;
746     }
747 
748     return result;
749 }
750 
CMNapiAbort(napi_env env,napi_callback_info info)751 napi_value CMNapiAbort(napi_env env, napi_callback_info info)
752 {
753     SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
754     if (context == nullptr) {
755         CM_LOG_E("init cm abort context failed");
756         return nullptr;
757     }
758 
759     napi_value result = ParseCMAbortParams(env, info, context);
760     if (result == nullptr) {
761         CM_LOG_E("parse cm abort params failed");
762         FreeSignVerifyAsyncContext(env, context);
763         return nullptr;
764     }
765 
766     result = CMAbortAsyncWork(env, context);
767     if (result == nullptr) {
768         CM_LOG_E("start cm abort async work failed");
769         FreeSignVerifyAsyncContext(env, context);
770         return nullptr;
771     }
772 
773     return result;
774 }
775 }  // namespace CMNapi
776 
777