1 /*
2 * Copyright (C) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "napi_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 napi_ref signRef = nullptr;
38 napi_ref priKeyRef = nullptr;
39
40 HcfSign *sign = nullptr;
41 HcfParamsSpec *params = nullptr;
42 HcfPriKey *priKey = nullptr;
43
44 HcfResult errCode = HCF_SUCCESS;
45 const char *errMsg = nullptr;
46 };
47
48 struct SignUpdateCtx {
49 napi_env env = nullptr;
50
51 AsyncType asyncType = ASYNC_CALLBACK;
52 napi_ref callback = nullptr;
53 napi_deferred deferred = nullptr;
54 napi_value promise = nullptr;
55 napi_async_work asyncWork = nullptr;
56 napi_ref signRef = nullptr;
57
58 HcfSign *sign;
59 HcfBlob *data;
60
61 HcfResult errCode = HCF_SUCCESS;
62 const char *errMsg = nullptr;
63 };
64
65 struct SignDoFinalCtx {
66 napi_env env = nullptr;
67
68 AsyncType asyncType = ASYNC_CALLBACK;
69 napi_ref callback = nullptr;
70 napi_deferred deferred = nullptr;
71 napi_value promise = nullptr;
72 napi_async_work asyncWork = nullptr;
73 napi_ref signRef = nullptr;
74
75 HcfSign *sign;
76 HcfBlob *data;
77
78 HcfResult errCode = HCF_SUCCESS;
79 const char *errMsg = nullptr;
80 HcfBlob returnSignatureData;
81 };
82
83 thread_local napi_ref NapiSign::classRef_ = nullptr;
84
FreeSignInitCtx(napi_env env,SignInitCtx * ctx)85 static void FreeSignInitCtx(napi_env env, SignInitCtx *ctx)
86 {
87 if (ctx == nullptr) {
88 return;
89 }
90
91 if (ctx->asyncWork != nullptr) {
92 napi_delete_async_work(env, ctx->asyncWork);
93 }
94
95 if (ctx->callback != nullptr) {
96 napi_delete_reference(env, ctx->callback);
97 }
98
99 if (ctx->signRef != nullptr) {
100 napi_delete_reference(env, ctx->signRef);
101 ctx->signRef = nullptr;
102 }
103
104 if (ctx->priKeyRef != nullptr) {
105 napi_delete_reference(env, ctx->priKeyRef);
106 ctx->priKeyRef = nullptr;
107 }
108
109 HcfFree(ctx);
110 }
111
FreeSignUpdateCtx(napi_env env,SignUpdateCtx * ctx)112 static void FreeSignUpdateCtx(napi_env env, SignUpdateCtx *ctx)
113 {
114 if (ctx == nullptr) {
115 return;
116 }
117
118 if (ctx->asyncWork != nullptr) {
119 napi_delete_async_work(env, ctx->asyncWork);
120 }
121
122 if (ctx->callback != nullptr) {
123 napi_delete_reference(env, ctx->callback);
124 }
125
126 if (ctx->signRef != nullptr) {
127 napi_delete_reference(env, ctx->signRef);
128 ctx->signRef = nullptr;
129 }
130
131 HcfBlobDataFree(ctx->data);
132 HcfFree(ctx->data);
133 HcfFree(ctx);
134 }
135
FreeSignDoFinalCtx(napi_env env,SignDoFinalCtx * ctx)136 static void FreeSignDoFinalCtx(napi_env env, SignDoFinalCtx *ctx)
137 {
138 if (ctx == nullptr) {
139 return;
140 }
141
142 if (ctx->asyncWork != nullptr) {
143 napi_delete_async_work(env, ctx->asyncWork);
144 ctx->asyncWork = nullptr;
145 }
146
147 if (ctx->callback != nullptr) {
148 napi_delete_reference(env, ctx->callback);
149 ctx->callback = nullptr;
150 }
151
152 if (ctx->signRef != nullptr) {
153 napi_delete_reference(env, ctx->signRef);
154 ctx->signRef = nullptr;
155 }
156
157 if (ctx->returnSignatureData.data != nullptr) {
158 HcfFree(ctx->returnSignatureData.data);
159 ctx->returnSignatureData.data = nullptr;
160 ctx->returnSignatureData.len = 0;
161 }
162
163 HcfBlobDataFree(ctx->data);
164 HcfFree(ctx->data);
165 HcfFree(ctx);
166 }
167
BuildSignJsInitCtx(napi_env env,napi_callback_info info,SignInitCtx * ctx)168 static bool BuildSignJsInitCtx(napi_env env, napi_callback_info info, SignInitCtx *ctx)
169 {
170 napi_value thisVar = nullptr;
171 size_t expectedArgc = PARAMS_NUM_TWO;
172 size_t argc = expectedArgc;
173 napi_value argv[PARAMS_NUM_TWO] = { nullptr };
174 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
175 if (argc != expectedArgc && argc != expectedArgc - 1) {
176 LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
177 return false;
178 }
179 ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
180
181 NapiSign *napiSign = nullptr;
182 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
183 if (status != napi_ok || napiSign == nullptr) {
184 LOGE("failed to unwrap napi sign obj.");
185 return false;
186 }
187
188 size_t index = 0;
189 NapiPriKey *napiPriKey = nullptr;
190 status = napi_unwrap(env, argv[index], reinterpret_cast<void **>(&napiPriKey));
191 if (status != napi_ok || napiPriKey == nullptr) {
192 LOGE("failed to unwrap napi priKey obj.");
193 return false;
194 }
195
196 ctx->sign = napiSign->GetSign();
197 ctx->params = nullptr;
198 ctx->priKey = napiPriKey->GetPriKey();
199
200 if (napi_create_reference(env, thisVar, 1, &ctx->signRef) != napi_ok) {
201 LOGE("create sign ref failed when do sign init!");
202 return false;
203 }
204
205 if (napi_create_reference(env, argv[PARAM0], 1, &ctx->priKeyRef) != napi_ok) {
206 LOGE("create private key ref failed when do sign init!");
207 return false;
208 }
209
210 if (ctx->asyncType == ASYNC_PROMISE) {
211 napi_create_promise(env, &ctx->deferred, &ctx->promise);
212 return true;
213 } else {
214 return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
215 }
216 }
217
BuildSignJsUpdateCtx(napi_env env,napi_callback_info info,SignUpdateCtx * ctx)218 static bool BuildSignJsUpdateCtx(napi_env env, napi_callback_info info, SignUpdateCtx *ctx)
219 {
220 napi_value thisVar = nullptr;
221 size_t expectedArgc = PARAMS_NUM_TWO;
222 size_t argc = expectedArgc;
223 napi_value argv[PARAMS_NUM_TWO] = { nullptr };
224 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
225 if ((argc != expectedArgc) && (argc != expectedArgc - 1)) {
226 LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
227 return false;
228 }
229 ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
230
231 NapiSign *napiSign = nullptr;
232 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
233 if (status != napi_ok || napiSign == nullptr) {
234 LOGE("failed to unwrap napi sign obj.");
235 return false;
236 }
237
238 size_t index = 0;
239 HcfBlob *blob = GetBlobFromNapiDataBlob(env, argv[index]);
240 if (blob == nullptr) {
241 LOGE("failed to get data.");
242 return false;
243 }
244
245 ctx->sign = napiSign->GetSign();
246 ctx->data = blob;
247
248 if (napi_create_reference(env, thisVar, 1, &ctx->signRef) != napi_ok) {
249 LOGE("create sign ref failed when do sign update!");
250 return false;
251 }
252
253 if (ctx->asyncType == ASYNC_PROMISE) {
254 napi_create_promise(env, &ctx->deferred, &ctx->promise);
255 return true;
256 } else {
257 return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
258 }
259 }
260
BuildSignJsDoFinalCtx(napi_env env,napi_callback_info info,SignDoFinalCtx * ctx)261 static bool BuildSignJsDoFinalCtx(napi_env env, napi_callback_info info, SignDoFinalCtx *ctx)
262 {
263 napi_value thisVar = nullptr;
264 size_t expectedArgc = PARAMS_NUM_TWO;
265 size_t argc = expectedArgc;
266 napi_value argv[PARAMS_NUM_TWO] = { nullptr };
267 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
268 if ((argc != expectedArgc) && (argc != expectedArgc - 1)) {
269 LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
270 return false;
271 }
272 ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
273
274 NapiSign *napiSign = nullptr;
275 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
276 if (status != napi_ok || napiSign == nullptr) {
277 LOGE("failed to unwrap napi sign obj.");
278 return false;
279 }
280
281 size_t index = 0;
282 napi_valuetype valueType;
283 napi_typeof(env, argv[index], &valueType);
284 HcfBlob *data = nullptr;
285 if (valueType != napi_null) {
286 data = GetBlobFromNapiDataBlob(env, argv[index]);
287 if (data == nullptr) {
288 LOGE("failed to get data.");
289 return false;
290 }
291 }
292
293 ctx->sign = napiSign->GetSign();
294 ctx->data = data;
295
296 if (napi_create_reference(env, thisVar, 1, &ctx->signRef) != napi_ok) {
297 LOGE("create sign ref failed when do sign final!");
298 return false;
299 }
300
301 if (ctx->asyncType == ASYNC_PROMISE) {
302 napi_create_promise(env, &ctx->deferred, &ctx->promise);
303 return true;
304 } else {
305 return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
306 }
307 }
308
ReturnInitCallbackResult(napi_env env,SignInitCtx * ctx,napi_value result)309 static void ReturnInitCallbackResult(napi_env env, SignInitCtx *ctx, napi_value result)
310 {
311 napi_value businessError = nullptr;
312 if (ctx->errCode != HCF_SUCCESS) {
313 businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
314 }
315
316 napi_value params[ARGS_SIZE_ONE] = { businessError };
317
318 napi_value func = nullptr;
319 napi_get_reference_value(env, ctx->callback, &func);
320
321 napi_value recv = nullptr;
322 napi_value callFuncRet = nullptr;
323 napi_get_undefined(env, &recv);
324 napi_call_function(env, recv, func, ARGS_SIZE_ONE, params, &callFuncRet);
325 }
326
ReturnInitPromiseResult(napi_env env,SignInitCtx * ctx,napi_value result)327 static void ReturnInitPromiseResult(napi_env env, SignInitCtx *ctx, napi_value result)
328 {
329 if (ctx->errCode == HCF_SUCCESS) {
330 napi_resolve_deferred(env, ctx->deferred, result);
331 } else {
332 napi_reject_deferred(env, ctx->deferred, GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
333 }
334 }
335
ReturnUpdateCallbackResult(napi_env env,SignUpdateCtx * ctx,napi_value result)336 static void ReturnUpdateCallbackResult(napi_env env, SignUpdateCtx *ctx, napi_value result)
337 {
338 napi_value businessError = nullptr;
339 if (ctx->errCode != HCF_SUCCESS) {
340 businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
341 }
342
343 napi_value params[ARGS_SIZE_ONE] = { businessError };
344
345 napi_value func = nullptr;
346 napi_get_reference_value(env, ctx->callback, &func);
347
348 napi_value recv = nullptr;
349 napi_value callFuncRet = nullptr;
350 napi_get_undefined(env, &recv);
351 napi_call_function(env, recv, func, ARGS_SIZE_ONE, params, &callFuncRet);
352 }
353
ReturnUpdatePromiseResult(napi_env env,SignUpdateCtx * ctx,napi_value result)354 static void ReturnUpdatePromiseResult(napi_env env, SignUpdateCtx *ctx, napi_value result)
355 {
356 if (ctx->errCode == HCF_SUCCESS) {
357 napi_resolve_deferred(env, ctx->deferred, result);
358 } else {
359 napi_reject_deferred(env, ctx->deferred, GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
360 }
361 }
362
ReturnDoFinalCallbackResult(napi_env env,SignDoFinalCtx * ctx,napi_value result)363 static void ReturnDoFinalCallbackResult(napi_env env, SignDoFinalCtx *ctx, napi_value result)
364 {
365 napi_value businessError = nullptr;
366 if (ctx->errCode != HCF_SUCCESS) {
367 businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
368 }
369
370 napi_value params[ARGS_SIZE_TWO] = { businessError, result };
371
372 napi_value func = nullptr;
373 napi_get_reference_value(env, ctx->callback, &func);
374
375 napi_value recv = nullptr;
376 napi_value callFuncRet = nullptr;
377 napi_get_undefined(env, &recv);
378 napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
379 }
380
ReturnDoFinalPromiseResult(napi_env env,SignDoFinalCtx * ctx,napi_value result)381 static void ReturnDoFinalPromiseResult(napi_env env, SignDoFinalCtx *ctx, napi_value result)
382 {
383 if (ctx->errCode == HCF_SUCCESS) {
384 napi_resolve_deferred(env, ctx->deferred, result);
385 } else {
386 napi_reject_deferred(env, ctx->deferred, GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
387 }
388 }
389
SignJsInitAsyncWorkProcess(napi_env env,void * data)390 static void SignJsInitAsyncWorkProcess(napi_env env, void *data)
391 {
392 SignInitCtx *ctx = static_cast<SignInitCtx *>(data);
393
394 ctx->errCode = ctx->sign->init(ctx->sign, ctx->params, ctx->priKey);
395 if (ctx->errCode != HCF_SUCCESS) {
396 LOGD("[error] sign init fail.");
397 ctx->errMsg = "sign init fail.";
398 }
399 }
400
SignJsInitAsyncWorkReturn(napi_env env,napi_status status,void * data)401 static void SignJsInitAsyncWorkReturn(napi_env env, napi_status status, void *data)
402 {
403 SignInitCtx *ctx = static_cast<SignInitCtx *>(data);
404
405 if (ctx->asyncType == ASYNC_CALLBACK) {
406 ReturnInitCallbackResult(env, ctx, NapiGetNull(env));
407 } else {
408 ReturnInitPromiseResult(env, ctx, NapiGetNull(env));
409 }
410 FreeSignInitCtx(env, ctx);
411 }
412
SignJsUpdateAsyncWorkProcess(napi_env env,void * data)413 static void SignJsUpdateAsyncWorkProcess(napi_env env, void *data)
414 {
415 SignUpdateCtx *ctx = static_cast<SignUpdateCtx *>(data);
416
417 ctx->errCode = ctx->sign->update(ctx->sign, ctx->data);
418 if (ctx->errCode != HCF_SUCCESS) {
419 LOGD("[error] sign update fail.");
420 ctx->errMsg = "sign update fail.";
421 }
422 }
423
SignJsUpdateAsyncWorkReturn(napi_env env,napi_status status,void * data)424 static void SignJsUpdateAsyncWorkReturn(napi_env env, napi_status status, void *data)
425 {
426 SignUpdateCtx *ctx = static_cast<SignUpdateCtx *>(data);
427
428 if (ctx->asyncType == ASYNC_CALLBACK) {
429 ReturnUpdateCallbackResult(env, ctx, NapiGetNull(env));
430 } else {
431 ReturnUpdatePromiseResult(env, ctx, NapiGetNull(env));
432 }
433 FreeSignUpdateCtx(env, ctx);
434 }
435
SignJsDoFinalAsyncWorkProcess(napi_env env,void * data)436 static void SignJsDoFinalAsyncWorkProcess(napi_env env, void *data)
437 {
438 SignDoFinalCtx *ctx = static_cast<SignDoFinalCtx *>(data);
439
440 ctx->errCode = ctx->sign->sign(ctx->sign, ctx->data, &ctx->returnSignatureData);
441 if (ctx->errCode != HCF_SUCCESS) {
442 LOGD("[error] sign doFinal fail.");
443 ctx->errMsg = "sign doFinal fail.";
444 }
445 }
446
SignJsDoFinalAsyncWorkReturn(napi_env env,napi_status status,void * data)447 static void SignJsDoFinalAsyncWorkReturn(napi_env env, napi_status status, void *data)
448 {
449 SignDoFinalCtx *ctx = static_cast<SignDoFinalCtx *>(data);
450
451 napi_value dataBlob = nullptr;
452 if (ctx->errCode == HCF_SUCCESS) {
453 dataBlob = ConvertBlobToNapiValue(env, &ctx->returnSignatureData);
454 }
455
456 if (ctx->asyncType == ASYNC_CALLBACK) {
457 ReturnDoFinalCallbackResult(env, ctx, dataBlob);
458 } else {
459 ReturnDoFinalPromiseResult(env, ctx, dataBlob);
460 }
461 FreeSignDoFinalCtx(env, ctx);
462 }
463
NewSignJsInitAsyncWork(napi_env env,SignInitCtx * ctx)464 static napi_value NewSignJsInitAsyncWork(napi_env env, SignInitCtx *ctx)
465 {
466 napi_value resourceName = nullptr;
467 napi_create_string_utf8(env, "init", NAPI_AUTO_LENGTH, &resourceName);
468
469 napi_create_async_work(
470 env, nullptr, resourceName,
471 [](napi_env env, void *data) {
472 SignJsInitAsyncWorkProcess(env, data);
473 return;
474 },
475 [](napi_env env, napi_status status, void *data) {
476 SignJsInitAsyncWorkReturn(env, status, data);
477 return;
478 },
479 static_cast<void *>(ctx),
480 &ctx->asyncWork);
481
482 napi_queue_async_work(env, ctx->asyncWork);
483 if (ctx->asyncType == ASYNC_PROMISE) {
484 return ctx->promise;
485 } else {
486 return NapiGetNull(env);
487 }
488 }
489
NewSignJsUpdateAsyncWork(napi_env env,SignUpdateCtx * ctx)490 static napi_value NewSignJsUpdateAsyncWork(napi_env env, SignUpdateCtx *ctx)
491 {
492 napi_value resourceName = nullptr;
493 napi_create_string_utf8(env, "update", NAPI_AUTO_LENGTH, &resourceName);
494
495 napi_create_async_work(
496 env, nullptr, resourceName,
497 [](napi_env env, void *data) {
498 SignJsUpdateAsyncWorkProcess(env, data);
499 return;
500 },
501 [](napi_env env, napi_status status, void *data) {
502 SignJsUpdateAsyncWorkReturn(env, status, data);
503 return;
504 },
505 static_cast<void *>(ctx),
506 &ctx->asyncWork);
507
508 napi_queue_async_work(env, ctx->asyncWork);
509 if (ctx->asyncType == ASYNC_PROMISE) {
510 return ctx->promise;
511 } else {
512 return NapiGetNull(env);
513 }
514 }
515
NewSignJsDoFinalAsyncWork(napi_env env,SignDoFinalCtx * ctx)516 static napi_value NewSignJsDoFinalAsyncWork(napi_env env, SignDoFinalCtx *ctx)
517 {
518 napi_value resourceName = nullptr;
519 napi_create_string_utf8(env, "sign", NAPI_AUTO_LENGTH, &resourceName);
520
521 napi_create_async_work(
522 env, nullptr, resourceName,
523 [](napi_env env, void *data) {
524 SignJsDoFinalAsyncWorkProcess(env, data);
525 return;
526 },
527 [](napi_env env, napi_status status, void *data) {
528 SignJsDoFinalAsyncWorkReturn(env, status, data);
529 return;
530 },
531 static_cast<void *>(ctx),
532 &ctx->asyncWork);
533
534 napi_queue_async_work(env, ctx->asyncWork);
535 if (ctx->asyncType == ASYNC_PROMISE) {
536 return ctx->promise;
537 } else {
538 return NapiGetNull(env);
539 }
540 }
541
NapiSign(HcfSign * sign)542 NapiSign::NapiSign(HcfSign *sign)
543 {
544 this->sign_ = sign;
545 }
546
~NapiSign()547 NapiSign::~NapiSign()
548 {
549 HcfObjDestroy(this->sign_);
550 }
551
GetSign()552 HcfSign *NapiSign::GetSign()
553 {
554 return this->sign_;
555 }
556
JsInit(napi_env env,napi_callback_info info)557 napi_value NapiSign::JsInit(napi_env env, napi_callback_info info)
558 {
559 SignInitCtx *ctx = static_cast<SignInitCtx *>(HcfMalloc(sizeof(SignInitCtx), 0));
560 if (ctx == nullptr) {
561 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
562 LOGE("create context fail.");
563 return nullptr;
564 }
565
566 if (!BuildSignJsInitCtx(env, info, ctx)) {
567 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
568 LOGE("build context fail.");
569 FreeSignInitCtx(env, ctx);
570 return nullptr;
571 }
572
573 return NewSignJsInitAsyncWork(env, ctx);
574 }
575
JsInitSync(napi_env env,napi_callback_info info)576 napi_value NapiSign::JsInitSync(napi_env env, napi_callback_info info)
577 {
578 napi_value thisVar = nullptr;
579 size_t expectedArgc = PARAMS_NUM_ONE;
580 size_t argc = expectedArgc;
581 napi_value argv[PARAMS_NUM_ONE] = { nullptr };
582 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
583 if (argc != PARAMS_NUM_ONE) {
584 LOGE("wrong argument num. require %d arguments. [Argc]: %zu!", PARAMS_NUM_ONE, argc);
585 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "wrong argument num."));
586 return nullptr;
587 }
588
589 NapiSign *napiSign = nullptr;
590 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
591 if (status != napi_ok || napiSign == nullptr) {
592 LOGE("failed to unwrap napi sign obj.");
593 napi_throw(env, GenerateBusinessError(env, HCF_ERR_NAPI, "failed to unwrap napi sign obj."));
594 return nullptr;
595 }
596
597 NapiPriKey *napiPriKey = nullptr;
598 status = napi_unwrap(env, argv[PARAM0], reinterpret_cast<void **>(&napiPriKey));
599 if (status != napi_ok || napiPriKey == nullptr) {
600 LOGE("failed to unwrap napi priKey obj.");
601 napi_throw(env, GenerateBusinessError(env, HCF_ERR_NAPI, "failed to unwrap napi priKey obj."));
602 return nullptr;
603 }
604
605 HcfSign *sign = napiSign->GetSign();
606 HcfPriKey *priKey = napiPriKey->GetPriKey();
607 HcfResult ret = sign->init(sign, nullptr, priKey);
608 if (ret != HCF_SUCCESS) {
609 LOGD("sign init fail.");
610 napi_throw(env, GenerateBusinessError(env, ret, "sign init fail."));
611 return nullptr;
612 }
613 napi_value instance = NapiGetNull(env);
614 return instance;
615 }
616
JsUpdate(napi_env env,napi_callback_info info)617 napi_value NapiSign::JsUpdate(napi_env env, napi_callback_info info)
618 {
619 SignUpdateCtx *ctx = static_cast<SignUpdateCtx *>(HcfMalloc(sizeof(SignUpdateCtx), 0));
620 if (ctx == nullptr) {
621 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
622 LOGE("create context fail.");
623 return nullptr;
624 }
625
626 if (!BuildSignJsUpdateCtx(env, info, ctx)) {
627 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
628 LOGE("build context fail.");
629 FreeSignUpdateCtx(env, ctx);
630 return nullptr;
631 }
632
633 return NewSignJsUpdateAsyncWork(env, ctx);
634 }
635
JsUpdateSync(napi_env env,napi_callback_info info)636 napi_value NapiSign::JsUpdateSync(napi_env env, napi_callback_info info)
637 {
638 napi_value thisVar = nullptr;
639 size_t argc = PARAMS_NUM_ONE;
640 napi_value argv[PARAMS_NUM_ONE] = { nullptr };
641 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
642 if (argc != PARAMS_NUM_ONE) {
643 LOGE("wrong argument num. require %d arguments. [Argc]: %zu!", PARAMS_NUM_ONE, argc);
644 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "wrong argument num."));
645 return nullptr;
646 }
647
648 NapiSign *napiSign = nullptr;
649 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
650 if (status != napi_ok || napiSign == nullptr) {
651 LOGE("failed to unwrap napi sign obj.");
652 napi_throw(env, GenerateBusinessError(env, HCF_ERR_NAPI, "failed to unwrap napi sign obj."));
653 return nullptr;
654 }
655
656 HcfBlob blob = { 0 };
657 HcfResult ret = GetBlobFromNapiValue(env, argv[PARAM0], &blob);
658 if (ret != HCF_SUCCESS) {
659 LOGE("failed to get input blob!");
660 napi_throw(env, GenerateBusinessError(env, ret, "failed to get data."));
661 return nullptr;
662 }
663
664 HcfSign *sign = napiSign->GetSign();
665 ret = sign->update(sign, &blob);
666 HcfBlobDataFree(&blob);
667 if (ret != HCF_SUCCESS) {
668 LOGD("sign update fail.");
669 napi_throw(env, GenerateBusinessError(env, ret, "sign update fail."));
670 return nullptr;
671 }
672 napi_value instance = NapiGetNull(env);
673 return instance;
674 }
675
JsSign(napi_env env,napi_callback_info info)676 napi_value NapiSign::JsSign(napi_env env, napi_callback_info info)
677 {
678 SignDoFinalCtx *ctx = static_cast<SignDoFinalCtx *>(HcfMalloc(sizeof(SignDoFinalCtx), 0));
679 if (ctx == nullptr) {
680 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
681 LOGE("create context fail.");
682 return nullptr;
683 }
684
685 if (!BuildSignJsDoFinalCtx(env, info, ctx)) {
686 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
687 LOGE("build context fail.");
688 FreeSignDoFinalCtx(env, ctx);
689 return nullptr;
690 }
691
692 return NewSignJsDoFinalAsyncWork(env, ctx);
693 }
694
JsSignSync(napi_env env,napi_callback_info info)695 napi_value NapiSign::JsSignSync(napi_env env, napi_callback_info info)
696 {
697 napi_value thisVar = nullptr;
698 size_t argc = PARAMS_NUM_ONE;
699 napi_value argv[PARAMS_NUM_ONE] = { nullptr };
700 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
701 if (argc != PARAMS_NUM_ONE) {
702 LOGE("wrong argument num. require %d arguments. [Argc]: %zu!", PARAMS_NUM_ONE, argc);
703 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "wrong argument num."));
704 return nullptr;
705 }
706
707 NapiSign *napiSign = nullptr;
708 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
709 if (status != napi_ok || napiSign == nullptr) {
710 LOGE("failed to unwrap napi sign obj.");
711 napi_throw(env, GenerateBusinessError(env, HCF_ERR_NAPI, "failed to unwrap napi sign obj."));
712 return nullptr;
713 }
714
715 napi_valuetype valueType;
716 napi_typeof(env, argv[PARAM0], &valueType);
717 HcfBlob *data = nullptr;
718 HcfBlob blob = { 0 };
719 if (valueType != napi_null) {
720 HcfResult ret = GetBlobFromNapiValue(env, argv[PARAM0], &blob);
721 if (ret != HCF_SUCCESS) {
722 LOGE("failed to get data.");
723 napi_throw(env, GenerateBusinessError(env, ret, "failed to get data."));
724 return nullptr;
725 }
726 data = &blob;
727 }
728
729 HcfSign *sign = napiSign->GetSign();
730 HcfBlob returnSignatureData = { .data = nullptr, .len = 0 };
731 HcfResult ret = sign->sign(sign, data, &returnSignatureData);
732 HcfBlobDataFree(data);
733 if (ret != HCF_SUCCESS) {
734 LOGD("sign doFinal fail.");
735 napi_throw(env, GenerateBusinessError(env, ret, "sign doFinal fail."));
736 return nullptr;
737 }
738
739 napi_value instance = nullptr;
740 ret = ConvertDataBlobToNapiValue(env, &returnSignatureData, &instance);
741 HcfBlobDataFree(&returnSignatureData);
742 if (ret != HCF_SUCCESS) {
743 LOGE("sign convert dataBlob to napi_value failed!");
744 napi_throw(env, GenerateBusinessError(env, ret, "sign convert dataBlob to napi_value failed!"));
745 return nullptr;
746 }
747
748 return instance;
749 }
750
SignConstructor(napi_env env,napi_callback_info info)751 napi_value NapiSign::SignConstructor(napi_env env, napi_callback_info info)
752 {
753 napi_value thisVar = nullptr;
754 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
755 return thisVar;
756 }
757
NapiWrapSign(napi_env env,napi_value instance,NapiSign * napiSign)758 static napi_value NapiWrapSign(napi_env env, napi_value instance, NapiSign *napiSign)
759 {
760 napi_status status = napi_wrap(
761 env, instance, napiSign,
762 [](napi_env env, void *data, void *hint) {
763 NapiSign *napiSign = static_cast<NapiSign *>(data);
764 delete napiSign;
765 return;
766 }, nullptr, nullptr);
767 if (status != napi_ok) {
768 LOGE("failed to wrap napiSign obj!");
769 delete napiSign;
770 return nullptr;
771 }
772 return instance;
773 }
774
CreateJsSign(napi_env env,napi_callback_info info)775 napi_value NapiSign::CreateJsSign(napi_env env, napi_callback_info info)
776 {
777 size_t expectedArgc = PARAMS_NUM_ONE;
778 size_t argc = expectedArgc;
779 napi_value argv[PARAMS_NUM_ONE] = { nullptr };
780 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
781
782 if (argc != expectedArgc) {
783 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
784 LOGE("The input args num is invalid.");
785 return nullptr;
786 }
787
788 napi_value instance;
789 napi_value constructor = nullptr;
790 napi_get_reference_value(env, classRef_, &constructor);
791 napi_new_instance(env, constructor, argc, argv, &instance);
792
793 std::string algName;
794 if (!GetStringFromJSParams(env, argv[0], algName)) {
795 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get algName fail."));
796 return nullptr;
797 }
798
799 HcfSign *sign = nullptr;
800 HcfResult ret = HcfSignCreate(algName.c_str(), &sign);
801 if (ret != HCF_SUCCESS) {
802 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "create c sign fail."));
803 LOGE("create c sign fail.");
804 return nullptr;
805 }
806
807 NapiSign *napiSign = new (std::nothrow) NapiSign(sign);
808 if (napiSign == nullptr) {
809 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi sign failed"));
810 LOGE("new napi sign failed");
811 HcfObjDestroy(sign);
812 return nullptr;
813 }
814
815 napi_value napiAlgName = nullptr;
816 napi_create_string_utf8(env, algName.c_str(), NAPI_AUTO_LENGTH, &napiAlgName);
817 napi_set_named_property(env, instance, CRYPTO_TAG_ALG_NAME.c_str(), napiAlgName);
818
819 return NapiWrapSign(env, instance, napiSign);
820 }
821
SetSignUserIdUintArray(napi_env env,napi_value * argv,HcfSign * sign)822 static HcfResult SetSignUserIdUintArray(napi_env env, napi_value *argv, HcfSign *sign)
823 {
824 HcfBlob *blob = nullptr;
825 blob = GetBlobFromNapiUint8Arr(env, argv[1]);
826 if (blob == nullptr) {
827 LOGE("failed to get blob.");
828 return HCF_INVALID_PARAMS;
829 }
830 HcfResult ret = sign->setSignSpecUint8Array(sign, SM2_USER_ID_UINT8ARR, *blob);
831 if (ret != HCF_SUCCESS) {
832 HcfBlobDataFree(blob);
833 HcfFree(blob);
834 LOGE("c setSignSpecUint8Array failed.");
835 return HCF_INVALID_PARAMS;
836 }
837 HcfBlobDataFree(blob);
838 HcfFree(blob);
839 return ret;
840 }
841
SetSignSaltLenInt(napi_env env,napi_value * argv,HcfSign * sign)842 static HcfResult SetSignSaltLenInt(napi_env env, napi_value *argv, HcfSign *sign)
843 {
844 int32_t saltLen = 0;
845 if (napi_get_value_int32(env, argv[1], &saltLen) != napi_ok) {
846 LOGE("get signSpec saltLen failed!");
847 return HCF_INVALID_PARAMS;
848 }
849 HcfResult ret = HCF_SUCCESS;
850 ret = sign->setSignSpecInt(sign, PSS_SALT_LEN_INT, saltLen);
851 if (ret != HCF_SUCCESS) {
852 LOGE("c setSignSpecNumber fail.");
853 return HCF_INVALID_PARAMS;
854 }
855 return ret;
856 }
857
SetDetailSignSpec(napi_env env,napi_value * argv,SignSpecItem item,HcfSign * sign)858 static HcfResult SetDetailSignSpec(napi_env env, napi_value *argv, SignSpecItem item, HcfSign *sign)
859 {
860 HcfResult result = HCF_INVALID_PARAMS;
861
862 switch (item) {
863 case SM2_USER_ID_UINT8ARR:
864 result = SetSignUserIdUintArray(env, argv, sign);
865 break;
866 case PSS_SALT_LEN_INT:
867 result = SetSignSaltLenInt(env, argv, sign);
868 break;
869 default:
870 LOGE("specItem not support.");
871 break;
872 }
873 return result;
874 }
875
876 // sign setSignSpec(itemType :signSpecItem, itemValue : number|string)
JsSetSignSpec(napi_env env,napi_callback_info info)877 napi_value NapiSign::JsSetSignSpec(napi_env env, napi_callback_info info)
878 {
879 napi_value thisVar = nullptr;
880 NapiSign *napiSign = nullptr;
881 size_t expectedArgc = ARGS_SIZE_TWO;
882 size_t argc = ARGS_SIZE_TWO;
883 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
884 // thisVar means the js this argument for the call (sign.() means this = sign)
885 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
886 if (argc != expectedArgc) {
887 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "init failed for wrong argument num."));
888 LOGE("wrong argument num. require 2 arguments. [Argc]: %zu!", argc);
889 return nullptr;
890 }
891 SignSpecItem item;
892 if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
893 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get signSpecItem failed!"));
894 LOGE("get signspecitem failed!");
895 return nullptr;
896 }
897 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
898 if (status != napi_ok || napiSign == nullptr) {
899 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiSign obj!"));
900 LOGE("failed to unwrap napiSign obj!");
901 return nullptr;
902 }
903 HcfSign *sign = napiSign->GetSign();
904 if (SetDetailSignSpec(env, argv, item, sign) != HCF_SUCCESS) {
905 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to set sign spec!"));
906 LOGE("failed to set sign spec!");
907 return nullptr;
908 }
909 return thisVar;
910 }
911
GetSignSpecString(napi_env env,SignSpecItem item,HcfSign * sign)912 static napi_value GetSignSpecString(napi_env env, SignSpecItem item, HcfSign *sign)
913 {
914 char *returnString = nullptr;
915 HcfResult ret = sign->getSignSpecString(sign, item, &returnString);
916 if (ret != HCF_SUCCESS) {
917 napi_throw(env, GenerateBusinessError(env, ret, "C getSignSpecString failed."));
918 LOGE("c getSignSpecString fail.");
919 return nullptr;
920 }
921
922 napi_value instance = nullptr;
923 napi_create_string_utf8(env, returnString, NAPI_AUTO_LENGTH, &instance);
924 HcfFree(returnString);
925 return instance;
926 }
927
GetSignSpecNumber(napi_env env,SignSpecItem item,HcfSign * sign)928 static napi_value GetSignSpecNumber(napi_env env, SignSpecItem item, HcfSign *sign)
929 {
930 int returnInt;
931 HcfResult ret = sign->getSignSpecInt(sign, item, &returnInt);
932 if (ret != HCF_SUCCESS) {
933 napi_throw(env, GenerateBusinessError(env, ret, "C getSignSpecInt failed."));
934 LOGE("c getSignSpecInt fail.");
935 return nullptr;
936 }
937
938 napi_value instance = nullptr;
939 napi_create_int32(env, returnInt, &instance);
940 return instance;
941 }
942
JsGetSignSpec(napi_env env,napi_callback_info info)943 napi_value NapiSign::JsGetSignSpec(napi_env env, napi_callback_info info)
944 {
945 napi_value thisVar = nullptr;
946 NapiSign *napiSign = nullptr;
947 size_t expectedArgc = ARGS_SIZE_ONE;
948 size_t argc = ARGS_SIZE_ONE;
949 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
950 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
951 if (argc != expectedArgc) {
952 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "init failed for wrong argument num."));
953 LOGE("wrong argument num. require 1 arguments. [Argc]: %zu!", argc);
954 return nullptr;
955 }
956 SignSpecItem item;
957 if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
958 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get signSpecItem failed!"));
959 LOGE("get signSpecItem failed!");
960 return nullptr;
961 }
962
963 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiSign));
964 if (status != napi_ok || napiSign == nullptr) {
965 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiSign obj!"));
966 LOGE("failed to unwrap napiSign obj!");
967 return nullptr;
968 }
969 HcfSign *sign = napiSign->GetSign();
970 if (sign == nullptr) {
971 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get sign obj!"));
972 LOGE("failed to get sign obj!");
973 return nullptr;
974 }
975
976 int32_t type = GetSignSpecType(item);
977 if (type == SPEC_ITEM_TYPE_STR) {
978 return GetSignSpecString(env, item, sign);
979 } else if (type == SPEC_ITEM_TYPE_NUM) {
980 return GetSignSpecNumber(env, item, sign);
981 } else {
982 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "signSpecItem not support!"));
983 return nullptr;
984 }
985 }
986
DefineSignJSClass(napi_env env,napi_value exports)987 void NapiSign::DefineSignJSClass(napi_env env, napi_value exports)
988 {
989 napi_property_descriptor desc[] = {
990 DECLARE_NAPI_FUNCTION("createSign", NapiSign::CreateJsSign),
991 };
992 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
993
994 napi_property_descriptor classDesc[] = {
995 DECLARE_NAPI_FUNCTION("init", NapiSign::JsInit),
996 DECLARE_NAPI_FUNCTION("update", NapiSign::JsUpdate),
997 DECLARE_NAPI_FUNCTION("sign", NapiSign::JsSign),
998 DECLARE_NAPI_FUNCTION("initSync", NapiSign::JsInitSync),
999 DECLARE_NAPI_FUNCTION("updateSync", NapiSign::JsUpdateSync),
1000 DECLARE_NAPI_FUNCTION("signSync", NapiSign::JsSignSync),
1001 DECLARE_NAPI_FUNCTION("setSignSpec", NapiSign::JsSetSignSpec),
1002 DECLARE_NAPI_FUNCTION("getSignSpec", NapiSign::JsGetSignSpec),
1003 };
1004 napi_value constructor = nullptr;
1005 napi_define_class(env, "Sign", NAPI_AUTO_LENGTH, NapiSign::SignConstructor, nullptr,
1006 sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
1007 napi_create_reference(env, constructor, 1, &classRef_);
1008 }
1009 } // CryptoFramework
1010 } // OHOS
1011