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