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 "napi_cipher.h"
17 #include "napi_key.h"
18 #include "securec.h"
19 #include "log.h"
20 #include "memory.h"
21
22 #include "cipher.h"
23 #include "napi_utils.h"
24 #include "napi_crypto_framework_defines.h"
25 #include "detailed_iv_params.h"
26 #include "detailed_gcm_params.h"
27 #include "detailed_ccm_params.h"
28
29 namespace OHOS {
30 namespace CryptoFramework {
31 thread_local napi_ref NapiCipher::classRef_ = nullptr;
32
33 struct CipherFwkCtxT {
34 napi_env env = nullptr;
35 AsyncType asyncType = ASYNC_CALLBACK;
36 napi_ref callback = nullptr;
37 napi_deferred deferred = nullptr;
38 napi_value promise = nullptr;
39 napi_async_work asyncWork = nullptr;
40
41 HcfCipher *cipher = nullptr;
42 HcfKey *key = nullptr;
43 HcfParamsSpec *paramsSpec = nullptr;
44 HcfBlob input = { .data = nullptr, .len = 0 };
45 HcfBlob output = { .data = nullptr, .len = 0 };
46 enum HcfCryptoMode opMode = ENCRYPT_MODE;
47
48 int32_t errCode = 0;
49 const char *errMsg = nullptr;
50 };
51
52 using CipherFwkCtx = CipherFwkCtxT *;
53
FreeParamsSpec(HcfParamsSpec * paramsSpec)54 static void FreeParamsSpec(HcfParamsSpec *paramsSpec)
55 {
56 if (paramsSpec == nullptr) {
57 return;
58 }
59 if (IV_PARAMS_SPEC.compare(paramsSpec->getType()) == 0) {
60 HcfIvParamsSpec *iv = reinterpret_cast<HcfIvParamsSpec *>(paramsSpec);
61 HcfFree(iv->iv.data);
62 iv->iv.data = nullptr;
63 iv->iv.len = 0;
64 }
65 if (GCM_PARAMS_SPEC.compare(paramsSpec->getType()) == 0) {
66 HcfGcmParamsSpec *gcm = reinterpret_cast<HcfGcmParamsSpec *>(paramsSpec);
67 HcfFree(gcm->iv.data);
68 HcfFree(gcm->aad.data);
69 HcfFree(gcm->tag.data);
70 gcm->iv.len = 0;
71 gcm->aad.len = 0;
72 gcm->tag.len = 0;
73 gcm->iv.data = nullptr;
74 gcm->aad.data = nullptr;
75 gcm->tag.data = nullptr;
76 }
77 if (CCM_PARAMS_SPEC.compare(paramsSpec->getType()) == 0) {
78 HcfCcmParamsSpec *ccm = reinterpret_cast<HcfCcmParamsSpec *>(paramsSpec);
79 HcfFree(ccm->iv.data);
80 HcfFree(ccm->aad.data);
81 HcfFree(ccm->tag.data);
82 ccm->iv.len = 0;
83 ccm->aad.len = 0;
84 ccm->tag.len = 0;
85 ccm->iv.data = nullptr;
86 ccm->aad.data = nullptr;
87 ccm->tag.data = nullptr;
88 }
89 HcfFree(paramsSpec);
90 }
91
FreeCipherFwkCtx(napi_env env,CipherFwkCtx & context)92 static void FreeCipherFwkCtx(napi_env env, CipherFwkCtx &context)
93 {
94 if (context == nullptr) {
95 return;
96 }
97
98 if (context->asyncWork != nullptr) {
99 napi_delete_async_work(env, context->asyncWork);
100 context->asyncWork = nullptr;
101 }
102
103 if (context->callback != nullptr) {
104 napi_delete_reference(env, context->callback);
105 context->callback = nullptr;
106 }
107 if (context->input.data != nullptr) {
108 HcfFree(context->input.data);
109 context->input.data = nullptr;
110 context->input.len = 0;
111 }
112 if (context->output.data != nullptr) {
113 HcfFree(context->output.data);
114 context->output.data = nullptr;
115 context->output.len = 0;
116 }
117 FreeParamsSpec(context->paramsSpec);
118 context->paramsSpec = nullptr;
119
120 context->cipher = nullptr;
121 context->key = nullptr;
122 context->errMsg = nullptr;
123 HcfFree(context);
124 context = nullptr;
125 }
126
BuildContextForInit(napi_env env,napi_callback_info info,CipherFwkCtx context)127 bool BuildContextForInit(napi_env env, napi_callback_info info, CipherFwkCtx context)
128 {
129 napi_value thisVar = nullptr;
130 NapiCipher *napiCipher = nullptr;
131 NapiKey *napiKey = nullptr;
132 size_t expectedArgc = ARGS_SIZE_FOUR;
133 size_t argc = ARGS_SIZE_FOUR;
134 napi_value argv[ARGS_SIZE_FOUR] = { nullptr };
135 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
136 if (argc != expectedArgc && argc != expectedArgc - 1) {
137 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "init failed for wrong argument num.", false));
138 LOGE("wrong argument num. require 3 or 4 arguments. [Argc]: %zu!", argc);
139 return false;
140 }
141 context->asyncType = (argc == expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
142
143 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiCipher));
144 if (status != napi_ok) {
145 LOGE("failed to unwrap napi napiCipher obj!");
146 return false;
147 }
148 context->cipher = napiCipher->GetCipher();
149
150 // get opMode, type is uint32
151 size_t index = ARGS_SIZE_ZERO;
152 if (napi_get_value_uint32(env, argv[index++], reinterpret_cast<uint32_t *>(&(context->opMode))) != napi_ok) {
153 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get opMode failed!", false));
154 LOGE("get opMode failed!");
155 return false;
156 }
157
158 // get key, unwrap from JS
159 status = napi_unwrap(env, argv[index++], reinterpret_cast<void **>(&napiKey));
160 if (status != napi_ok) {
161 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napi napiSymKey obj!", false));
162 LOGE("failed to unwrap napi napiSymKey obj!");
163 return false;
164 }
165 context->key = napiKey->GetHcfKey();
166
167 // get paramsSpec, unwrap from JS
168 napi_valuetype valueType;
169 napi_typeof(env, argv[index], &valueType);
170 if (valueType != napi_null) {
171 if (!GetParamsSpecFromNapiValue(env, argv[index], context->opMode, &context->paramsSpec)) {
172 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get valid params spec!", false));
173 LOGE("GetParamsSpecFromNapiValue failed!");
174 return false;
175 }
176 }
177 index++;
178
179 if (context->asyncType == ASYNC_PROMISE) {
180 napi_create_promise(env, &context->deferred, &context->promise);
181 return true;
182 } else {
183 return GetCallbackFromJSParams(env, argv[index], &context->callback, false);
184 }
185 }
186
BuildContextForUpdate(napi_env env,napi_callback_info info,CipherFwkCtx context)187 bool BuildContextForUpdate(napi_env env, napi_callback_info info, CipherFwkCtx context)
188 {
189 napi_value thisVar = nullptr;
190 NapiCipher *napiCipher = nullptr;
191 size_t expectedArgc = ARGS_SIZE_TWO;
192 size_t argc = ARGS_SIZE_TWO;
193 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
194 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
195 if (argc != expectedArgc && argc != expectedArgc - 1) {
196 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "update failed for wrong argument num.", false));
197 LOGE("wrong argument num. require 1 or 2 arguments. [Argc]: %zu!", argc);
198 return false;
199 }
200 context->asyncType = (argc == expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
201
202 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiCipher));
203 if (status != napi_ok) {
204 LOGE("failed to unwrap napi napiCipher obj!");
205 return false;
206 }
207 context->cipher = napiCipher->GetCipher();
208
209 // get input, type is blob
210 size_t index = ARGS_SIZE_ZERO;
211 HcfBlob *input = nullptr;
212 input = GetBlobFromNapiValue(env, argv[index++]);
213 if (input == nullptr) {
214 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "update failed for invalid input blob.", false));
215 LOGE("GetBlobFromNapiValue failed!");
216 return false;
217 }
218 context->input.data = input->data;
219 context->input.len = input->len;
220 HcfFree(input);
221 if (context->asyncType == ASYNC_PROMISE) {
222 napi_create_promise(env, &context->deferred, &context->promise);
223 return true;
224 } else {
225 return GetCallbackFromJSParams(env, argv[index], &context->callback, false);
226 }
227 }
228
BuildContextForFinal(napi_env env,napi_callback_info info,CipherFwkCtx context)229 bool BuildContextForFinal(napi_env env, napi_callback_info info, CipherFwkCtx context)
230 {
231 napi_value thisVar = nullptr;
232 NapiCipher *napiCipher = nullptr;
233 size_t expectedArgc = ARGS_SIZE_TWO;
234 size_t argc = ARGS_SIZE_TWO;
235 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
236 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
237 if (argc != expectedArgc && argc != expectedArgc - 1) {
238 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS,
239 "doFinal failed for invalid input blob.", false));
240 LOGE("wrong argument num. require 1 or 2 arguments. [Argc]: %zu!", argc);
241 return false;
242 }
243 context->asyncType = (argc == expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
244
245 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiCipher));
246 if (status != napi_ok) {
247 LOGE("failed to unwrap napi napiCipher obj!");
248 return false;
249 }
250 context->cipher = napiCipher->GetCipher();
251
252 // get input, type is blob
253 size_t index = ARGS_SIZE_ZERO;
254 napi_valuetype valueType;
255 napi_typeof(env, argv[index], &valueType);
256 if (valueType != napi_null) {
257 HcfBlob *input = nullptr;
258 input = GetBlobFromNapiValue(env, argv[index]);
259 if (input == nullptr) {
260 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS,
261 "doFinal failed for invalid input blob.", false));
262 LOGE("GetBlobFromNapiValue failed!");
263 return false;
264 }
265 context->input.data = input->data;
266 context->input.len = input->len;
267 HcfFree(input);
268 }
269 index++;
270 if (context->asyncType == ASYNC_PROMISE) {
271 napi_create_promise(env, &context->deferred, &context->promise);
272 return true;
273 } else {
274 return GetCallbackFromJSParams(env, argv[index], &context->callback, false);
275 }
276 }
277
ReturnCallbackResult(napi_env env,CipherFwkCtx context,napi_value result)278 static void ReturnCallbackResult(napi_env env, CipherFwkCtx context, napi_value result)
279 {
280 napi_value businessError = nullptr;
281 if (context->errCode != HCF_SUCCESS) {
282 businessError = GenerateBusinessError(env, context->errCode, context->errMsg, false);
283 }
284 napi_value params[ARGS_SIZE_TWO] = { businessError, result };
285
286 napi_value func = nullptr;
287 napi_get_reference_value(env, context->callback, &func);
288
289 napi_value recv = nullptr;
290 napi_value callFuncRet = nullptr;
291 napi_get_undefined(env, &recv);
292 napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
293 }
294
ReturnPromiseResult(napi_env env,CipherFwkCtx context,napi_value result)295 static void ReturnPromiseResult(napi_env env, CipherFwkCtx context, napi_value result)
296 {
297 if (context->errCode == HCF_SUCCESS) {
298 napi_resolve_deferred(env, context->deferred, result);
299 } else {
300 napi_reject_deferred(env, context->deferred,
301 GenerateBusinessError(env, context->errCode, context->errMsg, false));
302 }
303 }
304
305 // init execute
AsyncInitProcess(napi_env env,void * data)306 void AsyncInitProcess(napi_env env, void *data)
307 {
308 if (data == nullptr) {
309 return;
310 }
311 CipherFwkCtx context = static_cast<CipherFwkCtx>(data);
312 HcfCipher *cipher = context->cipher;
313 HcfParamsSpec *params = context->paramsSpec;
314 HcfKey *key = context->key;
315
316 HcfResult res = cipher->init(cipher, context->opMode, key, params);
317 if (res != HCF_SUCCESS) {
318 LOGE("init ret:%d", res);
319 context->errCode = res;
320 context->errMsg = "init failed.";
321 return;
322 }
323 context->errCode = HCF_SUCCESS;
324 }
325
326 // update execute
AsyncUpdateProcess(napi_env env,void * data)327 void AsyncUpdateProcess(napi_env env, void *data)
328 {
329 if (data == nullptr) {
330 return;
331 }
332 CipherFwkCtx context = static_cast<CipherFwkCtx>(data);
333 HcfCipher *cipher = context->cipher;
334 HcfResult res = cipher->update(cipher, &context->input, &context->output);
335 if (res != HCF_SUCCESS) {
336 LOGE("Update ret:%d!", res);
337 context->errCode = res;
338 context->errMsg = "update failed.";
339 return;
340 }
341 context->errCode = HCF_SUCCESS;
342 }
343
AsyncDoFinalProcess(napi_env env,void * data)344 void AsyncDoFinalProcess(napi_env env, void *data)
345 {
346 if (data == nullptr) {
347 return;
348 }
349 CipherFwkCtx context = static_cast<CipherFwkCtx>(data);
350 HcfCipher *cipher = context->cipher;
351
352 HcfResult res = cipher->doFinal(cipher, &context->input, &context->output);
353 if (res != HCF_SUCCESS) {
354 LOGE("doFinal ret:%d!", res);
355 context->errCode = res;
356 context->errMsg = "doFinal failed.";
357 return;
358 }
359 context->errCode = HCF_SUCCESS;
360 }
361
GetNapiNull(napi_env env)362 napi_value GetNapiNull(napi_env env)
363 {
364 napi_value output = nullptr;
365 napi_status status = napi_get_null(env, &output);
366 if (status != napi_ok) {
367 LOGE("create null napi value failed");
368 }
369 return output;
370 }
371
AsyncInitReturn(napi_env env,napi_status status,void * data)372 void AsyncInitReturn(napi_env env, napi_status status, void *data)
373 {
374 CipherFwkCtx context = static_cast<CipherFwkCtx>(data);
375 napi_value result = GetNapiNull(env);
376
377 if (context->asyncType == ASYNC_CALLBACK) {
378 ReturnCallbackResult(env, context, result);
379 } else {
380 ReturnPromiseResult(env, context, result);
381 }
382 FreeCipherFwkCtx(env, context);
383 }
384
AsyncUpdateReturn(napi_env env,napi_status status,void * data)385 void AsyncUpdateReturn(napi_env env, napi_status status, void *data)
386 {
387 CipherFwkCtx context = static_cast<CipherFwkCtx>(data);
388 napi_value instance = ConvertBlobToNapiValue(env, &context->output);
389 if (instance == nullptr) {
390 LOGE("May be nullptr!");
391 instance = GetNapiNull(env);
392 }
393
394 if (context->asyncType == ASYNC_CALLBACK) {
395 ReturnCallbackResult(env, context, instance);
396 } else {
397 ReturnPromiseResult(env, context, instance);
398 }
399 FreeCipherFwkCtx(env, context);
400 }
401
AsyncDoFinalReturn(napi_env env,napi_status status,void * data)402 void AsyncDoFinalReturn(napi_env env, napi_status status, void *data)
403 {
404 CipherFwkCtx context = static_cast<CipherFwkCtx>(data);
405 napi_value instance = ConvertBlobToNapiValue(env, &context->output);
406 if (instance == nullptr) {
407 LOGE("Maybe in decrypt mode, or CCM crypto maybe occur!");
408 instance = GetNapiNull(env);
409 }
410
411 if (context->asyncType == ASYNC_CALLBACK) {
412 ReturnCallbackResult(env, context, instance);
413 } else {
414 ReturnPromiseResult(env, context, instance);
415 }
416 FreeCipherFwkCtx(env, context);
417 }
418
NewAsyncInit(napi_env env,CipherFwkCtx context)419 napi_value NewAsyncInit(napi_env env, CipherFwkCtx context)
420 {
421 napi_value resourceName = nullptr;
422 napi_create_string_utf8(env, "init", NAPI_AUTO_LENGTH, &resourceName);
423
424 napi_create_async_work(
425 env, nullptr, resourceName,
426 [](napi_env env, void *data) {
427 AsyncInitProcess(env, data);
428 return;
429 },
430 [](napi_env env, napi_status status, void *data) {
431 AsyncInitReturn(env, status, data);
432 return;
433 },
434 static_cast<void *>(context),
435 &context->asyncWork);
436
437 napi_queue_async_work(env, context->asyncWork);
438 if (context->asyncType == ASYNC_PROMISE) {
439 return context->promise;
440 } else {
441 return NapiGetNull(env);
442 }
443 }
444
NewAsyncUpdate(napi_env env,CipherFwkCtx context)445 napi_value NewAsyncUpdate(napi_env env, CipherFwkCtx context)
446 {
447 napi_value resourceName = nullptr;
448 napi_create_string_utf8(env, "update", NAPI_AUTO_LENGTH, &resourceName);
449
450 napi_create_async_work(
451 env, nullptr, resourceName,
452 [](napi_env env, void *data) {
453 AsyncUpdateProcess(env, data);
454 return;
455 },
456 [](napi_env env, napi_status status, void *data) {
457 AsyncUpdateReturn(env, status, data);
458 return;
459 },
460 static_cast<void *>(context),
461 &context->asyncWork);
462
463 napi_queue_async_work(env, context->asyncWork);
464 if (context->asyncType == ASYNC_PROMISE) {
465 return context->promise;
466 } else {
467 return NapiGetNull(env);
468 }
469 }
470
NewAsyncDoFinal(napi_env env,CipherFwkCtx context)471 napi_value NewAsyncDoFinal(napi_env env, CipherFwkCtx context)
472 {
473 napi_value resourceName = nullptr;
474 napi_create_string_utf8(env, "doFinal", NAPI_AUTO_LENGTH, &resourceName);
475
476 napi_create_async_work(
477 env, nullptr, resourceName,
478 [](napi_env env, void *data) {
479 AsyncDoFinalProcess(env, data);
480 return;
481 },
482 [](napi_env env, napi_status status, void *data) {
483 AsyncDoFinalReturn(env, status, data);
484 return;
485 },
486 static_cast<void *>(context),
487 &context->asyncWork);
488
489 napi_queue_async_work(env, context->asyncWork);
490 if (context->asyncType == ASYNC_PROMISE) {
491 return context->promise;
492 } else {
493 return NapiGetNull(env);
494 }
495 }
496
NapiCipher(HcfCipher * cipher)497 NapiCipher::NapiCipher(HcfCipher *cipher)
498 {
499 this->cipher_ = cipher;
500 }
501
~NapiCipher()502 NapiCipher::~NapiCipher()
503 {
504 HcfObjDestroy(this->cipher_);
505 }
506
GetCipher() const507 HcfCipher *NapiCipher::GetCipher() const
508 {
509 return this->cipher_;
510 }
511
JsCipherInit(napi_env env,napi_callback_info info)512 napi_value NapiCipher::JsCipherInit(napi_env env, napi_callback_info info)
513 {
514 CipherFwkCtx context = static_cast<CipherFwkCtx>(HcfMalloc(sizeof(CipherFwkCtxT), 0));
515 if (context == nullptr) {
516 LOGE("create context fail!");
517 return nullptr;
518 }
519
520 if (!BuildContextForInit(env, info, context)) {
521 LOGE("build context for init fail!");
522 FreeCipherFwkCtx(env, context);
523 return nullptr;
524 }
525
526 return NewAsyncInit(env, context);
527 }
528
JsCipherUpdate(napi_env env,napi_callback_info info)529 napi_value NapiCipher::JsCipherUpdate(napi_env env, napi_callback_info info)
530 {
531 CipherFwkCtx context = static_cast<CipherFwkCtx>(HcfMalloc(sizeof(CipherFwkCtxT), 0));
532 if (context == nullptr) {
533 LOGE("create context fail!");
534 return nullptr;
535 }
536
537 if (!BuildContextForUpdate(env, info, context)) {
538 LOGE("build context for update fail!");
539 FreeCipherFwkCtx(env, context);
540 return nullptr;
541 }
542
543 return NewAsyncUpdate(env, context);
544 }
545
JsCipherDoFinal(napi_env env,napi_callback_info info)546 napi_value NapiCipher::JsCipherDoFinal(napi_env env, napi_callback_info info)
547 {
548 CipherFwkCtx context = static_cast<CipherFwkCtx>(HcfMalloc(sizeof(CipherFwkCtxT), 0));
549 if (context == nullptr) {
550 LOGE("create context fail!");
551 return nullptr;
552 }
553
554 if (!BuildContextForFinal(env, info, context)) {
555 LOGE("build context for final fail!");
556 FreeCipherFwkCtx(env, context);
557 return nullptr;
558 }
559 return NewAsyncDoFinal(env, context);
560 }
561
JsGetAlgorithm(napi_env env,napi_callback_info info)562 napi_value NapiCipher::JsGetAlgorithm(napi_env env, napi_callback_info info)
563 {
564 napi_value thisVar = nullptr;
565 NapiCipher *napiCipher = nullptr;
566
567 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
568
569 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiCipher));
570 if (status != napi_ok) {
571 LOGE("failed to unwrap napiCipher obj!");
572 return nullptr;
573 }
574
575 HcfCipher *cipher = napiCipher->GetCipher();
576 if (cipher == nullptr) {
577 LOGE("failed to get cipher obj!");
578 return nullptr;
579 }
580
581 // execute C function
582 const char *algo = cipher->getAlgorithm(cipher);
583 napi_value instance = nullptr;
584 napi_create_string_utf8(env, algo, NAPI_AUTO_LENGTH, &instance);
585 return instance;
586 }
587
CipherConstructor(napi_env env,napi_callback_info info)588 napi_value NapiCipher::CipherConstructor(napi_env env, napi_callback_info info)
589 {
590 napi_value thisVar = nullptr;
591 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
592
593 return thisVar;
594 }
595
CreateCipher(napi_env env,napi_callback_info info)596 napi_value NapiCipher::CreateCipher(napi_env env, napi_callback_info info)
597 {
598 size_t expectedArgc = ARGS_SIZE_ONE;
599 size_t argc = ARGS_SIZE_ONE;
600 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
601 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
602
603 if (argc != expectedArgc) {
604 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid.", false));
605 LOGE("The input args num is invalid.");
606 return nullptr;
607 }
608
609 // create instance according to input js object
610 napi_value instance = nullptr;
611 napi_value constructor = nullptr;
612 NAPI_CALL(env, napi_get_reference_value(env, classRef_, &constructor));
613 NAPI_CALL(env, napi_new_instance(env, constructor, argc, argv, &instance));
614
615 // parse input string
616 std::string algoName;
617 if (!GetStringFromJSParams(env, argv[ARGS_SIZE_ZERO], algoName, false)) {
618 LOGE("GetStringFromJSParams failed!");
619 return nullptr;
620 }
621
622 // execute C function, generate C object
623 HcfCipher *cipher = nullptr;
624 HcfResult res = HcfCipherCreate(algoName.c_str(), &cipher);
625 if (res != HCF_SUCCESS) {
626 napi_throw(env, GenerateBusinessError(env, res, "create C cipher fail!", false));
627 LOGE("create C cipher fail!");
628 return nullptr;
629 }
630 NapiCipher *napiCipher = new (std::nothrow) NapiCipher(cipher);
631 if (napiCipher == nullptr) {
632 LOGE("new napiCipher failed!");
633 HcfObjDestroy(cipher);
634 return nullptr;
635 }
636
637 napi_status status = napi_wrap(env, instance, napiCipher,
638 [](napi_env env, void *data, void *hint) {
639 NapiCipher *napiCipher = static_cast<NapiCipher *>(data);
640 delete napiCipher;
641 return;
642 },
643 nullptr,
644 nullptr);
645 if (status != napi_ok) {
646 LOGE("failed to wrap napiCipher obj!");
647 delete napiCipher;
648 return nullptr;
649 }
650 return instance;
651 }
652
DefineCipherJSClass(napi_env env,napi_value exports)653 void NapiCipher::DefineCipherJSClass(napi_env env, napi_value exports)
654 {
655 napi_property_descriptor desc[] = {
656 DECLARE_NAPI_FUNCTION("createCipher", CreateCipher),
657 };
658 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
659
660 napi_property_descriptor classDesc[] = {
661 DECLARE_NAPI_FUNCTION("init", NapiCipher::JsCipherInit),
662 DECLARE_NAPI_FUNCTION("update", NapiCipher::JsCipherUpdate),
663 DECLARE_NAPI_FUNCTION("doFinal", NapiCipher::JsCipherDoFinal),
664 { .utf8name = "algName", .getter = NapiCipher::JsGetAlgorithm },
665 };
666 napi_value constructor = nullptr;
667 napi_define_class(env, "Cipher", NAPI_AUTO_LENGTH, NapiCipher::CipherConstructor, nullptr,
668 sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
669 napi_create_reference(env, constructor, 1, &classRef_);
670 }
671 } // CryptoFramework
672 } // OHOS