• 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 = GetBlobFromNapiDataBlob(env, argv[index]);
207     if (blob == nullptr) {
208         LOGE("failed to get blob data from napi.");
209         return false;
210     }
211 
212     ctx->verify = napiVerify->GetVerify();
213     ctx->data = blob;
214 
215     if (ctx->asyncType == ASYNC_PROMISE) {
216         napi_create_promise(env, &ctx->deferred, &ctx->promise);
217         return true;
218     } else {
219         return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
220     }
221 }
222 
GetDataBlobAndSignatureFromInput(napi_env env,napi_value dataValue,napi_value signatureDataValue,HcfBlob ** returnData,HcfBlob ** returnSignatureData)223 static bool GetDataBlobAndSignatureFromInput(napi_env env, napi_value dataValue, napi_value signatureDataValue,
224     HcfBlob **returnData, HcfBlob **returnSignatureData)
225 {
226     napi_valuetype valueType;
227     napi_typeof(env, dataValue, &valueType);
228     HcfBlob *data = nullptr;
229     if (valueType != napi_null) {
230         data = GetBlobFromNapiDataBlob(env, dataValue);
231         if (data == nullptr) {
232             LOGE("failed to get data.");
233             return false;
234         }
235     }
236 
237     HcfBlob *signatureData = GetBlobFromNapiDataBlob(env, signatureDataValue);
238     if (signatureData == nullptr) {
239         LOGE("failed to get signature.");
240         HcfBlobDataFree(data);
241         HcfFree(data);
242         return false;
243     }
244 
245     *returnData = data;
246     *returnSignatureData = signatureData;
247     return true;
248 }
249 
BuildVerifyJsDoFinalCtx(napi_env env,napi_callback_info info,VerifyDoFinalCtx * ctx)250 static bool BuildVerifyJsDoFinalCtx(napi_env env, napi_callback_info info, VerifyDoFinalCtx *ctx)
251 {
252     napi_value thisVar = nullptr;
253     size_t expectedArgc = PARAMS_NUM_THREE;
254     size_t argc = expectedArgc;
255     napi_value argv[PARAMS_NUM_THREE] = { nullptr, nullptr, nullptr };
256     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
257     if ((argc != expectedArgc) && (argc != expectedArgc - 1)) {
258         LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
259         return false;
260     }
261     ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
262 
263     NapiVerify *napiVerify = nullptr;
264     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiVerify));
265     if (status != napi_ok || napiVerify == nullptr) {
266         LOGE("failed to unwrap napi verify obj.");
267         return false;
268     }
269 
270     HcfBlob *data = nullptr;
271     HcfBlob *signatureData = nullptr;
272     if (!GetDataBlobAndSignatureFromInput(env, argv[PARAM0], argv[PARAM1], &data, &signatureData)) {
273         return false;
274     }
275 
276     ctx->verify = napiVerify->GetVerify();
277     ctx->data = data;
278     ctx->signatureData = signatureData;
279 
280     if (ctx->asyncType == ASYNC_PROMISE) {
281         napi_create_promise(env, &ctx->deferred, &ctx->promise);
282         return true;
283     } else {
284         return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
285     }
286 }
287 
ReturnInitCallbackResult(napi_env env,VerifyInitCtx * ctx,napi_value result)288 static void ReturnInitCallbackResult(napi_env env, VerifyInitCtx *ctx, napi_value result)
289 {
290     napi_value businessError = nullptr;
291     if (ctx->errCode != HCF_SUCCESS) {
292         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
293     }
294 
295     napi_value params[ARGS_SIZE_ONE] = { businessError };
296 
297     napi_value func = nullptr;
298     napi_get_reference_value(env, ctx->callback, &func);
299 
300     napi_value recv = nullptr;
301     napi_value callFuncRet = nullptr;
302     napi_get_undefined(env, &recv);
303     napi_call_function(env, recv, func, ARGS_SIZE_ONE, params, &callFuncRet);
304 }
305 
ReturnInitPromiseResult(napi_env env,VerifyInitCtx * ctx,napi_value result)306 static void ReturnInitPromiseResult(napi_env env, VerifyInitCtx *ctx, napi_value result)
307 {
308     if (ctx->errCode == HCF_SUCCESS) {
309         napi_resolve_deferred(env, ctx->deferred, result);
310     } else {
311         napi_reject_deferred(env, ctx->deferred,
312             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
313     }
314 }
315 
ReturnUpdateCallbackResult(napi_env env,VerifyUpdateCtx * ctx,napi_value result)316 static void ReturnUpdateCallbackResult(napi_env env, VerifyUpdateCtx *ctx, napi_value result)
317 {
318     napi_value businessError = nullptr;
319     if (ctx->errCode != HCF_SUCCESS) {
320         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
321     }
322 
323     napi_value params[ARGS_SIZE_ONE] = { businessError };
324 
325     napi_value func = nullptr;
326     napi_get_reference_value(env, ctx->callback, &func);
327 
328     napi_value recv = nullptr;
329     napi_value callFuncRet = nullptr;
330     napi_get_undefined(env, &recv);
331     napi_call_function(env, recv, func, ARGS_SIZE_ONE, params, &callFuncRet);
332 }
333 
ReturnUpdatePromiseResult(napi_env env,VerifyUpdateCtx * ctx,napi_value result)334 static void ReturnUpdatePromiseResult(napi_env env, VerifyUpdateCtx *ctx, napi_value result)
335 {
336     if (ctx->errCode == HCF_SUCCESS) {
337         napi_resolve_deferred(env, ctx->deferred, result);
338     } else {
339         napi_reject_deferred(env, ctx->deferred,
340             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
341     }
342 }
343 
ReturnDoFinalCallbackResult(napi_env env,VerifyDoFinalCtx * ctx,napi_value result)344 static void ReturnDoFinalCallbackResult(napi_env env, VerifyDoFinalCtx *ctx, napi_value result)
345 {
346     napi_value businessError = nullptr;
347     if (ctx->errCode != HCF_SUCCESS) {
348         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
349     }
350 
351     napi_value params[ARGS_SIZE_TWO] = { businessError, result };
352 
353     napi_value func = nullptr;
354     napi_get_reference_value(env, ctx->callback, &func);
355 
356     napi_value recv = nullptr;
357     napi_value callFuncRet = nullptr;
358     napi_get_undefined(env, &recv);
359     napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
360 }
361 
ReturnDoFinalPromiseResult(napi_env env,VerifyDoFinalCtx * ctx,napi_value result)362 static void ReturnDoFinalPromiseResult(napi_env env, VerifyDoFinalCtx *ctx, napi_value result)
363 {
364     if (ctx->errCode == HCF_SUCCESS) {
365         napi_resolve_deferred(env, ctx->deferred, result);
366     } else {
367         napi_reject_deferred(env, ctx->deferred,
368             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
369     }
370 }
371 
VerifyJsInitAsyncWorkProcess(napi_env env,void * data)372 static void VerifyJsInitAsyncWorkProcess(napi_env env, void *data)
373 {
374     VerifyInitCtx *ctx = static_cast<VerifyInitCtx *>(data);
375 
376     ctx->errCode = ctx->verify->init(ctx->verify, ctx->params, ctx->pubKey);
377     if (ctx->errCode != HCF_SUCCESS) {
378         LOGD("[error] verify init fail.");
379         ctx->errMsg = "verify init fail.";
380     }
381 }
382 
VerifyJsInitAsyncWorkReturn(napi_env env,napi_status status,void * data)383 static void VerifyJsInitAsyncWorkReturn(napi_env env, napi_status status, void *data)
384 {
385     VerifyInitCtx *ctx = static_cast<VerifyInitCtx *>(data);
386 
387     if (ctx->asyncType == ASYNC_CALLBACK) {
388         ReturnInitCallbackResult(env, ctx, NapiGetNull(env));
389     } else {
390         ReturnInitPromiseResult(env, ctx, NapiGetNull(env));
391     }
392     FreeVerifyInitCtx(env, ctx);
393 }
394 
VerifyJsUpdateAsyncWorkProcess(napi_env env,void * data)395 static void VerifyJsUpdateAsyncWorkProcess(napi_env env, void *data)
396 {
397     VerifyUpdateCtx *ctx = static_cast<VerifyUpdateCtx *>(data);
398 
399     ctx->errCode = ctx->verify->update(ctx->verify, ctx->data);
400     if (ctx->errCode != HCF_SUCCESS) {
401         LOGD("[error] verify update fail.");
402         ctx->errMsg = "verify update fail.";
403     }
404 }
405 
VerifyJsUpdateAsyncWorkReturn(napi_env env,napi_status status,void * data)406 static void VerifyJsUpdateAsyncWorkReturn(napi_env env, napi_status status, void *data)
407 {
408     VerifyUpdateCtx *ctx = static_cast<VerifyUpdateCtx *>(data);
409 
410     if (ctx->asyncType == ASYNC_CALLBACK) {
411         ReturnUpdateCallbackResult(env, ctx, NapiGetNull(env));
412     } else {
413         ReturnUpdatePromiseResult(env, ctx, NapiGetNull(env));
414     }
415     FreeVerifyUpdateCtx(env, ctx);
416 }
417 
VerifyJsDoFinalAsyncWorkProcess(napi_env env,void * data)418 static void VerifyJsDoFinalAsyncWorkProcess(napi_env env, void *data)
419 {
420     VerifyDoFinalCtx *ctx = static_cast<VerifyDoFinalCtx *>(data);
421 
422     ctx->isVerifySucc = ctx->verify->verify(ctx->verify, ctx->data, ctx->signatureData);
423     ctx->errCode = HCF_SUCCESS;
424     if (!ctx->isVerifySucc) {
425         LOGD("[error] verify doFinal fail.");
426         return;
427     }
428 }
429 
VerifyJsDoFinalAsyncWorkReturn(napi_env env,napi_status status,void * data)430 static void VerifyJsDoFinalAsyncWorkReturn(napi_env env, napi_status status, void *data)
431 {
432     VerifyDoFinalCtx *ctx = static_cast<VerifyDoFinalCtx *>(data);
433 
434     napi_value result = nullptr;
435     if (ctx->errCode == HCF_SUCCESS) {
436         napi_get_boolean(env, ctx->isVerifySucc, &result);
437     }
438 
439     if (ctx->asyncType == ASYNC_CALLBACK) {
440         ReturnDoFinalCallbackResult(env, ctx, result);
441     } else {
442         ReturnDoFinalPromiseResult(env, ctx, result);
443     }
444     FreeVerifyDoFinalCtx(env, ctx);
445 }
446 
NewVerifyJsInitAsyncWork(napi_env env,VerifyInitCtx * ctx)447 static napi_value NewVerifyJsInitAsyncWork(napi_env env, VerifyInitCtx *ctx)
448 {
449     napi_value resourceName = nullptr;
450     napi_create_string_utf8(env, "init", NAPI_AUTO_LENGTH, &resourceName);
451 
452     napi_create_async_work(
453         env, nullptr, resourceName,
454         [](napi_env env, void *data) {
455             VerifyJsInitAsyncWorkProcess(env, data);
456             return;
457         },
458         [](napi_env env, napi_status status, void *data) {
459             VerifyJsInitAsyncWorkReturn(env, status, data);
460             return;
461         },
462         static_cast<void *>(ctx),
463         &ctx->asyncWork);
464 
465     napi_queue_async_work(env, ctx->asyncWork);
466     if (ctx->asyncType == ASYNC_PROMISE) {
467         return ctx->promise;
468     } else {
469         return NapiGetNull(env);
470     }
471 }
472 
NewVerifyJsUpdateAsyncWork(napi_env env,VerifyUpdateCtx * ctx)473 static napi_value NewVerifyJsUpdateAsyncWork(napi_env env, VerifyUpdateCtx *ctx)
474 {
475     napi_value resourceName = nullptr;
476     napi_create_string_utf8(env, "update", NAPI_AUTO_LENGTH, &resourceName);
477 
478     napi_create_async_work(
479         env, nullptr, resourceName,
480         [](napi_env env, void *data) {
481             VerifyJsUpdateAsyncWorkProcess(env, data);
482             return;
483         },
484         [](napi_env env, napi_status status, void *data) {
485             VerifyJsUpdateAsyncWorkReturn(env, status, data);
486             return;
487         },
488         static_cast<void *>(ctx),
489         &ctx->asyncWork);
490 
491     napi_queue_async_work(env, ctx->asyncWork);
492     if (ctx->asyncType == ASYNC_PROMISE) {
493         return ctx->promise;
494     } else {
495         return NapiGetNull(env);
496     }
497 }
498 
NewVerifyJsDoFinalAsyncWork(napi_env env,VerifyDoFinalCtx * ctx)499 static napi_value NewVerifyJsDoFinalAsyncWork(napi_env env, VerifyDoFinalCtx *ctx)
500 {
501     napi_value resourceName = nullptr;
502     napi_create_string_utf8(env, "verify", NAPI_AUTO_LENGTH, &resourceName);
503 
504     napi_create_async_work(
505         env, nullptr, resourceName,
506         [](napi_env env, void *data) {
507             VerifyJsDoFinalAsyncWorkProcess(env, data);
508             return;
509         },
510         [](napi_env env, napi_status status, void *data) {
511             VerifyJsDoFinalAsyncWorkReturn(env, status, data);
512             return;
513         },
514         static_cast<void *>(ctx),
515         &ctx->asyncWork);
516 
517     napi_queue_async_work(env, ctx->asyncWork);
518     if (ctx->asyncType == ASYNC_PROMISE) {
519         return ctx->promise;
520     } else {
521         return NapiGetNull(env);
522     }
523 }
524 
NapiVerify(HcfVerify * verify)525 NapiVerify::NapiVerify(HcfVerify *verify)
526 {
527     this->verify_ = verify;
528 }
529 
~NapiVerify()530 NapiVerify::~NapiVerify()
531 {
532     HcfObjDestroy(this->verify_);
533 }
534 
GetVerify()535 HcfVerify *NapiVerify::GetVerify()
536 {
537     return this->verify_;
538 }
539 
JsInit(napi_env env,napi_callback_info info)540 napi_value NapiVerify::JsInit(napi_env env, napi_callback_info info)
541 {
542     VerifyInitCtx *ctx = static_cast<VerifyInitCtx *>(HcfMalloc(sizeof(VerifyInitCtx), 0));
543     if (ctx == nullptr) {
544         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
545         LOGE("create context fail.");
546         return nullptr;
547     }
548 
549     if (!BuildVerifyJsInitCtx(env, info, ctx)) {
550         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
551         LOGE("build context fail.");
552         FreeVerifyInitCtx(env, ctx);
553         return nullptr;
554     }
555 
556     return NewVerifyJsInitAsyncWork(env, ctx);
557 }
558 
JsUpdate(napi_env env,napi_callback_info info)559 napi_value NapiVerify::JsUpdate(napi_env env, napi_callback_info info)
560 {
561     VerifyUpdateCtx *ctx = static_cast<VerifyUpdateCtx *>(HcfMalloc(sizeof(VerifyUpdateCtx), 0));
562     if (ctx == nullptr) {
563         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
564         LOGE("create context fail.");
565         return nullptr;
566     }
567 
568     if (!BuildVerifyJsUpdateCtx(env, info, ctx)) {
569         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
570         LOGE("build context fail.");
571         FreeVerifyUpdateCtx(env, ctx);
572         return nullptr;
573     }
574 
575     return NewVerifyJsUpdateAsyncWork(env, ctx);
576 }
577 
JsVerify(napi_env env,napi_callback_info info)578 napi_value NapiVerify::JsVerify(napi_env env, napi_callback_info info)
579 {
580     VerifyDoFinalCtx *ctx = static_cast<VerifyDoFinalCtx *>(HcfMalloc(sizeof(VerifyDoFinalCtx), 0));
581     if (ctx == nullptr) {
582         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail."));
583         LOGE("create context fail.");
584         return nullptr;
585     }
586 
587     if (!BuildVerifyJsDoFinalCtx(env, info, ctx)) {
588         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
589         LOGE("build context fail.");
590         FreeVerifyDoFinalCtx(env, ctx);
591         return nullptr;
592     }
593 
594     return NewVerifyJsDoFinalAsyncWork(env, ctx);
595 }
596 
VerifyConstructor(napi_env env,napi_callback_info info)597 napi_value NapiVerify::VerifyConstructor(napi_env env, napi_callback_info info)
598 {
599     napi_value thisVar = nullptr;
600     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
601     return thisVar;
602 }
603 
NapiWrapVerify(napi_env env,napi_value instance,NapiVerify * napiVerify)604 static napi_value NapiWrapVerify(napi_env env, napi_value instance, NapiVerify *napiVerify)
605 {
606     napi_status status = napi_wrap(
607         env, instance, napiVerify,
608         [](napi_env env, void *data, void *hint) {
609             NapiVerify *napiVerify = static_cast<NapiVerify *>(data);
610             delete napiVerify;
611             return;
612         }, nullptr, nullptr);
613     if (status != napi_ok) {
614         LOGE("failed to wrap napiVerify obj!");
615         delete napiVerify;
616         napiVerify = nullptr;
617         return nullptr;
618     }
619     return instance;
620 }
621 
CreateJsVerify(napi_env env,napi_callback_info info)622 napi_value NapiVerify::CreateJsVerify(napi_env env, napi_callback_info info)
623 {
624     LOGD("Enter CreateJsVerify...");
625     size_t expectedArgc = PARAMS_NUM_ONE;
626     size_t argc = expectedArgc;
627     napi_value argv[PARAMS_NUM_ONE] = { nullptr };
628     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
629 
630     if (argc != expectedArgc) {
631         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
632         LOGE("The input args num is invalid.");
633         return nullptr;
634     }
635 
636     napi_value instance;
637     napi_value constructor = nullptr;
638     napi_get_reference_value(env, classRef_, &constructor);
639     napi_new_instance(env, constructor, argc, argv, &instance);
640 
641     std::string algName;
642     if (!GetStringFromJSParams(env, argv[0], algName)) {
643         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get algoName."));
644         LOGE("failed to get algoName.");
645         return nullptr;
646     }
647 
648     HcfVerify *verify = nullptr;
649     HcfResult ret = HcfVerifyCreate(algName.c_str(), &verify);
650     if (ret != HCF_SUCCESS) {
651         napi_throw(env, GenerateBusinessError(env, ret, "create c verify fail."));
652         LOGE("create c verify fail.");
653         return nullptr;
654     }
655 
656     NapiVerify *napiVerify = new (std::nothrow) NapiVerify(verify);
657     if (napiVerify == nullptr) {
658         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi verify failed"));
659         LOGE("new napi verify failed");
660         HcfObjDestroy(verify);
661         return nullptr;
662     }
663 
664     napi_value napiAlgName = nullptr;
665     napi_create_string_utf8(env, algName.c_str(), NAPI_AUTO_LENGTH, &napiAlgName);
666     napi_set_named_property(env, instance, CRYPTO_TAG_ALG_NAME.c_str(), napiAlgName);
667 
668     return NapiWrapVerify(env, instance, napiVerify);
669 }
670 
SetVerifyUserIdUintArray(napi_env env,napi_value * argv,HcfVerify * verify)671 static HcfResult SetVerifyUserIdUintArray(napi_env env, napi_value *argv, HcfVerify *verify)
672 {
673     HcfBlob *blob = nullptr;
674     blob = GetBlobFromNapiUint8Arr(env, argv[1]);
675     if (blob == nullptr) {
676         LOGE("failed to get blob.");
677         return HCF_INVALID_PARAMS;
678     }
679     HcfResult ret = verify->setVerifySpecUint8Array(verify, SM2_USER_ID_UINT8ARR, *blob);
680     if (ret != HCF_SUCCESS) {
681         HcfBlobDataFree(blob);
682         HcfFree(blob);
683         LOGE("c SetVerifyUserIdUintArray failed.");
684         return HCF_INVALID_PARAMS;
685     }
686     HcfBlobDataFree(blob);
687     HcfFree(blob);
688     return ret;
689 }
690 
SetVerifySaltLenInt(napi_env env,napi_value * argv,HcfVerify * verify)691 static HcfResult SetVerifySaltLenInt(napi_env env, napi_value *argv, HcfVerify *verify)
692 {
693     int32_t saltLen = 0;
694     if (napi_get_value_int32(env, argv[1], &saltLen) != napi_ok) {
695         LOGE("get signSpec saltLen failed!");
696         return HCF_INVALID_PARAMS;
697     }
698     HcfResult ret = verify->setVerifySpecInt(verify, PSS_SALT_LEN_INT, saltLen);
699     if (ret != HCF_SUCCESS) {
700         LOGE("c setSignSpecNumber fail.");
701         return HCF_INVALID_PARAMS;
702     }
703     return ret;
704 }
705 
SetDetailVerifySpec(napi_env env,napi_value * argv,SignSpecItem item,HcfVerify * verify)706 static HcfResult SetDetailVerifySpec(napi_env env, napi_value *argv, SignSpecItem item, HcfVerify *verify)
707 {
708     HcfResult result = HCF_INVALID_PARAMS;
709 
710     switch (item) {
711         case SM2_USER_ID_UINT8ARR:
712             result = SetVerifyUserIdUintArray(env, argv, verify);
713             break;
714         case PSS_SALT_LEN_INT:
715             result = SetVerifySaltLenInt(env, argv, verify);
716             break;
717         default:
718             LOGE("specItem not support.");
719             break;
720     }
721     return result;
722 }
723 
724 // verify setVerifySpec(itemType :VerifySpecItem, itemValue : number|string)
JsSetVerifySpec(napi_env env,napi_callback_info info)725 napi_value NapiVerify::JsSetVerifySpec(napi_env env, napi_callback_info info)
726 {
727     napi_value thisVar = nullptr;
728     NapiVerify *napiVerify = nullptr;
729     size_t expectedArgc = ARGS_SIZE_TWO;
730     size_t argc = ARGS_SIZE_TWO;
731     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
732     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
733     if (argc != expectedArgc) {
734         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "init failed for wrong argument num."));
735         LOGE("wrong argument num. require 2 arguments. [Argc]: %zu!", argc);
736         return nullptr;
737     }
738     SignSpecItem item;
739     if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
740         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get signSpecItem failed!"));
741         LOGE("get signspecitem failed!");
742         return nullptr;
743     }
744     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiVerify));
745     if (status != napi_ok || napiVerify == nullptr) {
746         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiVerify obj!"));
747         LOGE("failed to unwrap napiVerify obj!");
748         return nullptr;
749     }
750     HcfVerify *verify = napiVerify->GetVerify();
751     if (SetDetailVerifySpec(env, argv, item, verify) != HCF_SUCCESS) {
752         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to set verify spec!"));
753         LOGE("failed to set verify spec!");
754         return nullptr;
755     }
756     return thisVar;
757 }
758 
GetVerifySpecString(napi_env env,SignSpecItem item,HcfVerify * verify)759 static napi_value GetVerifySpecString(napi_env env, SignSpecItem item, HcfVerify *verify)
760 {
761     char *returnString = nullptr;
762     HcfResult ret = verify->getVerifySpecString(verify, item, &returnString);
763     if (ret != HCF_SUCCESS) {
764         napi_throw(env, GenerateBusinessError(env, ret, "C getVerifySpecString failed."));
765         LOGE("c getVerifySpecString fail.");
766         return nullptr;
767     }
768 
769     napi_value instance = nullptr;
770     napi_create_string_utf8(env, returnString, NAPI_AUTO_LENGTH, &instance);
771     HcfFree(returnString);
772     return instance;
773 }
774 
GetVerifySpecNumber(napi_env env,SignSpecItem item,HcfVerify * verify)775 static napi_value GetVerifySpecNumber(napi_env env, SignSpecItem item, HcfVerify *verify)
776 {
777     int returnInt;
778     HcfResult ret = verify->getVerifySpecInt(verify, item, &returnInt);
779     if (ret != HCF_SUCCESS) {
780         napi_throw(env, GenerateBusinessError(env, ret, "C getVerifySpecInt failed."));
781         LOGE("c getVerifySpecInt fail.");
782         return nullptr;
783     }
784 
785     napi_value instance = nullptr;
786     napi_create_int32(env, returnInt, &instance);
787     return instance;
788 }
789 
JsGetVerifySpec(napi_env env,napi_callback_info info)790 napi_value NapiVerify::JsGetVerifySpec(napi_env env, napi_callback_info info)
791 {
792     napi_value thisVar = nullptr;
793     NapiVerify *napiVerify = nullptr;
794     size_t expectedArgc = ARGS_SIZE_ONE;
795     size_t argc = ARGS_SIZE_ONE;
796     napi_value argv[ARGS_SIZE_ONE] = { nullptr };
797     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
798     if (argc != expectedArgc) {
799         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "init failed for wrong argument num."));
800         LOGE("wrong argument num. require 1 arguments. [Argc]: %zu!", argc);
801         return nullptr;
802     }
803     SignSpecItem item;
804     if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
805         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get signSpecItem failed!"));
806         LOGE("get signSpecItem failed!");
807         return nullptr;
808     }
809 
810     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiVerify));
811     if (status != napi_ok || napiVerify == nullptr) {
812         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiVerify obj!"));
813         LOGE("failed to unwrap napiVerify obj!");
814         return nullptr;
815     }
816     HcfVerify *verify = napiVerify->GetVerify();
817     if (verify == nullptr) {
818         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get verify obj!"));
819         LOGE("failed to get verfiy obj!");
820         return nullptr;
821     }
822 
823     int32_t type = GetSignSpecType(item);
824     if (type == SPEC_ITEM_TYPE_STR) {
825         return GetVerifySpecString(env, item, verify);
826     } else if (type == SPEC_ITEM_TYPE_NUM) {
827         return GetVerifySpecNumber(env, item, verify);
828     } else {
829         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "VerifySpecItem not support!"));
830         return nullptr;
831     }
832 }
833 
DefineVerifyJSClass(napi_env env,napi_value exports)834 void NapiVerify::DefineVerifyJSClass(napi_env env, napi_value exports)
835 {
836     napi_property_descriptor desc[] = {
837         DECLARE_NAPI_FUNCTION("createVerify", NapiVerify::CreateJsVerify),
838     };
839     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
840 
841     napi_property_descriptor classDesc[] = {
842         DECLARE_NAPI_FUNCTION("init", NapiVerify::JsInit),
843         DECLARE_NAPI_FUNCTION("update", NapiVerify::JsUpdate),
844         DECLARE_NAPI_FUNCTION("verify", NapiVerify::JsVerify),
845         DECLARE_NAPI_FUNCTION("setVerifySpec", NapiVerify::JsSetVerifySpec),
846         DECLARE_NAPI_FUNCTION("getVerifySpec", NapiVerify::JsGetVerifySpec),
847     };
848     napi_value constructor = nullptr;
849     napi_define_class(env, "Verify", NAPI_AUTO_LENGTH, NapiVerify::VerifyConstructor, nullptr,
850         sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
851     napi_create_reference(env, constructor, 1, &classRef_);
852 }
853 } // CryptoFramework
854 } // OHOS
855