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