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