• 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_verify.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 VerifyInitCtx {
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     HcfVerify *verify = nullptr;
39     HcfParamsSpec *params = nullptr;
40     HcfPubKey *pubKey = nullptr;
41 
42     HcfResult errCode = HCF_SUCCESS;
43     const char *errMsg = nullptr;
44 };
45 
46 struct VerifyUpdateCtx {
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     HcfVerify *verify = nullptr;
56     HcfBlob *data = nullptr;
57 
58     HcfResult errCode = HCF_SUCCESS;
59     const char *errMsg = nullptr;
60 };
61 
62 struct VerifyDoFinalCtx {
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     HcfVerify *verify = nullptr;
72     HcfBlob *data = nullptr;
73     HcfBlob *signatureData = nullptr;
74 
75     HcfResult errCode = HCF_SUCCESS;
76     const char *errMsg = nullptr;
77     bool isVerifySucc;
78 };
79 
80 thread_local napi_ref NapiVerify::classRef_ = nullptr;
81 
FreeVerifyInitCtx(napi_env env,VerifyInitCtx * ctx)82 static void FreeVerifyInitCtx(napi_env env, VerifyInitCtx *ctx)
83 {
84     if (ctx == nullptr) {
85         return;
86     }
87 
88     if (ctx->asyncWork != nullptr) {
89         napi_delete_async_work(env, ctx->asyncWork);
90         ctx->asyncWork = nullptr;
91     }
92 
93     if (ctx->callback != nullptr) {
94         napi_delete_reference(env, ctx->callback);
95         ctx->callback = nullptr;
96     }
97 
98     HcfFree(ctx);
99 }
100 
FreeVerifyUpdateCtx(napi_env env,VerifyUpdateCtx * ctx)101 static void FreeVerifyUpdateCtx(napi_env env, VerifyUpdateCtx *ctx)
102 {
103     if (ctx == nullptr) {
104         return;
105     }
106 
107     if (ctx->asyncWork != nullptr) {
108         napi_delete_async_work(env, ctx->asyncWork);
109         ctx->asyncWork = nullptr;
110     }
111 
112     if (ctx->callback != nullptr) {
113         napi_delete_reference(env, ctx->callback);
114         ctx->callback = nullptr;
115     }
116 
117     HcfBlobDataFree(ctx->data);
118     HcfFree(ctx->data);
119     HcfFree(ctx);
120 }
121 
FreeVerifyDoFinalCtx(napi_env env,VerifyDoFinalCtx * ctx)122 static void FreeVerifyDoFinalCtx(napi_env env, VerifyDoFinalCtx *ctx)
123 {
124     if (ctx == nullptr) {
125         return;
126     }
127 
128     if (ctx->asyncWork != nullptr) {
129         napi_delete_async_work(env, ctx->asyncWork);
130         ctx->asyncWork = nullptr;
131     }
132 
133     if (ctx->callback != nullptr) {
134         napi_delete_reference(env, ctx->callback);
135         ctx->callback = nullptr;
136     }
137 
138     HcfBlobDataFree(ctx->data);
139     HcfFree(ctx->data);
140     HcfBlobDataFree(ctx->signatureData);
141     HcfFree(ctx->signatureData);
142     HcfFree(ctx);
143 }
144 
BuildVerifyJsInitCtx(napi_env env,napi_callback_info info,VerifyInitCtx * ctx)145 static bool BuildVerifyJsInitCtx(napi_env env, napi_callback_info info, VerifyInitCtx *ctx)
146 {
147     napi_value thisVar = nullptr;
148     size_t expectedArgc = PARAMS_NUM_TWO;
149     size_t argc = expectedArgc;
150     napi_value argv[PARAMS_NUM_TWO] = { nullptr, nullptr };
151     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
152     if ((argc != expectedArgc) && (argc != expectedArgc - 1)) {
153         LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
154         return false;
155     }
156     ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
157 
158     NapiVerify *napiVerify = nullptr;
159     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiVerify));
160     if (status != napi_ok || napiVerify == nullptr) {
161         LOGE("failed to unwrap napi verify obj.");
162         return false;
163     }
164 
165     size_t index = 0;
166     NapiPubKey *napiPubKey = nullptr;
167     status = napi_unwrap(env, argv[index], reinterpret_cast<void **>(&napiPubKey));
168     if (status != napi_ok || napiPubKey == nullptr) {
169         LOGE("failed to unwrap napi pubKey obj.");
170         return false;
171     }
172 
173     ctx->verify = napiVerify->GetVerify();
174     ctx->params = nullptr;
175     ctx->pubKey = napiPubKey->GetPubKey();
176 
177     if (ctx->asyncType == ASYNC_PROMISE) {
178         napi_create_promise(env, &ctx->deferred, &ctx->promise);
179         return true;
180     } else {
181         return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
182     }
183 }
184 
BuildVerifyJsUpdateCtx(napi_env env,napi_callback_info info,VerifyUpdateCtx * ctx)185 static bool BuildVerifyJsUpdateCtx(napi_env env, napi_callback_info info, VerifyUpdateCtx *ctx)
186 {
187     napi_value thisVar = nullptr;
188     size_t expectedArgc = PARAMS_NUM_TWO;
189     size_t argc = expectedArgc;
190     napi_value argv[PARAMS_NUM_TWO] = { nullptr, nullptr };
191     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
192     if ((argc != expectedArgc) && (argc != expectedArgc - 1)) {
193         LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
194         return false;
195     }
196     ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
197 
198     NapiVerify *napiVerify = nullptr;
199     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiVerify));
200     if (status != napi_ok || napiVerify == nullptr) {
201         LOGE("failed to unwrap napi verify obj.");
202         return false;
203     }
204 
205     size_t index = 0;
206     HcfBlob *blob = GetBlobFromNapiValue(env, argv[index]);
207     if (blob == nullptr) {
208         return false;
209     }
210 
211     ctx->verify = napiVerify->GetVerify();
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 
GetDataBlobAndSignatureFromInput(napi_env env,napi_value dataValue,napi_value signatureDataValue,HcfBlob ** returnData,HcfBlob ** returnSignatureData)222 static bool GetDataBlobAndSignatureFromInput(napi_env env, napi_value dataValue, napi_value signatureDataValue,
223     HcfBlob **returnData, HcfBlob **returnSignatureData)
224 {
225     napi_valuetype valueType;
226     napi_typeof(env, dataValue, &valueType);
227     HcfBlob *data = nullptr;
228     if (valueType != napi_null) {
229         data = GetBlobFromNapiValue(env, dataValue);
230         if (data == nullptr) {
231             LOGE("failed to get data.");
232             return false;
233         }
234     }
235 
236     HcfBlob *signatureData = GetBlobFromNapiValue(env, signatureDataValue);
237     if (signatureData == nullptr) {
238         LOGE("failed to get signature.");
239         HcfBlobDataFree(data);
240         HcfFree(data);
241         return false;
242     }
243 
244     *returnData = data;
245     *returnSignatureData = signatureData;
246     return true;
247 }
248 
BuildVerifyJsDoFinalCtx(napi_env env,napi_callback_info info,VerifyDoFinalCtx * ctx)249 static bool BuildVerifyJsDoFinalCtx(napi_env env, napi_callback_info info, VerifyDoFinalCtx *ctx)
250 {
251     napi_value thisVar = nullptr;
252     size_t expectedArgc = PARAMS_NUM_THREE;
253     size_t argc = expectedArgc;
254     napi_value argv[PARAMS_NUM_THREE] = { nullptr, nullptr, nullptr };
255     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
256     if ((argc != expectedArgc) && (argc != expectedArgc - 1)) {
257         LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
258         return false;
259     }
260     ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
261 
262     NapiVerify *napiVerify = nullptr;
263     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiVerify));
264     if (status != napi_ok || napiVerify == nullptr) {
265         LOGE("failed to unwrap napi verify obj.");
266         return false;
267     }
268 
269     HcfBlob *data = nullptr;
270     HcfBlob *signatureData = nullptr;
271     if (!GetDataBlobAndSignatureFromInput(env, argv[PARAM0], argv[PARAM1], &data, &signatureData)) {
272         return false;
273     }
274 
275     ctx->verify = napiVerify->GetVerify();
276     ctx->data = data;
277     ctx->signatureData = signatureData;
278 
279     if (ctx->asyncType == ASYNC_PROMISE) {
280         napi_create_promise(env, &ctx->deferred, &ctx->promise);
281         return true;
282     } else {
283         return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
284     }
285 }
286 
ReturnInitCallbackResult(napi_env env,VerifyInitCtx * ctx,napi_value result)287 static void ReturnInitCallbackResult(napi_env env, VerifyInitCtx *ctx, napi_value result)
288 {
289     napi_value businessError = nullptr;
290     if (ctx->errCode != HCF_SUCCESS) {
291         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
292     }
293 
294     napi_value params[ARGS_SIZE_ONE] = { businessError };
295 
296     napi_value func = nullptr;
297     napi_get_reference_value(env, ctx->callback, &func);
298 
299     napi_value recv = nullptr;
300     napi_value callFuncRet = nullptr;
301     napi_get_undefined(env, &recv);
302     napi_call_function(env, recv, func, ARGS_SIZE_ONE, params, &callFuncRet);
303 }
304 
ReturnInitPromiseResult(napi_env env,VerifyInitCtx * ctx,napi_value result)305 static void ReturnInitPromiseResult(napi_env env, VerifyInitCtx *ctx, napi_value result)
306 {
307     if (ctx->errCode == HCF_SUCCESS) {
308         napi_resolve_deferred(env, ctx->deferred, result);
309     } else {
310         napi_reject_deferred(env, ctx->deferred,
311             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
312     }
313 }
314 
ReturnUpdateCallbackResult(napi_env env,VerifyUpdateCtx * ctx,napi_value result)315 static void ReturnUpdateCallbackResult(napi_env env, VerifyUpdateCtx *ctx, napi_value result)
316 {
317     napi_value businessError = nullptr;
318     if (ctx->errCode != HCF_SUCCESS) {
319         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
320     }
321 
322     napi_value params[ARGS_SIZE_ONE] = { businessError };
323 
324     napi_value func = nullptr;
325     napi_get_reference_value(env, ctx->callback, &func);
326 
327     napi_value recv = nullptr;
328     napi_value callFuncRet = nullptr;
329     napi_get_undefined(env, &recv);
330     napi_call_function(env, recv, func, ARGS_SIZE_ONE, params, &callFuncRet);
331 }
332 
ReturnUpdatePromiseResult(napi_env env,VerifyUpdateCtx * ctx,napi_value result)333 static void ReturnUpdatePromiseResult(napi_env env, VerifyUpdateCtx *ctx, napi_value result)
334 {
335     if (ctx->errCode == HCF_SUCCESS) {
336         napi_resolve_deferred(env, ctx->deferred, result);
337     } else {
338         napi_reject_deferred(env, ctx->deferred,
339             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
340     }
341 }
342 
ReturnDoFinalCallbackResult(napi_env env,VerifyDoFinalCtx * ctx,napi_value result)343 static void ReturnDoFinalCallbackResult(napi_env env, VerifyDoFinalCtx *ctx, napi_value result)
344 {
345     napi_value businessError = nullptr;
346     if (ctx->errCode != HCF_SUCCESS) {
347         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
348     }
349 
350     napi_value params[ARGS_SIZE_TWO] = { businessError, result };
351 
352     napi_value func = nullptr;
353     napi_get_reference_value(env, ctx->callback, &func);
354 
355     napi_value recv = nullptr;
356     napi_value callFuncRet = nullptr;
357     napi_get_undefined(env, &recv);
358     napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
359 }
360 
ReturnDoFinalPromiseResult(napi_env env,VerifyDoFinalCtx * ctx,napi_value result)361 static void ReturnDoFinalPromiseResult(napi_env env, VerifyDoFinalCtx *ctx, napi_value result)
362 {
363     if (ctx->errCode == HCF_SUCCESS) {
364         napi_resolve_deferred(env, ctx->deferred, result);
365     } else {
366         napi_reject_deferred(env, ctx->deferred,
367             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
368     }
369 }
370 
VerifyJsInitAsyncWorkProcess(napi_env env,void * data)371 void VerifyJsInitAsyncWorkProcess(napi_env env, void *data)
372 {
373     VerifyInitCtx *ctx = static_cast<VerifyInitCtx *>(data);
374 
375     ctx->errCode = ctx->verify->init(ctx->verify, ctx->params, ctx->pubKey);
376     if (ctx->errCode != HCF_SUCCESS) {
377         LOGE("verify init fail.");
378         ctx->errMsg = "verify init fail.";
379     }
380 }
381 
VerifyJsInitAsyncWorkReturn(napi_env env,napi_status status,void * data)382 void VerifyJsInitAsyncWorkReturn(napi_env env, napi_status status, void *data)
383 {
384     VerifyInitCtx *ctx = static_cast<VerifyInitCtx *>(data);
385 
386     if (ctx->asyncType == ASYNC_CALLBACK) {
387         ReturnInitCallbackResult(env, ctx, NapiGetNull(env));
388     } else {
389         ReturnInitPromiseResult(env, ctx, NapiGetNull(env));
390     }
391     FreeVerifyInitCtx(env, ctx);
392 }
393 
VerifyJsUpdateAsyncWorkProcess(napi_env env,void * data)394 void VerifyJsUpdateAsyncWorkProcess(napi_env env, void *data)
395 {
396     VerifyUpdateCtx *ctx = static_cast<VerifyUpdateCtx *>(data);
397 
398     ctx->errCode = ctx->verify->update(ctx->verify, ctx->data);
399     if (ctx->errCode != HCF_SUCCESS) {
400         LOGE("verify update fail.");
401         ctx->errMsg = "verify update fail.";
402     }
403 }
404 
VerifyJsUpdateAsyncWorkReturn(napi_env env,napi_status status,void * data)405 void VerifyJsUpdateAsyncWorkReturn(napi_env env, napi_status status, void *data)
406 {
407     VerifyUpdateCtx *ctx = static_cast<VerifyUpdateCtx *>(data);
408 
409     if (ctx->asyncType == ASYNC_CALLBACK) {
410         ReturnUpdateCallbackResult(env, ctx, NapiGetNull(env));
411     } else {
412         ReturnUpdatePromiseResult(env, ctx, NapiGetNull(env));
413     }
414     FreeVerifyUpdateCtx(env, ctx);
415 }
416 
VerifyJsDoFinalAsyncWorkProcess(napi_env env,void * data)417 void VerifyJsDoFinalAsyncWorkProcess(napi_env env, void *data)
418 {
419     VerifyDoFinalCtx *ctx = static_cast<VerifyDoFinalCtx *>(data);
420 
421     ctx->isVerifySucc = ctx->verify->verify(ctx->verify, ctx->data, ctx->signatureData);
422     ctx->errCode = HCF_SUCCESS;
423     if (!ctx->isVerifySucc) {
424         LOGE("verify doFinal fail.");
425         return;
426     }
427 }
428 
VerifyJsDoFinalAsyncWorkReturn(napi_env env,napi_status status,void * data)429 void VerifyJsDoFinalAsyncWorkReturn(napi_env env, napi_status status, void *data)
430 {
431     VerifyDoFinalCtx *ctx = static_cast<VerifyDoFinalCtx *>(data);
432 
433     napi_value result = nullptr;
434     if (ctx->errCode == HCF_SUCCESS) {
435         napi_get_boolean(env, ctx->isVerifySucc, &result);
436     }
437 
438     if (ctx->asyncType == ASYNC_CALLBACK) {
439         ReturnDoFinalCallbackResult(env, ctx, result);
440     } else {
441         ReturnDoFinalPromiseResult(env, ctx, result);
442     }
443     FreeVerifyDoFinalCtx(env, ctx);
444 }
445 
NewVerifyJsInitAsyncWork(napi_env env,VerifyInitCtx * ctx)446 static napi_value NewVerifyJsInitAsyncWork(napi_env env, VerifyInitCtx *ctx)
447 {
448     napi_value resourceName = nullptr;
449     napi_create_string_utf8(env, "init", NAPI_AUTO_LENGTH, &resourceName);
450 
451     napi_create_async_work(
452         env, nullptr, resourceName,
453         [](napi_env env, void *data) {
454             VerifyJsInitAsyncWorkProcess(env, data);
455             return;
456         },
457         [](napi_env env, napi_status status, void *data) {
458             VerifyJsInitAsyncWorkReturn(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 
NewVerifyJsUpdateAsyncWork(napi_env env,VerifyUpdateCtx * ctx)472 static napi_value NewVerifyJsUpdateAsyncWork(napi_env env, VerifyUpdateCtx *ctx)
473 {
474     napi_value resourceName = nullptr;
475     napi_create_string_utf8(env, "update", NAPI_AUTO_LENGTH, &resourceName);
476 
477     napi_create_async_work(
478         env, nullptr, resourceName,
479         [](napi_env env, void *data) {
480             VerifyJsUpdateAsyncWorkProcess(env, data);
481             return;
482         },
483         [](napi_env env, napi_status status, void *data) {
484             VerifyJsUpdateAsyncWorkReturn(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 
NewVerifyJsDoFinalAsyncWork(napi_env env,VerifyDoFinalCtx * ctx)498 static napi_value NewVerifyJsDoFinalAsyncWork(napi_env env, VerifyDoFinalCtx *ctx)
499 {
500     napi_value resourceName = nullptr;
501     napi_create_string_utf8(env, "verify", NAPI_AUTO_LENGTH, &resourceName);
502 
503     napi_create_async_work(
504         env, nullptr, resourceName,
505         [](napi_env env, void *data) {
506             VerifyJsDoFinalAsyncWorkProcess(env, data);
507             return;
508         },
509         [](napi_env env, napi_status status, void *data) {
510             VerifyJsDoFinalAsyncWorkReturn(env, status, data);
511             return;
512         },
513         static_cast<void *>(ctx),
514         &ctx->asyncWork);
515 
516     napi_queue_async_work(env, ctx->asyncWork);
517     if (ctx->asyncType == ASYNC_PROMISE) {
518         return ctx->promise;
519     } else {
520         return NapiGetNull(env);
521     }
522 }
523 
NapiVerify(HcfVerify * verify)524 NapiVerify::NapiVerify(HcfVerify *verify)
525 {
526     this->verify_ = verify;
527 }
528 
~NapiVerify()529 NapiVerify::~NapiVerify()
530 {
531     HcfObjDestroy(this->verify_);
532 }
533 
GetVerify()534 HcfVerify *NapiVerify::GetVerify()
535 {
536     return this->verify_;
537 }
538 
JsInit(napi_env env,napi_callback_info info)539 napi_value NapiVerify::JsInit(napi_env env, napi_callback_info info)
540 {
541     VerifyInitCtx *ctx = static_cast<VerifyInitCtx *>(HcfMalloc(sizeof(VerifyInitCtx), 0));
542     if (ctx == nullptr) {
543         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
544         LOGE("create context fail.");
545         return nullptr;
546     }
547 
548     if (!BuildVerifyJsInitCtx(env, info, ctx)) {
549         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
550         LOGE("build context fail.");
551         FreeVerifyInitCtx(env, ctx);
552         return nullptr;
553     }
554 
555     return NewVerifyJsInitAsyncWork(env, ctx);
556 }
557 
JsUpdate(napi_env env,napi_callback_info info)558 napi_value NapiVerify::JsUpdate(napi_env env, napi_callback_info info)
559 {
560     VerifyUpdateCtx *ctx = static_cast<VerifyUpdateCtx *>(HcfMalloc(sizeof(VerifyUpdateCtx), 0));
561     if (ctx == nullptr) {
562         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
563         LOGE("create context fail.");
564         return nullptr;
565     }
566 
567     if (!BuildVerifyJsUpdateCtx(env, info, ctx)) {
568         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
569         LOGE("build context fail.");
570         FreeVerifyUpdateCtx(env, ctx);
571         return nullptr;
572     }
573 
574     return NewVerifyJsUpdateAsyncWork(env, ctx);
575 }
576 
JsVerify(napi_env env,napi_callback_info info)577 napi_value NapiVerify::JsVerify(napi_env env, napi_callback_info info)
578 {
579     VerifyDoFinalCtx *ctx = static_cast<VerifyDoFinalCtx *>(HcfMalloc(sizeof(VerifyDoFinalCtx), 0));
580     if (ctx == nullptr) {
581         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
582         LOGE("create context fail.");
583         return nullptr;
584     }
585 
586     if (!BuildVerifyJsDoFinalCtx(env, info, ctx)) {
587         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
588         LOGE("build context fail.");
589         FreeVerifyDoFinalCtx(env, ctx);
590         return nullptr;
591     }
592 
593     return NewVerifyJsDoFinalAsyncWork(env, ctx);
594 }
595 
VerifyConstructor(napi_env env,napi_callback_info info)596 napi_value NapiVerify::VerifyConstructor(napi_env env, napi_callback_info info)
597 {
598     napi_value thisVar = nullptr;
599     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
600     return thisVar;
601 }
602 
NapiWrapVerify(napi_env env,napi_value instance,NapiVerify * napiVerify)603 static napi_value NapiWrapVerify(napi_env env, napi_value instance, NapiVerify *napiVerify)
604 {
605     napi_status status = napi_wrap(
606         env, instance, napiVerify,
607         [](napi_env env, void *data, void *hint) {
608             NapiVerify *napiVerify = static_cast<NapiVerify *>(data);
609             delete napiVerify;
610             return;
611         }, nullptr, nullptr);
612     if (status != napi_ok) {
613         LOGE("failed to wrap napiVerify obj!");
614         delete napiVerify;
615         napiVerify = nullptr;
616         return nullptr;
617     }
618     return instance;
619 }
620 
CreateJsVerify(napi_env env,napi_callback_info info)621 napi_value NapiVerify::CreateJsVerify(napi_env env, napi_callback_info info)
622 {
623     size_t expectedArgc = PARAMS_NUM_ONE;
624     size_t argc = expectedArgc;
625     napi_value argv[PARAMS_NUM_ONE] = { nullptr };
626     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
627 
628     if (argc != expectedArgc) {
629         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
630         LOGE("The input args num is invalid.");
631         return nullptr;
632     }
633 
634     napi_value instance;
635     napi_value constructor = nullptr;
636     napi_get_reference_value(env, classRef_, &constructor);
637     napi_new_instance(env, constructor, argc, argv, &instance);
638 
639     std::string algName;
640     if (!GetStringFromJSParams(env, argv[0], algName)) {
641         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get algoName."));
642         LOGE("failed to get algoName.");
643         return nullptr;
644     }
645 
646     HcfVerify *verify = nullptr;
647     HcfResult res = HcfVerifyCreate(algName.c_str(), &verify);
648     if (res != HCF_SUCCESS) {
649         napi_throw(env, GenerateBusinessError(env, res, "create c verify fail."));
650         LOGE("create c verify fail.");
651         return nullptr;
652     }
653 
654     NapiVerify *napiVerify = new (std::nothrow) NapiVerify(verify);
655     if (napiVerify == nullptr) {
656         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi verify failed"));
657         LOGE("new napi verify failed");
658         HcfObjDestroy(verify);
659         return nullptr;
660     }
661 
662     napi_value napiAlgName = nullptr;
663     napi_create_string_utf8(env, algName.c_str(), NAPI_AUTO_LENGTH, &napiAlgName);
664     napi_set_named_property(env, instance, CRYPTO_TAG_ALG_NAME.c_str(), napiAlgName);
665 
666     return NapiWrapVerify(env, instance, napiVerify);
667 }
668 
669 // verify setVerifySpec(itemType :VerifySpecItem, itemValue : number)
JsSetVerifySpec(napi_env env,napi_callback_info info)670 napi_value NapiVerify::JsSetVerifySpec(napi_env env, napi_callback_info info)
671 {
672     napi_value thisVar = nullptr;
673     NapiVerify *napiVerify = nullptr;
674     size_t expectedArgc = ARGS_SIZE_TWO;
675     size_t argc = ARGS_SIZE_TWO;
676     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
677     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
678     if (argc != expectedArgc) {
679         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "init failed for wrong argument num."));
680         LOGE("wrong argument num. require 2 arguments. [Argc]: %zu!", argc);
681         return nullptr;
682     }
683     SignSpecItem item;
684     if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
685         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get signSpecItem failed!"));
686         LOGE("get signspecitem failed!");
687         return nullptr;
688     }
689     int32_t saltLen;
690     if (napi_get_value_int32(env, argv[1], &saltLen) != napi_ok) {
691         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get VerifySpec saltLen failed!"));
692         LOGE("get VerifySpec saltLen failed!");
693         return nullptr;
694     }
695     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiVerify));
696     if (status != napi_ok || napiVerify == nullptr) {
697         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiVerify obj!"));
698         LOGE("failed to unwrap napiVerify obj!");
699         return nullptr;
700     }
701     HcfVerify *verify = napiVerify->GetVerify();
702     HcfResult res = verify->setVerifySpecInt(verify, item, saltLen);
703     if (res != HCF_SUCCESS) {
704         napi_throw(env, GenerateBusinessError(env, res, "c setVerifySpecNumber fail."));
705         LOGE("c setVerifySpecNumber fail.");
706         return nullptr;
707     }
708     return thisVar;
709 }
710 
GetVerifySpecString(napi_env env,SignSpecItem item,HcfVerify * verify)711 static napi_value GetVerifySpecString(napi_env env, SignSpecItem item, HcfVerify *verify)
712 {
713     char *returnString = nullptr;
714     HcfResult res = verify->getVerifySpecString(verify, item, &returnString);
715     if (res != HCF_SUCCESS) {
716         napi_throw(env, GenerateBusinessError(env, res, "C getVerifySpecString failed."));
717         LOGE("c getVerifySpecString fail.");
718         return nullptr;
719     }
720 
721     napi_value instance = nullptr;
722     napi_create_string_utf8(env, returnString, NAPI_AUTO_LENGTH, &instance);
723     HcfFree(returnString);
724     return instance;
725 }
726 
GetVerifySpecNumber(napi_env env,SignSpecItem item,HcfVerify * verify)727 static napi_value GetVerifySpecNumber(napi_env env, SignSpecItem item, HcfVerify *verify)
728 {
729     int returnInt;
730     HcfResult res = verify->getVerifySpecInt(verify, item, &returnInt);
731     if (res != HCF_SUCCESS) {
732         napi_throw(env, GenerateBusinessError(env, res, "C getVerifySpecInt failed."));
733         LOGE("c getVerifySpecInt fail.");
734         return nullptr;
735     }
736 
737     napi_value instance = nullptr;
738     napi_create_int32(env, returnInt, &instance);
739     return instance;
740 }
741 
JsGetVerifySpec(napi_env env,napi_callback_info info)742 napi_value NapiVerify::JsGetVerifySpec(napi_env env, napi_callback_info info)
743 {
744     napi_value thisVar = nullptr;
745     NapiVerify *napiVerify = nullptr;
746     size_t expectedArgc = ARGS_SIZE_ONE;
747     size_t argc = ARGS_SIZE_ONE;
748     napi_value argv[ARGS_SIZE_ONE] = { nullptr };
749     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
750     if (argc != expectedArgc) {
751         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "init failed for wrong argument num."));
752         LOGE("wrong argument num. require 1 arguments. [Argc]: %zu!", argc);
753         return nullptr;
754     }
755     SignSpecItem item;
756     if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
757         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get getVerifySpecString failed!"));
758         LOGE("get getVerifySpecString failed!");
759         return nullptr;
760     }
761 
762     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiVerify));
763     if (status != napi_ok || napiVerify == nullptr) {
764         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiVerify obj!"));
765         LOGE("failed to unwrap napiVerify obj!");
766         return nullptr;
767     }
768     HcfVerify *verify = napiVerify->GetVerify();
769     if (verify == nullptr) {
770         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get verify obj!"));
771         LOGE("failed to get verfiy obj!");
772         return nullptr;
773     }
774 
775     int32_t type = GetSignSpecType(item);
776     if (type == SPEC_ITEM_TYPE_STR) {
777         return GetVerifySpecString(env, item, verify);
778     } else if (type == SPEC_ITEM_TYPE_NUM) {
779         return GetVerifySpecNumber(env, item, verify);
780     } else {
781         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "VerifySpecItem not support!"));
782         return nullptr;
783     }
784 }
785 
DefineVerifyJSClass(napi_env env,napi_value exports)786 void NapiVerify::DefineVerifyJSClass(napi_env env, napi_value exports)
787 {
788     napi_property_descriptor desc[] = {
789         DECLARE_NAPI_FUNCTION("createVerify", NapiVerify::CreateJsVerify),
790     };
791     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
792 
793     napi_property_descriptor classDesc[] = {
794         DECLARE_NAPI_FUNCTION("init", NapiVerify::JsInit),
795         DECLARE_NAPI_FUNCTION("update", NapiVerify::JsUpdate),
796         DECLARE_NAPI_FUNCTION("verify", NapiVerify::JsVerify),
797         DECLARE_NAPI_FUNCTION("setVerifySpec", NapiVerify::JsSetVerifySpec),
798         DECLARE_NAPI_FUNCTION("getVerifySpec", NapiVerify::JsGetVerifySpec),
799     };
800     napi_value constructor = nullptr;
801     napi_define_class(env, "Verify", NAPI_AUTO_LENGTH, NapiVerify::VerifyConstructor, nullptr,
802         sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
803     napi_create_reference(env, constructor, 1, &classRef_);
804 }
805 } // CryptoFramework
806 } // OHOS
807