1 /*
2  * Copyright (c) 2022-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 <string>
17 
18 #include "napi/native_api.h"
19 #include "napi/native_node_api.h"
20 
21 #include "cipher.h"
22 #include "cipher_log.h"
23 #include "securec.h"
24 
25 namespace OHOS::Ace::Napi {
26 namespace {
27 }
28 
29 struct CallbackContext {
30     napi_ref callbackSuccess = nullptr;
31     napi_ref callbackFail = nullptr;
32     napi_ref callbackComplete = nullptr;
33 };
34 
35 struct CommonNapiValue {
36     napi_env env = nullptr;
37     napi_async_work work = nullptr;
38     napi_value action_napi = nullptr;
39     napi_value text_napi = nullptr;
40     napi_value key_napi = nullptr;
41     napi_value transformation_napi = nullptr;
42 };
43 
44 struct RsaAsyncContext {
45     CommonNapiValue *commonNapi = nullptr;
46     CallbackContext *callback = nullptr;
47     RsaKeyData *rsaKey = nullptr;
48     RsaData *textIn = nullptr;
49     RsaData *textOut = nullptr;
50     int32_t ret = 0;
51 };
52 
53 struct AesAsyncContext {
54     CommonNapiValue *commonNapi = nullptr;
55     napi_value iv_napi = nullptr;
56     napi_value ivOffset_napi = nullptr;
57     napi_value ivLen_napi = nullptr;
58     CallbackContext *callback = nullptr;
59     char *key = nullptr;
60     char *textIn = nullptr;
61     char *textOut = nullptr;
62     char *action = nullptr;
63     char *transformation = nullptr;
64     char *ivBuf = nullptr;
65     int32_t ivOffset = 0;
66     int32_t ivLen = 0;
67     int32_t ret = 0;
68 };
69 
70 static const char g_failCode[] = "System error";
71 static const int ERROR_CODE = 200;
72 static const int FAIL_ARG = 2;
73 static const int IV_LEN = 16;
74 
75 #define SELF_FREE_PTR(PTR, FREE_FUNC) \
76 { \
77     if ((PTR) != nullptr) { \
78         FREE_FUNC(PTR); \
79         (PTR) = nullptr; \
80     } \
81 }
82 
83 #define CIPHER_FREE_PTR(p) SELF_FREE_PTR(p, free)
84 
GetString(napi_env env,napi_value object,char ** element,size_t * len)85 static int32_t GetString(napi_env env, napi_value object, char **element, size_t *len)
86 {
87     napi_valuetype valueType = napi_undefined;
88     napi_status status = napi_typeof(env, object, &valueType);
89     if (status != napi_ok) {
90         return ERROR_CODE_GENERAL;
91     }
92 
93     if (valueType != napi_string) {
94         *element = nullptr;
95         CIPHER_LOG_E("input is not a string-type object");
96         return ERROR_SUCCESS;
97     }
98 
99     status = napi_get_value_string_utf8(env, object, nullptr, 0, len);
100     if (status != napi_ok) {
101         return ERROR_CODE_GENERAL;
102     }
103 
104     *element = static_cast<char *>(malloc(*len + 1));
105     if (*element == nullptr) {
106         CIPHER_LOG_E("malloc element fail");
107         return ERROR_CODE_GENERAL;
108     }
109     (void)memset_s(*element, *len + 1, 0, *len + 1);
110     size_t result = 0;
111     status = napi_get_value_string_utf8(env, object, *element, *len + 1, &result);
112     if (status != napi_ok) {
113         return ERROR_CODE_GENERAL;
114     }
115     return ERROR_SUCCESS;
116 }
117 
GetCallbackFuncProperty(napi_env env,napi_value object,napi_value * successFunc,napi_value * failFunc,napi_value * completeFunc)118 static int32_t GetCallbackFuncProperty(napi_env env, napi_value object, napi_value *successFunc,
119     napi_value *failFunc, napi_value *completeFunc)
120 {
121     napi_status status = napi_get_named_property(env, object, "success", successFunc);
122     if (status != napi_ok || *successFunc == nullptr) {
123         CIPHER_LOG_E("get success property fail");
124         return ERROR_CODE_GENERAL;
125     }
126     status = napi_get_named_property(env, object, "fail", failFunc);
127     if (status != napi_ok || *failFunc == nullptr) {
128         CIPHER_LOG_E("get fail property fail");
129         return ERROR_CODE_GENERAL;
130     }
131     status = napi_get_named_property(env, object, "complete", completeFunc);
132     if (status != napi_ok || *completeFunc == nullptr) {
133         CIPHER_LOG_E("get complete property fail");
134         return ERROR_CODE_GENERAL;
135     }
136     return ERROR_SUCCESS;
137 }
138 
CreateCallbackReference(napi_env env,napi_value successFunc,napi_value failFunc,napi_value completeFunc,CallbackContext * callback)139 static int32_t CreateCallbackReference(napi_env env, napi_value successFunc, napi_value failFunc,
140     napi_value completeFunc, CallbackContext *callback)
141 {
142     napi_valuetype valueType = napi_undefined;
143     napi_status status = napi_typeof(env, successFunc, &valueType);
144     if (status != napi_ok) {
145         return ERROR_CODE_GENERAL;
146     }
147     if (valueType != napi_function) {
148         return ERROR_CODE_GENERAL;
149     }
150 
151     status = napi_create_reference(env, successFunc, 1, &callback->callbackSuccess);
152     if (status != napi_ok) {
153         CIPHER_LOG_E("create success reference fail");
154         return ERROR_CODE_GENERAL;
155     }
156 
157     status = napi_create_reference(env, failFunc, 1, &callback->callbackFail);
158     if (status != napi_ok) {
159         CIPHER_LOG_E("create fail reference fail");
160         return ERROR_CODE_GENERAL;
161     }
162 
163     status = napi_create_reference(env, completeFunc, 1, &callback->callbackComplete);
164     if (status != napi_ok) {
165         CIPHER_LOG_E("create complete reference fail");
166         return ERROR_CODE_GENERAL;
167     }
168 
169     return ERROR_SUCCESS;
170 }
171 
ReadAesData(napi_env env,AesAsyncContext * context)172 static int32_t ReadAesData(napi_env env, AesAsyncContext *context)
173 {
174     size_t len = 0;
175     int32_t ret = GetString(env, context->commonNapi->action_napi, &context->action, &len);
176     if (ret != ERROR_SUCCESS || context->action == nullptr) {
177         CIPHER_LOG_E("get action fail");
178         return ret;
179     }
180 
181     len = 0;
182     ret = GetString(env, context->commonNapi->text_napi, &context->textIn, &len);
183     if (ret != ERROR_SUCCESS || context->textIn == nullptr) {
184         CIPHER_LOG_E("get text fail");
185         return ret;
186     }
187 
188     len = 0;
189     ret = GetString(env, context->commonNapi->key_napi, &context->key, &len);
190     if (ret != ERROR_SUCCESS || context->key == nullptr) {
191         CIPHER_LOG_E("get key fail");
192         return ret;
193     }
194 
195     len = 0;
196     ret = GetString(env, context->commonNapi->transformation_napi, &context->transformation, &len);
197     if (ret != ERROR_SUCCESS) {
198         CIPHER_LOG_E("get transformition fail");
199         return ret;
200     }
201 
202     (void)context->ivLen_napi;
203     context->ivLen = IV_LEN;
204 
205     len = 0;
206     ret = GetString(env, context->iv_napi, &context->ivBuf, &len);
207     if (ret != ERROR_SUCCESS) {
208         CIPHER_LOG_E("get ivBuf fail");
209         return ret;
210     }
211 
212     (void)context->ivOffset_napi;
213     context->ivOffset = 0;
214     return ret;
215 }
216 
GetCommonProperties(napi_env env,napi_value object,CommonNapiValue * commonNapi)217 static int32_t GetCommonProperties(napi_env env, napi_value object, CommonNapiValue *commonNapi)
218 {
219     napi_status status = napi_get_named_property(env, object, "action", &commonNapi->action_napi);
220     if (status != napi_ok || commonNapi->action_napi == nullptr) {
221         CIPHER_LOG_E("get action property fail");
222         return ERROR_CODE_GENERAL;
223     }
224     status = napi_get_named_property(env, object, "text", &commonNapi->text_napi);
225     if (status != napi_ok || commonNapi->text_napi == nullptr) {
226         CIPHER_LOG_E("get text property fail");
227         return ERROR_CODE_GENERAL;
228     }
229     status = napi_get_named_property(env, object, "key", &commonNapi->key_napi);
230     if (status != napi_ok || commonNapi->key_napi == nullptr) {
231         CIPHER_LOG_E("get key property fail");
232         return ERROR_CODE_GENERAL;
233     }
234     status = napi_get_named_property(env, object, "transformation", &commonNapi->transformation_napi);
235     if (status != napi_ok) {
236         CIPHER_LOG_E("get transformation property fail");
237         return ERROR_CODE_GENERAL;
238     }
239     return ERROR_SUCCESS;
240 }
241 
GetAesProperties(napi_env env,napi_value object,AesAsyncContext * context)242 static int32_t GetAesProperties(napi_env env, napi_value object, AesAsyncContext *context)
243 {
244     int32_t ret = GetCommonProperties(env, object, context->commonNapi);
245     if (ret != ERROR_SUCCESS) {
246         return ret;
247     }
248 
249     napi_status status = napi_get_named_property(env, object, "iv", &context->iv_napi);
250     if (status != napi_ok) {
251         CIPHER_LOG_E("get iv property fail");
252         return ERROR_CODE_GENERAL;
253     }
254     status = napi_get_named_property(env, object, "ivOffset", &context->ivOffset_napi);
255     if (status != napi_ok || context->ivOffset_napi == nullptr) {
256         CIPHER_LOG_E("get ivOffset property fail");
257         return ERROR_CODE_GENERAL;
258     }
259     status = napi_get_named_property(env, object, "ivLen", &context->ivLen_napi);
260     if (status != napi_ok || context->ivLen_napi == nullptr) {
261         CIPHER_LOG_E("get ivLen property fail");
262         return ERROR_CODE_GENERAL;
263     }
264     return ERROR_SUCCESS;
265 }
266 
GetAesInput(napi_env env,napi_value object,AesAsyncContext * context)267 static int32_t GetAesInput(napi_env env, napi_value object, AesAsyncContext *context)
268 {
269     napi_value successFunc = nullptr;
270     napi_value failFunc = nullptr;
271     napi_value completeFunc = nullptr;
272     napi_valuetype valueType = napi_undefined;
273     context->commonNapi = static_cast<CommonNapiValue *>(malloc(sizeof(struct CommonNapiValue)));
274     if (context->commonNapi == nullptr) {
275         return ERROR_CODE_GENERAL;
276     }
277     (void)memset_s(context->commonNapi, sizeof(struct CommonNapiValue), 0, sizeof(struct CommonNapiValue));
278 
279     napi_status status = napi_typeof(env, object, &valueType);
280     if (status != napi_ok) {
281         return ERROR_CODE_GENERAL;
282     }
283     if (valueType != napi_object) {
284         return ERROR_CODE_GENERAL;
285     }
286 
287     int32_t ret = GetAesProperties(env, object, context);
288     if (ret != ERROR_SUCCESS) {
289         return ret;
290     }
291 
292     ret = GetCallbackFuncProperty(env, object, &successFunc, &failFunc, &completeFunc);
293     if (ret != ERROR_SUCCESS) {
294         return ret;
295     }
296 
297     context->callback = static_cast<CallbackContext *>(malloc(sizeof(struct CallbackContext)));
298     if (context->callback == nullptr) {
299         return ERROR_CODE_GENERAL;
300     }
301     (void)memset_s(context->callback, sizeof(struct CallbackContext), 0, sizeof(struct CallbackContext));
302 
303     ret = CreateCallbackReference(env, successFunc, failFunc, completeFunc, context->callback);
304     if (ret != ERROR_SUCCESS) {
305     }
306 
307     return ReadAesData(env, context);
308 }
309 
AesExcute(AesAsyncContext * asyncContext)310 static int32_t AesExcute(AesAsyncContext *asyncContext)
311 {
312     AesCryptContext aes = { { nullptr, nullptr, 0, 0, 0 }, CIPHER_AES_ECB, { nullptr, nullptr, 0, 0 } };
313     AesIvMode iv = { nullptr, nullptr, 0, 0 };
314     iv.ivBuf = asyncContext->ivBuf;
315     iv.ivLen = asyncContext->ivLen;
316     iv.ivOffset = asyncContext->ivOffset;
317     iv.transformation = asyncContext->transformation;
318 
319     int ret = InitAesCryptData(asyncContext->action, asyncContext->textIn, asyncContext->key, &iv, &aes);
320     if (ret != ERROR_SUCCESS) {
321         CIPHER_LOG_E("InitAesCryptData fail, ret is %d", ret);
322         return ret;
323     }
324 
325     ret = AesCrypt(&aes);
326     if (ret != ERROR_SUCCESS) {
327         CIPHER_LOG_E("AesCrypt fail, ret is %d", ret);
328     }
329     asyncContext->textOut = static_cast<char *>(malloc(strlen(aes.data.text) + 1));
330     if (asyncContext->textOut == nullptr) {
331         DeinitAesCryptData(&aes);
332         return ERROR_CODE_GENERAL;
333     }
334     (void)memset_s(asyncContext->textOut, strlen(aes.data.text) + 1, 0, strlen(aes.data.text) + 1);
335     (void)memcpy_s(asyncContext->textOut, strlen(aes.data.text) + 1, aes.data.text, strlen(aes.data.text));
336     DeinitAesCryptData(&aes);
337 
338     return ret;
339 }
340 
ReadRsaData(napi_env env,RsaAsyncContext * context)341 static int32_t ReadRsaData(napi_env env, RsaAsyncContext *context)
342 {
343     context->rsaKey = static_cast<RsaKeyData *>(malloc(sizeof(RsaKeyData)));
344     if (context->rsaKey == nullptr) {
345         return ERROR_CODE_GENERAL;
346     }
347     (void)memset_s(context->rsaKey, sizeof(RsaKeyData), 0, sizeof(RsaKeyData));
348 
349     context->rsaKey->trans = nullptr;
350     context->textIn = static_cast<RsaData *>(malloc(sizeof(RsaData)));
351     if (context->textIn == nullptr) {
352         return ERROR_CODE_GENERAL;
353     }
354     (void)memset_s(context->textIn, sizeof(RsaData), 0, sizeof(RsaData));
355 
356     context->textOut = static_cast<RsaData *>(malloc(sizeof(RsaData)));
357     if (context->textOut == nullptr) {
358         return ERROR_CODE_GENERAL;
359     }
360     (void)memset_s(context->textOut, sizeof(RsaData), 0, sizeof(RsaData));
361 
362     context->textOut->data = nullptr;
363     context->textOut->length = 0;
364 
365     size_t len = 0;
366     int32_t ret = GetString(env, context->commonNapi->action_napi, &context->rsaKey->action, &len);
367     if (ret != ERROR_SUCCESS || context->rsaKey->action == nullptr) {
368         CIPHER_LOG_E("get action fail");
369         return ret;
370     }
371 
372     ret = GetString(env, context->commonNapi->text_napi, &context->textIn->data, &context->textIn->length);
373     if (ret != ERROR_SUCCESS || context->textIn->data == nullptr) {
374         CIPHER_LOG_E("get textIn fail");
375         return ret;
376     }
377 
378     ret = GetString(env, context->commonNapi->key_napi, &context->rsaKey->key, &context->rsaKey->keyLen);
379     if (ret != ERROR_SUCCESS || context->rsaKey->key == nullptr) {
380         CIPHER_LOG_E("get key fail");
381         return ret;
382     }
383 
384     len = 0;
385     ret = GetString(env, context->commonNapi->transformation_napi, &context->rsaKey->trans, &len);
386     if (ret != ERROR_SUCCESS) {
387         CIPHER_LOG_E("get trans fail");
388     }
389     return ret;
390 }
391 
GetRsaInput(napi_env env,napi_value object,RsaAsyncContext * context)392 static int32_t GetRsaInput(napi_env env, napi_value object, RsaAsyncContext *context)
393 {
394     napi_value successFunc = nullptr;
395     napi_value failFunc = nullptr;
396     napi_value completeFunc = nullptr;
397     napi_valuetype valueType = napi_undefined;
398     context->commonNapi = static_cast<CommonNapiValue *>(malloc(sizeof(struct CommonNapiValue)));
399     if (context->commonNapi == nullptr) {
400         return ERROR_CODE_GENERAL;
401     }
402     (void)memset_s(context->commonNapi, sizeof(struct CommonNapiValue), 0, sizeof(struct CommonNapiValue));
403 
404     napi_status status = napi_typeof(env, object, &valueType);
405     if (status != napi_ok) {
406         return ERROR_CODE_GENERAL;
407     }
408     if (valueType != napi_object) {
409         return ERROR_CODE_GENERAL;
410     }
411 
412     int32_t ret = GetCommonProperties(env, object, context->commonNapi);
413     if (ret != ERROR_SUCCESS) {
414         return ret;
415     }
416 
417     ret = GetCallbackFuncProperty(env, object, &successFunc, &failFunc, &completeFunc);
418     if (ret != ERROR_SUCCESS) {
419         return ret;
420     }
421 
422     context->callback = static_cast<CallbackContext *>(malloc(sizeof(struct CallbackContext)));
423     if (context->callback == nullptr) {
424         return ERROR_CODE_GENERAL;
425     }
426     (void)memset_s(context->callback, sizeof(struct CallbackContext), 0, sizeof(struct CallbackContext));
427 
428     ret = CreateCallbackReference(env, successFunc, failFunc, completeFunc, context->callback);
429     if (ret != ERROR_SUCCESS) {
430     }
431 
432     return ReadRsaData(env, context);
433 }
434 
RsaExcute(RsaAsyncContext * asyncContext)435 static int32_t RsaExcute(RsaAsyncContext *asyncContext)
436 {
437     if ((asyncContext->rsaKey->key == nullptr) || (asyncContext->textIn->data == nullptr)) {
438         return ERROR_CODE_GENERAL;
439     }
440 
441     int32_t ret = RsaCrypt(asyncContext->rsaKey, asyncContext->textIn, asyncContext->textOut);
442     if ((ret != ERROR_SUCCESS) || (asyncContext->textOut->length == 0)) {
443         return ERROR_CODE_GENERAL;
444     }
445 
446     asyncContext->textOut->data = static_cast<char *>(malloc(asyncContext->textOut->length));
447     if (asyncContext->textOut->data == nullptr) {
448         return ERROR_CODE_GENERAL;
449     }
450     (void)memset_s(asyncContext->textOut->data, asyncContext->textOut->length, 0, asyncContext->textOut->length);
451 
452     ret = RsaCrypt(asyncContext->rsaKey, asyncContext->textIn, asyncContext->textOut);
453     if (ret != ERROR_SUCCESS) {
454         return ret;
455     }
456     return ret;
457 }
458 
SetComplete(napi_env env,CallbackContext * asyncContext)459 void SetComplete(napi_env env, CallbackContext *asyncContext)
460 {
461     napi_value callback = nullptr;
462     napi_value ret = 0;
463     napi_get_reference_value(env, asyncContext->callbackComplete, &callback);
464     napi_call_function(env, nullptr, callback, 0, nullptr, &ret);
465     napi_delete_reference(env, asyncContext->callbackComplete);
466 }
467 
SetSuccess(napi_env env,char * textOut,size_t textLength,CallbackContext * asyncContext)468 void SetSuccess(napi_env env, char *textOut, size_t textLength, CallbackContext *asyncContext)
469 {
470     napi_value callback = nullptr;
471     napi_value ret;
472 
473     napi_value result = nullptr;
474     napi_value returnObj = nullptr;
475     napi_create_object(env, &returnObj);
476     napi_create_string_utf8(env, textOut, textLength, &result);
477     napi_set_named_property(env, returnObj, "text", result);
478 
479     napi_get_reference_value(env, asyncContext->callbackSuccess, &callback);
480     napi_call_function(env, nullptr, callback, 1, &returnObj, &ret);
481     napi_delete_reference(env, asyncContext->callbackSuccess);
482 }
483 
SetFail(napi_env env,CallbackContext * asyncContext)484 void SetFail(napi_env env, CallbackContext *asyncContext)
485 {
486     napi_value callback = nullptr;
487     napi_value ret;
488 
489     napi_value result = nullptr;
490     napi_create_string_utf8(env, g_failCode, sizeof(g_failCode), &result);
491 
492     napi_value errorCode = nullptr;
493     napi_create_int32(env, ERROR_CODE, &errorCode);
494 
495     napi_value params[FAIL_ARG] = { result, errorCode };
496     napi_get_reference_value(env, asyncContext->callbackFail, &callback);
497     napi_call_function(env, nullptr, callback, FAIL_ARG, params, &ret);
498     napi_delete_reference(env, asyncContext->callbackFail);
499 }
500 
DeleteRsaAsyncContext(napi_env env,RsaAsyncContext * context)501 static void DeleteRsaAsyncContext(napi_env env, RsaAsyncContext *context)
502 {
503     if (context == nullptr) {
504         return;
505     }
506 
507     CIPHER_FREE_PTR(context->commonNapi);
508 
509     CIPHER_FREE_PTR(context->callback);
510 
511     if (context->textIn != nullptr) {
512         CIPHER_FREE_PTR(context->textIn->data);
513         CIPHER_FREE_PTR(context->textIn);
514     }
515 
516     if (context->textOut != nullptr) {
517         if (context->textOut->data != nullptr) {
518             (void)memset_s(context->textOut->data, context->textOut->length, 0, context->textOut->length);
519             CIPHER_FREE_PTR(context->textOut->data);
520         }
521         CIPHER_FREE_PTR(context->textOut);
522     }
523 
524     if (context->rsaKey != nullptr) {
525         CIPHER_FREE_PTR(context->rsaKey->trans);
526         CIPHER_FREE_PTR(context->rsaKey->action);
527         if (context->rsaKey->key != nullptr) {
528             (void)memset_s(context->rsaKey->key, context->rsaKey->keyLen, 0, context->rsaKey->keyLen);
529             CIPHER_FREE_PTR(context->rsaKey->key);
530         }
531         CIPHER_FREE_PTR(context->rsaKey);
532     }
533 }
534 
DeleteAesAsyncContext(napi_env env,AesAsyncContext * context)535 static void DeleteAesAsyncContext(napi_env env, AesAsyncContext *context)
536 {
537     if (context == nullptr) {
538         return;
539     }
540 
541     CIPHER_FREE_PTR(context->commonNapi);
542 
543     CIPHER_FREE_PTR(context->callback);
544 
545     if (context->key != nullptr) {
546         (void)memset_s(context->key, strlen(context->key), 0, strlen(context->key));
547     }
548     CIPHER_FREE_PTR(context->key);
549     CIPHER_FREE_PTR(context->textIn);
550     CIPHER_FREE_PTR(context->action);
551 
552     CIPHER_FREE_PTR(context->ivBuf);
553     CIPHER_FREE_PTR(context->transformation);
554 
555     if (context->textOut != nullptr) {
556         (void)memset_s(context->textOut, strlen(context->textOut), 0, strlen(context->textOut));
557     }
558     CIPHER_FREE_PTR(context->textOut);
559 }
560 
JSCipherRsa(napi_env env,napi_callback_info info)561 static napi_value JSCipherRsa(napi_env env, napi_callback_info info)
562 {
563     size_t argc = 1;
564     napi_value argv[1] = {0};
565     void *data = nullptr;
566     napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
567     auto rsaAsyncContext = new RsaAsyncContext();
568 
569     rsaAsyncContext->ret = GetRsaInput(env, argv[0], rsaAsyncContext);
570     if (rsaAsyncContext->ret != ERROR_SUCCESS) {
571         DeleteRsaAsyncContext(env, rsaAsyncContext);
572         delete rsaAsyncContext;
573         CIPHER_LOG_E("Failed to get rsa input.");
574         return nullptr;
575     }
576 
577     napi_value resource = nullptr;
578     napi_create_string_utf8(env, "JSCipherRsa", NAPI_AUTO_LENGTH, &resource);
579     napi_create_async_work(
580         env, nullptr, resource,
581         [](napi_env env, void *data) {
582             RsaAsyncContext *asyncContext = (RsaAsyncContext *)data;
583             if (asyncContext->ret == ERROR_SUCCESS) {
584                 asyncContext->ret = RsaExcute(asyncContext);
585             }
586         },
587 
588         [](napi_env env, napi_status status, void *data) {
589             RsaAsyncContext *asyncContext = (RsaAsyncContext *)data;
590             if (asyncContext->ret != ERROR_SUCCESS) {
591                 SetFail(env, asyncContext->callback);
592                 SetComplete(env, asyncContext->callback);
593                 napi_delete_reference(env, asyncContext->callback->callbackSuccess);
594             } else {
595                 SetSuccess(env, asyncContext->textOut->data, asyncContext->textOut->length, asyncContext->callback);
596                 SetComplete(env, asyncContext->callback);
597                 napi_delete_reference(env, asyncContext->callback->callbackFail);
598             }
599             napi_delete_async_work(env, asyncContext->commonNapi->work);
600             DeleteRsaAsyncContext(env, asyncContext);
601             delete asyncContext;
602         },
603         reinterpret_cast<void *>(rsaAsyncContext),
604         &rsaAsyncContext->commonNapi->work);
605         napi_queue_async_work(env, rsaAsyncContext->commonNapi->work);
606         return nullptr;
607 }
608 
JSCipherAes(napi_env env,napi_callback_info info)609 static napi_value JSCipherAes(napi_env env, napi_callback_info info)
610 {
611     size_t argc = 1;
612     napi_value argv[1] = {0};
613     void *data = nullptr;
614     napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
615     auto aesAsyncContext = new AesAsyncContext();
616 
617     aesAsyncContext->ret = GetAesInput(env, argv[0], aesAsyncContext);
618     if (aesAsyncContext->ret != ERROR_SUCCESS) {
619         DeleteAesAsyncContext(env, aesAsyncContext);
620         delete aesAsyncContext;
621         CIPHER_LOG_E("Failed to get aes input.");
622         return nullptr;
623     }
624 
625     napi_value resource = nullptr;
626     napi_create_string_utf8(env, "JSCipherAes", NAPI_AUTO_LENGTH, &resource);
627     napi_create_async_work(
628         env, nullptr, resource,
629         [](napi_env env, void *data) {
630             AesAsyncContext *asyncContext = (AesAsyncContext *)data;
631             if (asyncContext->ret == ERROR_SUCCESS) {
632                 asyncContext->ret = AesExcute(asyncContext);
633             }
634         },
635 
636         [](napi_env env, napi_status status, void *data) {
637             AesAsyncContext *asyncContext = (AesAsyncContext *)data;
638             if (asyncContext->ret != ERROR_SUCCESS) {
639                 SetFail(env, asyncContext->callback);
640                 SetComplete(env, asyncContext->callback);
641                 napi_delete_reference(env, asyncContext->callback->callbackSuccess);
642             } else {
643                 SetSuccess(env, asyncContext->textOut, static_cast<size_t>(strlen(asyncContext->textOut)),
644                     asyncContext->callback);
645                 SetComplete(env, asyncContext->callback);
646                 napi_delete_reference(env, asyncContext->callback->callbackFail);
647             }
648             napi_delete_async_work(env, asyncContext->commonNapi->work);
649             DeleteAesAsyncContext(env, asyncContext);
650             delete asyncContext;
651         },
652         reinterpret_cast<void *>(aesAsyncContext),
653         &aesAsyncContext->commonNapi->work);
654         napi_queue_async_work(env, aesAsyncContext->commonNapi->work);
655         return nullptr;
656 }
657 
658 
CipherExport(napi_env env,napi_value exports)659 static napi_value CipherExport(napi_env env, napi_value exports)
660 {
661     static napi_property_descriptor cipherDesc[] = {
662         DECLARE_NAPI_FUNCTION("aes", JSCipherAes),
663         DECLARE_NAPI_FUNCTION("rsa", JSCipherRsa),
664     };
665     NAPI_CALL(env, napi_define_properties(
666         env, exports, sizeof(cipherDesc) / sizeof(cipherDesc[0]), cipherDesc));
667     return exports;
668 }
669 
670 static napi_module CipherModule = {
671     .nm_version = 1,
672     .nm_flags = 0,
673     .nm_filename = nullptr,
674     .nm_register_func = CipherExport,
675     .nm_modname = "cipher",
676     .nm_priv = reinterpret_cast<void *>(0),
677     .reserved = { 0 },
678 };
679 
CipherRegister()680 extern "C" __attribute__((constructor)) void CipherRegister()
681 {
682     napi_module_register(&CipherModule);
683 }
684 }
685