• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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