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 "napi_sign.h"
17
18 #include "securec.h"
19 #include "log.h"
20 #include "memory.h"
21
22 #include "napi_crypto_framework_defines.h"
23 #include "napi_pri_key.h"
24 #include "napi_pub_key.h"
25 #include "napi_utils.h"
26
27 namespace OHOS {
28 namespace CryptoFramework {
29 struct SignInitCtx {
30 napi_env env = nullptr;
31
32 AsyncType asyncType = ASYNC_CALLBACK;
33 napi_ref callback = nullptr;
34 napi_deferred deferred = nullptr;
35 napi_value promise = nullptr;
36 napi_async_work asyncWork = nullptr;
37
38 HcfSign *sign = nullptr;
39 HcfParamsSpec *params = nullptr;
40 HcfPriKey *priKey = nullptr;
41
42 HcfResult errCode = HCF_SUCCESS;
43 const char *errMsg = nullptr;
44 };
45
46 struct SignUpdateCtx {
47 napi_env env = nullptr;
48
49 AsyncType asyncType = ASYNC_CALLBACK;
50 napi_ref callback = nullptr;
51 napi_deferred deferred = nullptr;
52 napi_value promise = nullptr;
53 napi_async_work asyncWork = nullptr;
54
55 HcfSign *sign;
56 HcfBlob *data;
57
58 HcfResult errCode = HCF_SUCCESS;
59 const char *errMsg = nullptr;
60 };
61
62 struct SignDoFinalCtx {
63 napi_env env = nullptr;
64
65 AsyncType asyncType = ASYNC_CALLBACK;
66 napi_ref callback = nullptr;
67 napi_deferred deferred = nullptr;
68 napi_value promise = nullptr;
69 napi_async_work asyncWork = nullptr;
70
71 HcfSign *sign;
72 HcfBlob *data;
73
74 HcfResult errCode = HCF_SUCCESS;
75 const char *errMsg = nullptr;
76 HcfBlob returnSignatureData;
77 };
78
79 thread_local napi_ref NapiSign::classRef_ = nullptr;
80
FreeSignInitCtx(napi_env env,SignInitCtx * ctx)81 static void FreeSignInitCtx(napi_env env, SignInitCtx *ctx)
82 {
83 if (ctx == nullptr) {
84 return;
85 }
86
87 if (ctx->asyncWork != nullptr) {
88 napi_delete_async_work(env, ctx->asyncWork);
89 }
90
91 if (ctx->callback != nullptr) {
92 napi_delete_reference(env, ctx->callback);
93 }
94
95 HcfFree(ctx);
96 }
97
FreeSignUpdateCtx(napi_env env,SignUpdateCtx * ctx)98 static void FreeSignUpdateCtx(napi_env env, SignUpdateCtx *ctx)
99 {
100 if (ctx == nullptr) {
101 return;
102 }
103
104 if (ctx->asyncWork != nullptr) {
105 napi_delete_async_work(env, ctx->asyncWork);
106 }
107
108 if (ctx->callback != nullptr) {
109 napi_delete_reference(env, ctx->callback);
110 }
111
112 HcfBlobDataFree(ctx->data);
113 HcfFree(ctx->data);
114 HcfFree(ctx);
115 }
116
FreeSignDoFinalCtx(napi_env env,SignDoFinalCtx * ctx)117 static void FreeSignDoFinalCtx(napi_env env, SignDoFinalCtx *ctx)
118 {
119 if (ctx == nullptr) {
120 return;
121 }
122
123 if (ctx->asyncWork != nullptr) {
124 napi_delete_async_work(env, ctx->asyncWork);
125 ctx->asyncWork = nullptr;
126 }
127
128 if (ctx->callback != nullptr) {
129 napi_delete_reference(env, ctx->callback);
130 ctx->callback = nullptr;
131 }
132
133 if (ctx->returnSignatureData.data != nullptr) {
134 HcfFree(ctx->returnSignatureData.data);
135 ctx->returnSignatureData.data = nullptr;
136 ctx->returnSignatureData.len = 0;
137 }
138
139 HcfBlobDataFree(ctx->data);
140 HcfFree(ctx->data);
141 HcfFree(ctx);
142 }
143
BuildSignJsInitCtx(napi_env env,napi_callback_info info,SignInitCtx * ctx)144 static bool BuildSignJsInitCtx(napi_env env, napi_callback_info info, SignInitCtx *ctx)
145 {
146 napi_value thisVar = nullptr;
147 size_t expectedArgc = PARAMS_NUM_TWO;
148 size_t argc = expectedArgc;
149 napi_value argv[PARAMS_NUM_TWO] = { nullptr, nullptr };
150 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
151 if (argc != expectedArgc && argc != expectedArgc - 1) {
152 LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
153 return false;
154 }
155 ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
156
157 NapiSign *napiSign = nullptr;
158 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
159 if (status != napi_ok || napiSign == nullptr) {
160 LOGE("failed to unwrap napi sign obj.");
161 return false;
162 }
163
164 size_t index = 0;
165 NapiPriKey *napiPriKey = nullptr;
166 status = napi_unwrap(env, argv[index], reinterpret_cast<void **>(&napiPriKey));
167 if (status != napi_ok || napiPriKey == nullptr) {
168 LOGE("failed to unwrap napi priKey obj.");
169 return false;
170 }
171
172 ctx->sign = napiSign->GetSign();
173 ctx->params = nullptr;
174 ctx->priKey = napiPriKey->GetPriKey();
175
176 if (ctx->asyncType == ASYNC_PROMISE) {
177 napi_create_promise(env, &ctx->deferred, &ctx->promise);
178 return true;
179 } else {
180 return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
181 }
182 }
183
BuildSignJsUpdateCtx(napi_env env,napi_callback_info info,SignUpdateCtx * ctx)184 static bool BuildSignJsUpdateCtx(napi_env env, napi_callback_info info, SignUpdateCtx *ctx)
185 {
186 napi_value thisVar = nullptr;
187 size_t expectedArgc = PARAMS_NUM_TWO;
188 size_t argc = expectedArgc;
189 napi_value argv[PARAMS_NUM_TWO] = { nullptr, nullptr };
190 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
191 if ((argc != expectedArgc) && (argc != expectedArgc - 1)) {
192 LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
193 return false;
194 }
195 ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
196
197 NapiSign *napiSign = nullptr;
198 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
199 if (status != napi_ok || napiSign == nullptr) {
200 LOGE("failed to unwrap napi sign obj.");
201 return false;
202 }
203
204 size_t index = 0;
205 HcfBlob *blob = GetBlobFromNapiDataBlob(env, argv[index]);
206 if (blob == nullptr) {
207 LOGE("failed to get data.");
208 return false;
209 }
210
211 ctx->sign = napiSign->GetSign();
212 ctx->data = blob;
213
214 if (ctx->asyncType == ASYNC_PROMISE) {
215 napi_create_promise(env, &ctx->deferred, &ctx->promise);
216 return true;
217 } else {
218 return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
219 }
220 }
221
BuildSignJsDoFinalCtx(napi_env env,napi_callback_info info,SignDoFinalCtx * ctx)222 static bool BuildSignJsDoFinalCtx(napi_env env, napi_callback_info info, SignDoFinalCtx *ctx)
223 {
224 napi_value thisVar = nullptr;
225 size_t expectedArgc = PARAMS_NUM_TWO;
226 size_t argc = expectedArgc;
227 napi_value argv[PARAMS_NUM_TWO] = { nullptr, nullptr };
228 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
229 if ((argc != expectedArgc) && (argc != expectedArgc - 1)) {
230 LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
231 return false;
232 }
233 ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
234
235 NapiSign *napiSign = nullptr;
236 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
237 if (status != napi_ok || napiSign == nullptr) {
238 LOGE("failed to unwrap napi sign obj.");
239 return false;
240 }
241
242 size_t index = 0;
243 napi_valuetype valueType;
244 napi_typeof(env, argv[index], &valueType);
245 HcfBlob *data = nullptr;
246 if (valueType != napi_null) {
247 data = GetBlobFromNapiDataBlob(env, argv[index]);
248 if (data == nullptr) {
249 LOGE("failed to get data.");
250 return false;
251 }
252 }
253
254 ctx->sign = napiSign->GetSign();
255 ctx->data = data;
256
257 if (ctx->asyncType == ASYNC_PROMISE) {
258 napi_create_promise(env, &ctx->deferred, &ctx->promise);
259 return true;
260 } else {
261 return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
262 }
263 }
264
ReturnInitCallbackResult(napi_env env,SignInitCtx * ctx,napi_value result)265 static void ReturnInitCallbackResult(napi_env env, SignInitCtx *ctx, napi_value result)
266 {
267 napi_value businessError = nullptr;
268 if (ctx->errCode != HCF_SUCCESS) {
269 businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
270 }
271
272 napi_value params[ARGS_SIZE_ONE] = { businessError };
273
274 napi_value func = nullptr;
275 napi_get_reference_value(env, ctx->callback, &func);
276
277 napi_value recv = nullptr;
278 napi_value callFuncRet = nullptr;
279 napi_get_undefined(env, &recv);
280 napi_call_function(env, recv, func, ARGS_SIZE_ONE, params, &callFuncRet);
281 }
282
ReturnInitPromiseResult(napi_env env,SignInitCtx * ctx,napi_value result)283 static void ReturnInitPromiseResult(napi_env env, SignInitCtx *ctx, napi_value result)
284 {
285 if (ctx->errCode == HCF_SUCCESS) {
286 napi_resolve_deferred(env, ctx->deferred, result);
287 } else {
288 napi_reject_deferred(env, ctx->deferred, GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
289 }
290 }
291
ReturnUpdateCallbackResult(napi_env env,SignUpdateCtx * ctx,napi_value result)292 static void ReturnUpdateCallbackResult(napi_env env, SignUpdateCtx *ctx, napi_value result)
293 {
294 napi_value businessError = nullptr;
295 if (ctx->errCode != HCF_SUCCESS) {
296 businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
297 }
298
299 napi_value params[ARGS_SIZE_ONE] = { businessError };
300
301 napi_value func = nullptr;
302 napi_get_reference_value(env, ctx->callback, &func);
303
304 napi_value recv = nullptr;
305 napi_value callFuncRet = nullptr;
306 napi_get_undefined(env, &recv);
307 napi_call_function(env, recv, func, ARGS_SIZE_ONE, params, &callFuncRet);
308 }
309
ReturnUpdatePromiseResult(napi_env env,SignUpdateCtx * ctx,napi_value result)310 static void ReturnUpdatePromiseResult(napi_env env, SignUpdateCtx *ctx, napi_value result)
311 {
312 if (ctx->errCode == HCF_SUCCESS) {
313 napi_resolve_deferred(env, ctx->deferred, result);
314 } else {
315 napi_reject_deferred(env, ctx->deferred, GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
316 }
317 }
318
ReturnDoFinalCallbackResult(napi_env env,SignDoFinalCtx * ctx,napi_value result)319 static void ReturnDoFinalCallbackResult(napi_env env, SignDoFinalCtx *ctx, napi_value result)
320 {
321 napi_value businessError = nullptr;
322 if (ctx->errCode != HCF_SUCCESS) {
323 businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
324 }
325
326 napi_value params[ARGS_SIZE_TWO] = { businessError, result };
327
328 napi_value func = nullptr;
329 napi_get_reference_value(env, ctx->callback, &func);
330
331 napi_value recv = nullptr;
332 napi_value callFuncRet = nullptr;
333 napi_get_undefined(env, &recv);
334 napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
335 }
336
ReturnDoFinalPromiseResult(napi_env env,SignDoFinalCtx * ctx,napi_value result)337 static void ReturnDoFinalPromiseResult(napi_env env, SignDoFinalCtx *ctx, napi_value result)
338 {
339 if (ctx->errCode == HCF_SUCCESS) {
340 napi_resolve_deferred(env, ctx->deferred, result);
341 } else {
342 napi_reject_deferred(env, ctx->deferred, GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
343 }
344 }
345
SignJsInitAsyncWorkProcess(napi_env env,void * data)346 static void SignJsInitAsyncWorkProcess(napi_env env, void *data)
347 {
348 SignInitCtx *ctx = static_cast<SignInitCtx *>(data);
349
350 ctx->errCode = ctx->sign->init(ctx->sign, ctx->params, ctx->priKey);
351 if (ctx->errCode != HCF_SUCCESS) {
352 LOGD("[error] sign init fail.");
353 ctx->errMsg = "sign init fail.";
354 }
355 }
356
SignJsInitAsyncWorkReturn(napi_env env,napi_status status,void * data)357 static void SignJsInitAsyncWorkReturn(napi_env env, napi_status status, void *data)
358 {
359 SignInitCtx *ctx = static_cast<SignInitCtx *>(data);
360
361 if (ctx->asyncType == ASYNC_CALLBACK) {
362 ReturnInitCallbackResult(env, ctx, NapiGetNull(env));
363 } else {
364 ReturnInitPromiseResult(env, ctx, NapiGetNull(env));
365 }
366 FreeSignInitCtx(env, ctx);
367 }
368
SignJsUpdateAsyncWorkProcess(napi_env env,void * data)369 static void SignJsUpdateAsyncWorkProcess(napi_env env, void *data)
370 {
371 SignUpdateCtx *ctx = static_cast<SignUpdateCtx *>(data);
372
373 ctx->errCode = ctx->sign->update(ctx->sign, ctx->data);
374 if (ctx->errCode != HCF_SUCCESS) {
375 LOGD("[error] sign update fail.");
376 ctx->errMsg = "sign update fail.";
377 }
378 }
379
SignJsUpdateAsyncWorkReturn(napi_env env,napi_status status,void * data)380 static void SignJsUpdateAsyncWorkReturn(napi_env env, napi_status status, void *data)
381 {
382 SignUpdateCtx *ctx = static_cast<SignUpdateCtx *>(data);
383
384 if (ctx->asyncType == ASYNC_CALLBACK) {
385 ReturnUpdateCallbackResult(env, ctx, NapiGetNull(env));
386 } else {
387 ReturnUpdatePromiseResult(env, ctx, NapiGetNull(env));
388 }
389 FreeSignUpdateCtx(env, ctx);
390 }
391
SignJsDoFinalAsyncWorkProcess(napi_env env,void * data)392 static void SignJsDoFinalAsyncWorkProcess(napi_env env, void *data)
393 {
394 SignDoFinalCtx *ctx = static_cast<SignDoFinalCtx *>(data);
395
396 ctx->errCode = ctx->sign->sign(ctx->sign, ctx->data, &ctx->returnSignatureData);
397 if (ctx->errCode != HCF_SUCCESS) {
398 LOGD("[error] sign doFinal fail.");
399 ctx->errMsg = "sign doFinal fail.";
400 }
401 }
402
SignJsDoFinalAsyncWorkReturn(napi_env env,napi_status status,void * data)403 static void SignJsDoFinalAsyncWorkReturn(napi_env env, napi_status status, void *data)
404 {
405 SignDoFinalCtx *ctx = static_cast<SignDoFinalCtx *>(data);
406
407 napi_value dataBlob = nullptr;
408 if (ctx->errCode == HCF_SUCCESS) {
409 dataBlob = ConvertBlobToNapiValue(env, &ctx->returnSignatureData);
410 }
411
412 if (ctx->asyncType == ASYNC_CALLBACK) {
413 ReturnDoFinalCallbackResult(env, ctx, dataBlob);
414 } else {
415 ReturnDoFinalPromiseResult(env, ctx, dataBlob);
416 }
417 FreeSignDoFinalCtx(env, ctx);
418 }
419
NewSignJsInitAsyncWork(napi_env env,SignInitCtx * ctx)420 static napi_value NewSignJsInitAsyncWork(napi_env env, SignInitCtx *ctx)
421 {
422 napi_value resourceName = nullptr;
423 napi_create_string_utf8(env, "init", NAPI_AUTO_LENGTH, &resourceName);
424
425 napi_create_async_work(
426 env, nullptr, resourceName,
427 [](napi_env env, void *data) {
428 SignJsInitAsyncWorkProcess(env, data);
429 return;
430 },
431 [](napi_env env, napi_status status, void *data) {
432 SignJsInitAsyncWorkReturn(env, status, data);
433 return;
434 },
435 static_cast<void *>(ctx),
436 &ctx->asyncWork);
437
438 napi_queue_async_work(env, ctx->asyncWork);
439 if (ctx->asyncType == ASYNC_PROMISE) {
440 return ctx->promise;
441 } else {
442 return NapiGetNull(env);
443 }
444 }
445
NewSignJsUpdateAsyncWork(napi_env env,SignUpdateCtx * ctx)446 static napi_value NewSignJsUpdateAsyncWork(napi_env env, SignUpdateCtx *ctx)
447 {
448 napi_value resourceName = nullptr;
449 napi_create_string_utf8(env, "update", NAPI_AUTO_LENGTH, &resourceName);
450
451 napi_create_async_work(
452 env, nullptr, resourceName,
453 [](napi_env env, void *data) {
454 SignJsUpdateAsyncWorkProcess(env, data);
455 return;
456 },
457 [](napi_env env, napi_status status, void *data) {
458 SignJsUpdateAsyncWorkReturn(env, status, data);
459 return;
460 },
461 static_cast<void *>(ctx),
462 &ctx->asyncWork);
463
464 napi_queue_async_work(env, ctx->asyncWork);
465 if (ctx->asyncType == ASYNC_PROMISE) {
466 return ctx->promise;
467 } else {
468 return NapiGetNull(env);
469 }
470 }
471
NewSignJsDoFinalAsyncWork(napi_env env,SignDoFinalCtx * ctx)472 static napi_value NewSignJsDoFinalAsyncWork(napi_env env, SignDoFinalCtx *ctx)
473 {
474 napi_value resourceName = nullptr;
475 napi_create_string_utf8(env, "sign", NAPI_AUTO_LENGTH, &resourceName);
476
477 napi_create_async_work(
478 env, nullptr, resourceName,
479 [](napi_env env, void *data) {
480 SignJsDoFinalAsyncWorkProcess(env, data);
481 return;
482 },
483 [](napi_env env, napi_status status, void *data) {
484 SignJsDoFinalAsyncWorkReturn(env, status, data);
485 return;
486 },
487 static_cast<void *>(ctx),
488 &ctx->asyncWork);
489
490 napi_queue_async_work(env, ctx->asyncWork);
491 if (ctx->asyncType == ASYNC_PROMISE) {
492 return ctx->promise;
493 } else {
494 return NapiGetNull(env);
495 }
496 }
497
NapiSign(HcfSign * sign)498 NapiSign::NapiSign(HcfSign *sign)
499 {
500 this->sign_ = sign;
501 }
502
~NapiSign()503 NapiSign::~NapiSign()
504 {
505 HcfObjDestroy(this->sign_);
506 }
507
GetSign()508 HcfSign *NapiSign::GetSign()
509 {
510 return this->sign_;
511 }
512
JsInit(napi_env env,napi_callback_info info)513 napi_value NapiSign::JsInit(napi_env env, napi_callback_info info)
514 {
515 SignInitCtx *ctx = static_cast<SignInitCtx *>(HcfMalloc(sizeof(SignInitCtx), 0));
516 if (ctx == nullptr) {
517 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
518 LOGE("create context fail.");
519 return nullptr;
520 }
521
522 if (!BuildSignJsInitCtx(env, info, ctx)) {
523 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
524 LOGE("build context fail.");
525 FreeSignInitCtx(env, ctx);
526 return nullptr;
527 }
528
529 return NewSignJsInitAsyncWork(env, ctx);
530 }
531
JsUpdate(napi_env env,napi_callback_info info)532 napi_value NapiSign::JsUpdate(napi_env env, napi_callback_info info)
533 {
534 SignUpdateCtx *ctx = static_cast<SignUpdateCtx *>(HcfMalloc(sizeof(SignUpdateCtx), 0));
535 if (ctx == nullptr) {
536 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
537 LOGE("create context fail.");
538 return nullptr;
539 }
540
541 if (!BuildSignJsUpdateCtx(env, info, ctx)) {
542 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
543 LOGE("build context fail.");
544 FreeSignUpdateCtx(env, ctx);
545 return nullptr;
546 }
547
548 return NewSignJsUpdateAsyncWork(env, ctx);
549 }
550
JsSign(napi_env env,napi_callback_info info)551 napi_value NapiSign::JsSign(napi_env env, napi_callback_info info)
552 {
553 SignDoFinalCtx *ctx = static_cast<SignDoFinalCtx *>(HcfMalloc(sizeof(SignDoFinalCtx), 0));
554 if (ctx == nullptr) {
555 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
556 LOGE("create context fail.");
557 return nullptr;
558 }
559
560 if (!BuildSignJsDoFinalCtx(env, info, ctx)) {
561 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
562 LOGE("build context fail.");
563 FreeSignDoFinalCtx(env, ctx);
564 return nullptr;
565 }
566
567 return NewSignJsDoFinalAsyncWork(env, ctx);
568 }
569
SignConstructor(napi_env env,napi_callback_info info)570 napi_value NapiSign::SignConstructor(napi_env env, napi_callback_info info)
571 {
572 napi_value thisVar = nullptr;
573 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
574 return thisVar;
575 }
576
NapiWrapSign(napi_env env,napi_value instance,NapiSign * napiSign)577 static napi_value NapiWrapSign(napi_env env, napi_value instance, NapiSign *napiSign)
578 {
579 napi_status status = napi_wrap(
580 env, instance, napiSign,
581 [](napi_env env, void *data, void *hint) {
582 NapiSign *napiSign = static_cast<NapiSign *>(data);
583 delete napiSign;
584 return;
585 }, nullptr, nullptr);
586 if (status != napi_ok) {
587 LOGE("failed to wrap napiSign obj!");
588 delete napiSign;
589 napiSign = nullptr;
590 return nullptr;
591 }
592 return instance;
593 }
594
CreateJsSign(napi_env env,napi_callback_info info)595 napi_value NapiSign::CreateJsSign(napi_env env, napi_callback_info info)
596 {
597 LOGD("Enter CreateJsSign...");
598 size_t expectedArgc = PARAMS_NUM_ONE;
599 size_t argc = expectedArgc;
600 napi_value argv[PARAMS_NUM_ONE] = { nullptr };
601 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."));
605 LOGE("The input args num is invalid.");
606 return nullptr;
607 }
608
609 napi_value instance;
610 napi_value constructor = nullptr;
611 napi_get_reference_value(env, classRef_, &constructor);
612 napi_new_instance(env, constructor, argc, argv, &instance);
613
614 std::string algName;
615 if (!GetStringFromJSParams(env, argv[0], algName)) {
616 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get algName fail."));
617 return nullptr;
618 }
619
620 HcfSign *sign = nullptr;
621 HcfResult ret = HcfSignCreate(algName.c_str(), &sign);
622 if (ret != HCF_SUCCESS) {
623 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "create c sign fail."));
624 LOGE("create c sign fail.");
625 return nullptr;
626 }
627
628 NapiSign *napiSign = new (std::nothrow) NapiSign(sign);
629 if (napiSign == nullptr) {
630 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi sign failed"));
631 LOGE("new napi sign failed");
632 HcfObjDestroy(sign);
633 return nullptr;
634 }
635
636 napi_value napiAlgName = nullptr;
637 napi_create_string_utf8(env, algName.c_str(), NAPI_AUTO_LENGTH, &napiAlgName);
638 napi_set_named_property(env, instance, CRYPTO_TAG_ALG_NAME.c_str(), napiAlgName);
639
640 return NapiWrapSign(env, instance, napiSign);
641 }
642
SetSignUserIdUintArray(napi_env env,napi_value * argv,HcfSign * sign)643 static HcfResult SetSignUserIdUintArray(napi_env env, napi_value *argv, HcfSign *sign)
644 {
645 HcfBlob *blob = nullptr;
646 blob = GetBlobFromNapiUint8Arr(env, argv[1]);
647 if (blob == nullptr) {
648 LOGE("failed to get blob.");
649 return HCF_INVALID_PARAMS;
650 }
651 HcfResult ret = sign->setSignSpecUint8Array(sign, SM2_USER_ID_UINT8ARR, *blob);
652 if (ret != HCF_SUCCESS) {
653 HcfBlobDataFree(blob);
654 HcfFree(blob);
655 LOGE("c setSignSpecUint8Array failed.");
656 return HCF_INVALID_PARAMS;
657 }
658 HcfBlobDataFree(blob);
659 HcfFree(blob);
660 return ret;
661 }
662
SetSignSaltLenInt(napi_env env,napi_value * argv,HcfSign * sign)663 static HcfResult SetSignSaltLenInt(napi_env env, napi_value *argv, HcfSign *sign)
664 {
665 int32_t saltLen = 0;
666 if (napi_get_value_int32(env, argv[1], &saltLen) != napi_ok) {
667 LOGE("get signSpec saltLen failed!");
668 return HCF_INVALID_PARAMS;
669 }
670 HcfResult ret = HCF_SUCCESS;
671 ret = sign->setSignSpecInt(sign, PSS_SALT_LEN_INT, saltLen);
672 if (ret != HCF_SUCCESS) {
673 LOGE("c setSignSpecNumber fail.");
674 return HCF_INVALID_PARAMS;
675 }
676 return ret;
677 }
678
SetDetailSignSpec(napi_env env,napi_value * argv,SignSpecItem item,HcfSign * sign)679 static HcfResult SetDetailSignSpec(napi_env env, napi_value *argv, SignSpecItem item, HcfSign *sign)
680 {
681 HcfResult result = HCF_INVALID_PARAMS;
682
683 switch (item) {
684 case SM2_USER_ID_UINT8ARR:
685 result = SetSignUserIdUintArray(env, argv, sign);
686 break;
687 case PSS_SALT_LEN_INT:
688 result = SetSignSaltLenInt(env, argv, sign);
689 break;
690 default:
691 LOGE("specItem not support.");
692 break;
693 }
694 return result;
695 }
696
697 // sign setSignSpec(itemType :signSpecItem, itemValue : number|string)
JsSetSignSpec(napi_env env,napi_callback_info info)698 napi_value NapiSign::JsSetSignSpec(napi_env env, napi_callback_info info)
699 {
700 napi_value thisVar = nullptr;
701 NapiSign *napiSign = nullptr;
702 size_t expectedArgc = ARGS_SIZE_TWO;
703 size_t argc = ARGS_SIZE_TWO;
704 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
705 // thisVar means the js this argument for the call (sign.() means this = sign)
706 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
707 if (argc != expectedArgc) {
708 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "init failed for wrong argument num."));
709 LOGE("wrong argument num. require 2 arguments. [Argc]: %zu!", argc);
710 return nullptr;
711 }
712 SignSpecItem item;
713 if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
714 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get signSpecItem failed!"));
715 LOGE("get signspecitem failed!");
716 return nullptr;
717 }
718 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
719 if (status != napi_ok || napiSign == nullptr) {
720 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiSign obj!"));
721 LOGE("failed to unwrap napiSign obj!");
722 return nullptr;
723 }
724 HcfSign *sign = napiSign->GetSign();
725 if (SetDetailSignSpec(env, argv, item, sign) != HCF_SUCCESS) {
726 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to set sign spec!"));
727 LOGE("failed to set sign spec!");
728 return nullptr;
729 }
730 return thisVar;
731 }
732
GetSignSpecString(napi_env env,SignSpecItem item,HcfSign * sign)733 static napi_value GetSignSpecString(napi_env env, SignSpecItem item, HcfSign *sign)
734 {
735 char *returnString = nullptr;
736 HcfResult ret = sign->getSignSpecString(sign, item, &returnString);
737 if (ret != HCF_SUCCESS) {
738 napi_throw(env, GenerateBusinessError(env, ret, "C getSignSpecString failed."));
739 LOGE("c getSignSpecString fail.");
740 return nullptr;
741 }
742
743 napi_value instance = nullptr;
744 napi_create_string_utf8(env, returnString, NAPI_AUTO_LENGTH, &instance);
745 HcfFree(returnString);
746 return instance;
747 }
748
GetSignSpecNumber(napi_env env,SignSpecItem item,HcfSign * sign)749 static napi_value GetSignSpecNumber(napi_env env, SignSpecItem item, HcfSign *sign)
750 {
751 int returnInt;
752 HcfResult ret = sign->getSignSpecInt(sign, item, &returnInt);
753 if (ret != HCF_SUCCESS) {
754 napi_throw(env, GenerateBusinessError(env, ret, "C getSignSpecInt failed."));
755 LOGE("c getSignSpecInt fail.");
756 return nullptr;
757 }
758
759 napi_value instance = nullptr;
760 napi_create_int32(env, returnInt, &instance);
761 return instance;
762 }
763
JsGetSignSpec(napi_env env,napi_callback_info info)764 napi_value NapiSign::JsGetSignSpec(napi_env env, napi_callback_info info)
765 {
766 napi_value thisVar = nullptr;
767 NapiSign *napiSign = nullptr;
768 size_t expectedArgc = ARGS_SIZE_ONE;
769 size_t argc = ARGS_SIZE_ONE;
770 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
771 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
772 if (argc != expectedArgc) {
773 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "init failed for wrong argument num."));
774 LOGE("wrong argument num. require 1 arguments. [Argc]: %zu!", argc);
775 return nullptr;
776 }
777 SignSpecItem item;
778 if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
779 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get signSpecItem failed!"));
780 LOGE("get signSpecItem failed!");
781 return nullptr;
782 }
783
784 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
785 if (status != napi_ok || napiSign == nullptr) {
786 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiSign obj!"));
787 LOGE("failed to unwrap napiSign obj!");
788 return nullptr;
789 }
790 HcfSign *sign = napiSign->GetSign();
791 if (sign == nullptr) {
792 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get sign obj!"));
793 LOGE("failed to get sign obj!");
794 return nullptr;
795 }
796
797 int32_t type = GetSignSpecType(item);
798 if (type == SPEC_ITEM_TYPE_STR) {
799 return GetSignSpecString(env, item, sign);
800 } else if (type == SPEC_ITEM_TYPE_NUM) {
801 return GetSignSpecNumber(env, item, sign);
802 } else {
803 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "signSpecItem not support!"));
804 return nullptr;
805 }
806 }
807
DefineSignJSClass(napi_env env,napi_value exports)808 void NapiSign::DefineSignJSClass(napi_env env, napi_value exports)
809 {
810 napi_property_descriptor desc[] = {
811 DECLARE_NAPI_FUNCTION("createSign", NapiSign::CreateJsSign),
812 };
813 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
814
815 napi_property_descriptor classDesc[] = {
816 DECLARE_NAPI_FUNCTION("init", NapiSign::JsInit),
817 DECLARE_NAPI_FUNCTION("update", NapiSign::JsUpdate),
818 DECLARE_NAPI_FUNCTION("sign", NapiSign::JsSign),
819 DECLARE_NAPI_FUNCTION("setSignSpec", NapiSign::JsSetSignSpec),
820 DECLARE_NAPI_FUNCTION("getSignSpec", NapiSign::JsGetSignSpec),
821 };
822 napi_value constructor = nullptr;
823 napi_define_class(env, "Sign", NAPI_AUTO_LENGTH, NapiSign::SignConstructor, nullptr,
824 sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
825 napi_create_reference(env, constructor, 1, &classRef_);
826 }
827 } // CryptoFramework
828 } // OHOS
829