• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *    http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_asy_key_spec_generator.h"
17 
18 #include "asy_key_params.h"
19 #include "securec.h"
20 #include "log.h"
21 #include "memory.h"
22 
23 #include "napi_crypto_framework_defines.h"
24 #include "napi_utils.h"
25 #include "napi_key_pair.h"
26 #include "napi_pri_key.h"
27 #include "napi_pub_key.h"
28 
29 namespace OHOS {
30 namespace CryptoFramework {
31 struct AsyKeyCtx {
32     napi_env env = nullptr;
33 
34     AsyncType asyncType = ASYNC_CALLBACK;
35     napi_ref callback = nullptr;
36     napi_deferred deferred = nullptr;
37     napi_value promise = nullptr;
38     napi_async_work asyncWork = nullptr;
39     napi_ref generatorRef = nullptr;
40 
41     HcfAsyKeyGeneratorBySpec *generator;
42     HcfResult errCode = HCF_SUCCESS;
43     const char *errMsg = nullptr;
44     HcfKeyPair *returnKeyPair = nullptr;
45     HcfPubKey *returnPubKey = nullptr;
46     HcfPriKey *returnPriKey = nullptr;
47 };
48 
49 thread_local napi_ref NapiAsyKeyGeneratorBySpec::classRef_ = nullptr;
50 
FreeAsyKeyCtx(napi_env env,AsyKeyCtx * ctx)51 static void FreeAsyKeyCtx(napi_env env, AsyKeyCtx *ctx)
52 {
53     if (ctx == nullptr) {
54         return;
55     }
56 
57     if (ctx->asyncWork != nullptr) {
58         napi_delete_async_work(env, ctx->asyncWork);
59         ctx->asyncWork = nullptr;
60     }
61 
62     if (ctx->callback != nullptr) {
63         napi_delete_reference(env, ctx->callback);
64         ctx->callback = nullptr;
65     }
66 
67     if (ctx->generatorRef != nullptr) {
68         napi_delete_reference(env, ctx->generatorRef);
69         ctx->generatorRef = nullptr;
70     }
71 
72     HcfFree(ctx);
73 }
74 
BuildAsyKeyCtx(napi_env env,napi_callback_info info,AsyKeyCtx * ctx)75 static bool BuildAsyKeyCtx(napi_env env, napi_callback_info info, AsyKeyCtx *ctx)
76 {
77     napi_value thisVar = nullptr;
78     size_t expectedArgc = PARAMS_NUM_ONE;
79     size_t argc = expectedArgc;
80     napi_value argv[PARAMS_NUM_ONE] = { nullptr };
81     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
82     if (argc != expectedArgc && argc != expectedArgc - 1) {
83         LOGE("wrong argument num. require %{public}zu or %{public}zu arguments. [Argc]: %{public}zu!",
84             expectedArgc - 1, expectedArgc, argc);
85         return false;
86     }
87     ctx->asyncType = isCallback(env, argv[0], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
88 
89     NapiAsyKeyGeneratorBySpec *napiGenerator = nullptr;
90     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiGenerator));
91     if (status != napi_ok || napiGenerator == nullptr) {
92         LOGE("failed to unwrap napi asyKeyGenerator obj.");
93         return false;
94     }
95     ctx->generator = napiGenerator->GetAsyKeyGeneratorBySpec();
96 
97     if (napi_create_reference(env, thisVar, 1, &ctx->generatorRef) != napi_ok) {
98         LOGE("create generator ref failed when generator asym key by spec!");
99         return false;
100     }
101 
102     if (ctx->asyncType == ASYNC_PROMISE) {
103         napi_create_promise(env, &ctx->deferred, &ctx->promise);
104         return true;
105     } else {
106         return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
107     }
108 }
109 
GetAsyKeyGenerator(napi_env env,napi_callback_info info,HcfAsyKeyGeneratorBySpec ** generator)110 static bool GetAsyKeyGenerator(napi_env env, napi_callback_info info, HcfAsyKeyGeneratorBySpec **generator)
111 {
112     napi_value thisVar = nullptr;
113     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
114 
115     NapiAsyKeyGeneratorBySpec *napiGenerator = nullptr;
116     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiGenerator));
117     if (status != napi_ok || napiGenerator == nullptr) {
118         LOGE("failed to unwrap napi asyKeyGenerator obj.");
119         return false;
120     }
121     *generator = napiGenerator->GetAsyKeyGeneratorBySpec();
122     return true;
123 }
124 
ReturnAsyKeyCallbackResult(napi_env env,AsyKeyCtx * ctx,napi_value result)125 static void ReturnAsyKeyCallbackResult(napi_env env, AsyKeyCtx *ctx, napi_value result)
126 {
127     napi_value businessError = nullptr;
128     if (ctx->errCode != HCF_SUCCESS) {
129         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
130     }
131 
132     napi_value params[ARGS_SIZE_TWO] = { businessError, result };
133 
134     napi_value func = nullptr;
135     napi_get_reference_value(env, ctx->callback, &func);
136 
137     napi_value recv = nullptr;
138     napi_value callFuncRet = nullptr;
139     napi_get_undefined(env, &recv);
140     napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
141 }
142 
ReturnAsyKeyPromiseResult(napi_env env,AsyKeyCtx * ctx,napi_value result)143 static void ReturnAsyKeyPromiseResult(napi_env env, AsyKeyCtx *ctx, napi_value result)
144 {
145     if (ctx->errCode == HCF_SUCCESS) {
146         napi_resolve_deferred(env, ctx->deferred, result);
147     } else {
148         napi_reject_deferred(env, ctx->deferred,
149             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
150     }
151 }
152 
GenKeyPairAsyncWorkProcess(napi_env env,void * data)153 static void GenKeyPairAsyncWorkProcess(napi_env env, void *data)
154 {
155     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
156 
157     ctx->errCode = ctx->generator->generateKeyPair(ctx->generator, &(ctx->returnKeyPair));
158     if (ctx->errCode != HCF_SUCCESS) {
159         LOGD("[error] generate key pair fail.");
160         ctx->errMsg = "generate key pair fail.";
161     }
162 }
163 
GenKeyPairAsyncWorkReturn(napi_env env,napi_status status,void * data)164 static void GenKeyPairAsyncWorkReturn(napi_env env, napi_status status, void *data)
165 {
166     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
167 
168     napi_value instance = nullptr;
169     if (ctx->errCode == HCF_SUCCESS) {
170         NapiKeyPair *napiKeyPair = new (std::nothrow) NapiKeyPair(ctx->returnKeyPair);
171         if (napiKeyPair == nullptr) {
172             napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi key pair failed!"));
173             LOGE("new napi key pair failed");
174             HcfObjDestroy(ctx->returnKeyPair);
175             ctx->returnKeyPair = nullptr;
176             FreeAsyKeyCtx(env, ctx);
177             return;
178         }
179         instance = napiKeyPair->ConvertToJsKeyPair(env);
180 
181         napi_status ret = napi_wrap(
182             env, instance, napiKeyPair,
183             [](napi_env env, void *data, void *hint) {
184                 NapiKeyPair *keyPair = static_cast<NapiKeyPair *>(data);
185                 delete keyPair;
186                 return;
187             }, nullptr, nullptr);
188         if (ret != napi_ok) {
189             LOGE("failed to wrap napiKeyPair obj!");
190             ctx->errCode = HCF_INVALID_PARAMS;
191             ctx->errMsg = "failed to wrap napiKeyPair obj!";
192             delete napiKeyPair;
193         }
194     }
195 
196     if (ctx->asyncType == ASYNC_CALLBACK) {
197         ReturnAsyKeyCallbackResult(env, ctx, instance);
198     } else {
199         ReturnAsyKeyPromiseResult(env, ctx, instance);
200     }
201     FreeAsyKeyCtx(env, ctx);
202 }
203 
PubKeyAsyncWorkProcess(napi_env env,void * data)204 static void PubKeyAsyncWorkProcess(napi_env env, void *data)
205 {
206     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
207 
208     ctx->errCode = ctx->generator->generatePubKey(ctx->generator, &(ctx->returnPubKey));
209     if (ctx->errCode != HCF_SUCCESS) {
210         LOGD("[error] generate PubKey fail.");
211         ctx->errMsg = "generate PubKey fail.";
212     }
213 }
214 
PubKeyAsyncWorkReturn(napi_env env,napi_status status,void * data)215 static void PubKeyAsyncWorkReturn(napi_env env, napi_status status, void *data)
216 {
217     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
218 
219     napi_value instance = nullptr;
220     if (ctx->errCode == HCF_SUCCESS) {
221         NapiPubKey *napiPubKey = new (std::nothrow) NapiPubKey(ctx->returnPubKey);
222         if (napiPubKey == nullptr) {
223             napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi pub key failed!"));
224             LOGE("new napi pub key failed");
225             HcfObjDestroy(ctx->returnPubKey);
226             ctx->returnPubKey = nullptr;
227             FreeAsyKeyCtx(env, ctx);
228             return;
229         }
230         instance = napiPubKey->ConvertToJsPubKey(env);
231 
232         napi_status ret = napi_wrap(
233             env, instance, napiPubKey,
234             [](napi_env env, void *data, void *hint) {
235                 NapiPubKey *napiPubKey = static_cast<NapiPubKey *>(data);
236                 HcfObjDestroy(napiPubKey->GetPubKey());
237                 delete napiPubKey;
238                 return;
239             }, nullptr, nullptr);
240         if (ret != napi_ok) {
241             LOGE("failed to wrap napiPubKey obj!");
242             ctx->errCode = HCF_INVALID_PARAMS;
243             ctx->errMsg = "failed to wrap napiPubKey obj!";
244             HcfObjDestroy(napiPubKey->GetPubKey());
245             delete napiPubKey;
246         }
247     }
248 
249     if (ctx->asyncType == ASYNC_CALLBACK) {
250         ReturnAsyKeyCallbackResult(env, ctx, instance);
251     } else {
252         ReturnAsyKeyPromiseResult(env, ctx, instance);
253     }
254     FreeAsyKeyCtx(env, ctx);
255 }
256 
PriKeyAsyncWorkProcess(napi_env env,void * data)257 static void PriKeyAsyncWorkProcess(napi_env env, void *data)
258 {
259     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
260 
261     ctx->errCode = ctx->generator->generatePriKey(ctx->generator, &(ctx->returnPriKey));
262     if (ctx->errCode != HCF_SUCCESS) {
263         LOGD("[error] generate PriKey fail.");
264         ctx->errMsg = "generate PriKey fail.";
265     }
266 }
267 
PriKeyAsyncWorkReturn(napi_env env,napi_status status,void * data)268 static void PriKeyAsyncWorkReturn(napi_env env, napi_status status, void *data)
269 {
270     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
271 
272     napi_value instance = nullptr;
273     if (ctx->errCode == HCF_SUCCESS) {
274         NapiPriKey *napiPriKey = new (std::nothrow) NapiPriKey(ctx->returnPriKey);
275         if (napiPriKey == nullptr) {
276             napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi pri key failed!"));
277             LOGE("new napi pri key failed");
278             HcfObjDestroy(ctx->returnPriKey);
279             ctx->returnPriKey = nullptr;
280             FreeAsyKeyCtx(env, ctx);
281             return;
282         }
283         instance = napiPriKey->ConvertToJsPriKey(env);
284 
285         napi_status ret = napi_wrap(
286             env, instance, napiPriKey,
287             [](napi_env env, void *data, void *hint) {
288                 NapiPriKey *napiPriKey = static_cast<NapiPriKey *>(data);
289                 HcfObjDestroy(napiPriKey->GetPriKey());
290                 delete napiPriKey;
291                 return;
292             }, nullptr, nullptr);
293         if (ret != napi_ok) {
294             LOGE("failed to wrap napiPriKey obj!");
295             ctx->errCode = HCF_INVALID_PARAMS;
296             ctx->errMsg = "failed to wrap napiPriKey obj!";
297             HcfObjDestroy(napiPriKey->GetPriKey());
298             delete napiPriKey;
299         }
300     }
301 
302     if (ctx->asyncType == ASYNC_CALLBACK) {
303         ReturnAsyKeyCallbackResult(env, ctx, instance);
304     } else {
305         ReturnAsyKeyPromiseResult(env, ctx, instance);
306     }
307     FreeAsyKeyCtx(env, ctx);
308 }
309 
NewGenKeyPairAsyncWork(napi_env env,AsyKeyCtx * ctx)310 static napi_value NewGenKeyPairAsyncWork(napi_env env, AsyKeyCtx *ctx)
311 {
312     napi_value resourceName = nullptr;
313     napi_create_string_utf8(env, "generateKeyPair", NAPI_AUTO_LENGTH, &resourceName);
314 
315     napi_create_async_work(
316         env, nullptr, resourceName,
317         [](napi_env env, void *data) {
318             GenKeyPairAsyncWorkProcess(env, data);
319             return;
320         },
321         [](napi_env env, napi_status status, void *data) {
322             GenKeyPairAsyncWorkReturn(env, status, data);
323             return;
324         },
325         static_cast<void *>(ctx),
326         &ctx->asyncWork);
327 
328     napi_queue_async_work(env, ctx->asyncWork);
329     if (ctx->asyncType == ASYNC_PROMISE) {
330         return ctx->promise;
331     } else {
332         return NapiGetNull(env);
333     }
334 }
335 
NewPubKeyAsyncWork(napi_env env,AsyKeyCtx * ctx)336 static napi_value NewPubKeyAsyncWork(napi_env env, AsyKeyCtx *ctx)
337 {
338     napi_value resourceName = nullptr;
339     napi_create_string_utf8(env, "generatePubKey", NAPI_AUTO_LENGTH, &resourceName);
340 
341     napi_create_async_work(
342         env, nullptr, resourceName,
343         [](napi_env env, void *data) {
344             PubKeyAsyncWorkProcess(env, data);
345             return;
346         },
347         [](napi_env env, napi_status status, void *data) {
348             PubKeyAsyncWorkReturn(env, status, data);
349             return;
350         },
351         static_cast<void *>(ctx),
352         &ctx->asyncWork);
353 
354     napi_queue_async_work(env, ctx->asyncWork);
355     if (ctx->asyncType == ASYNC_PROMISE) {
356         return ctx->promise;
357     } else {
358         return NapiGetNull(env);
359     }
360 }
361 
NewPriKeyAsyncWork(napi_env env,AsyKeyCtx * ctx)362 static napi_value NewPriKeyAsyncWork(napi_env env, AsyKeyCtx *ctx)
363 {
364     napi_value resourceName = nullptr;
365     napi_create_string_utf8(env, "generatePriKey", NAPI_AUTO_LENGTH, &resourceName);
366 
367     napi_create_async_work(
368         env, nullptr, resourceName,
369         [](napi_env env, void *data) {
370             PriKeyAsyncWorkProcess(env, data);
371             return;
372         },
373         [](napi_env env, napi_status status, void *data) {
374             PriKeyAsyncWorkReturn(env, status, data);
375             return;
376         },
377         static_cast<void *>(ctx),
378         &ctx->asyncWork);
379 
380     napi_queue_async_work(env, ctx->asyncWork);
381     if (ctx->asyncType == ASYNC_PROMISE) {
382         return ctx->promise;
383     } else {
384         return NapiGetNull(env);
385     }
386 }
387 
NapiAsyKeyGeneratorBySpec(HcfAsyKeyGeneratorBySpec * generator)388 NapiAsyKeyGeneratorBySpec::NapiAsyKeyGeneratorBySpec(HcfAsyKeyGeneratorBySpec *generator)
389 {
390     this->generator_ = generator;
391 }
392 
~NapiAsyKeyGeneratorBySpec()393 NapiAsyKeyGeneratorBySpec::~NapiAsyKeyGeneratorBySpec()
394 {
395     HcfObjDestroy(this->generator_);
396     this->generator_ = nullptr;
397 }
398 
GetAsyKeyGeneratorBySpec()399 HcfAsyKeyGeneratorBySpec *NapiAsyKeyGeneratorBySpec::GetAsyKeyGeneratorBySpec()
400 {
401     return this->generator_;
402 }
403 
JsGenerateKeyPair(napi_env env,napi_callback_info info)404 napi_value NapiAsyKeyGeneratorBySpec::JsGenerateKeyPair(napi_env env, napi_callback_info info)
405 {
406     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(HcfMalloc(sizeof(AsyKeyCtx), 0));
407     if (ctx == nullptr) {
408         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail!"));
409         LOGE("create context fail.");
410         return nullptr;
411     }
412 
413     if (!BuildAsyKeyCtx(env, info, ctx)) {
414         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail!"));
415         LOGE("build context fail.");
416         FreeAsyKeyCtx(env, ctx);
417         return nullptr;
418     }
419 
420     return NewGenKeyPairAsyncWork(env, ctx);
421 }
422 
JsGenerateKeyPairSync(napi_env env,napi_callback_info info)423 napi_value NapiAsyKeyGeneratorBySpec::JsGenerateKeyPairSync(napi_env env, napi_callback_info info)
424 {
425     HcfAsyKeyGeneratorBySpec *generator = nullptr;
426     if (!GetAsyKeyGenerator(env, info, &generator) || generator == nullptr) {
427         LOGE("build generator fail.");
428         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build generator fail!"));
429         return nullptr;
430     }
431 
432     HcfKeyPair *returnKeyPair = nullptr;
433     HcfResult errCode = generator->generateKeyPair(generator, &(returnKeyPair));
434     if (errCode != HCF_SUCCESS) {
435         LOGE("generate key pair fail.");
436         napi_throw(env, GenerateBusinessError(env, errCode, "generate key pair fail."));
437         return nullptr;
438     }
439 
440     napi_value instance = nullptr;
441     NapiKeyPair *napiKeyPair = new (std::nothrow) NapiKeyPair(returnKeyPair);
442     if (napiKeyPair == nullptr) {
443         HcfObjDestroy(returnKeyPair);
444         returnKeyPair = nullptr;
445         LOGE("new napi key pair failed");
446         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi key pair failed!"));
447         return nullptr;
448     }
449 
450     instance = napiKeyPair->ConvertToJsKeyPair(env);
451     napi_status ret = napi_wrap(
452         env, instance, napiKeyPair,
453         [](napi_env env, void *data, void *hint) {
454             NapiKeyPair *keyPair = static_cast<NapiKeyPair *>(data);
455             delete keyPair;
456             return;
457         }, nullptr, nullptr);
458     if (ret != napi_ok) {
459         LOGE("failed to wrap napiKeyPair obj!");
460         delete napiKeyPair;
461         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to wrap napiKeyPair obj!"));
462         return nullptr;
463     }
464     return instance;
465 }
466 
JsGeneratePubKey(napi_env env,napi_callback_info info)467 napi_value NapiAsyKeyGeneratorBySpec::JsGeneratePubKey(napi_env env, napi_callback_info info)
468 {
469     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(HcfMalloc(sizeof(AsyKeyCtx), 0));
470     if (ctx == nullptr) {
471         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail!"));
472         LOGE("create context fail.");
473         return nullptr;
474     }
475 
476     if (!BuildAsyKeyCtx(env, info, ctx)) {
477         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail!"));
478         LOGE("build context fail.");
479         FreeAsyKeyCtx(env, ctx);
480         return nullptr;
481     }
482 
483     return NewPubKeyAsyncWork(env, ctx);
484 }
485 
JsGeneratePubKeySync(napi_env env,napi_callback_info info)486 napi_value NapiAsyKeyGeneratorBySpec::JsGeneratePubKeySync(napi_env env, napi_callback_info info)
487 {
488     HcfAsyKeyGeneratorBySpec *generator = nullptr;
489     if (!GetAsyKeyGenerator(env, info, &generator) || generator == nullptr) {
490         LOGE("build generator fail.");
491         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build generator fail!"));
492         return nullptr;
493     }
494 
495     HcfPubKey *returnPubKey = nullptr;
496     HcfResult errCode = generator->generatePubKey(generator, &(returnPubKey));
497     if (errCode != HCF_SUCCESS) {
498         LOGE("generate PubKey fail.");
499         napi_throw(env, GenerateBusinessError(env, errCode, "generate PubKey fail."));
500         return nullptr;
501     }
502 
503     napi_value instance = nullptr;
504     NapiPubKey *napiPubKey = new (std::nothrow) NapiPubKey(returnPubKey);
505     if (napiPubKey == nullptr) {
506         HcfObjDestroy(returnPubKey);
507         returnPubKey = nullptr;
508         LOGE("new napi pub key failed");
509         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi pub key failed!"));
510         return nullptr;
511     }
512 
513     instance = napiPubKey->ConvertToJsPubKey(env);
514     napi_status ret = napi_wrap(
515         env, instance, napiPubKey,
516         [](napi_env env, void *data, void *hint) {
517             NapiPubKey *napiPubKey = static_cast<NapiPubKey *>(data);
518             HcfObjDestroy(napiPubKey->GetPubKey());
519             delete napiPubKey;
520             return;
521         }, nullptr, nullptr);
522     if (ret != napi_ok) {
523         LOGE("failed to wrap napiPubKey obj!");
524         HcfObjDestroy(napiPubKey->GetPubKey());
525         delete napiPubKey;
526         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "failed to wrap napiPubKey obj!"));
527         return nullptr;
528     }
529 
530     return instance;
531 }
532 
JsGeneratePriKey(napi_env env,napi_callback_info info)533 napi_value NapiAsyKeyGeneratorBySpec::JsGeneratePriKey(napi_env env, napi_callback_info info)
534 {
535     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(HcfMalloc(sizeof(AsyKeyCtx), 0));
536     if (ctx == nullptr) {
537         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail!"));
538         LOGE("create context fail.");
539         return nullptr;
540     }
541 
542     if (!BuildAsyKeyCtx(env, info, ctx)) {
543         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail!"));
544         LOGE("build context fail.");
545         FreeAsyKeyCtx(env, ctx);
546         return nullptr;
547     }
548 
549     return NewPriKeyAsyncWork(env, ctx);
550 }
551 
JsGeneratePriKeySync(napi_env env,napi_callback_info info)552 napi_value NapiAsyKeyGeneratorBySpec::JsGeneratePriKeySync(napi_env env, napi_callback_info info)
553 {
554     HcfAsyKeyGeneratorBySpec *generator = nullptr;
555     if (!GetAsyKeyGenerator(env, info, &generator) || generator == nullptr) {
556         LOGE("build generator fail.");
557         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build generator fail!"));
558         return nullptr;
559     }
560 
561     HcfPriKey *returnPriKey = nullptr;
562     HcfResult errCode = generator->generatePriKey(generator, &(returnPriKey));
563     if (errCode != HCF_SUCCESS) {
564         LOGE("generate PriKey fail.");
565         napi_throw(env, GenerateBusinessError(env, errCode, "generate PriKey fail."));
566         return nullptr;
567     }
568 
569     napi_value instance = nullptr;
570     NapiPriKey *napiPriKey = new (std::nothrow) NapiPriKey(returnPriKey);
571     if (napiPriKey == nullptr) {
572         HcfObjDestroy(returnPriKey);
573         returnPriKey = nullptr;
574         LOGE("new napi pri key failed");
575         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi pri key failed!"));
576         return nullptr;
577     }
578 
579     instance = napiPriKey->ConvertToJsPriKey(env);
580     napi_status ret = napi_wrap(
581         env, instance, napiPriKey,
582         [](napi_env env, void *data, void *hint) {
583             NapiPriKey *napiPriKey = static_cast<NapiPriKey *>(data);
584             HcfObjDestroy(napiPriKey->GetPriKey());
585             delete napiPriKey;
586             return;
587         }, nullptr, nullptr);
588     if (ret != napi_ok) {
589         LOGE("failed to wrap napiPriKey obj!");
590         HcfObjDestroy(napiPriKey->GetPriKey());
591         delete napiPriKey;
592         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "failed to wrap napiPriKey obj!"));
593         return nullptr;
594     }
595 
596     return instance;
597 }
598 
AsyKeyGeneratorBySpecConstructor(napi_env env,napi_callback_info info)599 napi_value NapiAsyKeyGeneratorBySpec::AsyKeyGeneratorBySpecConstructor(napi_env env, napi_callback_info info)
600 {
601     napi_value thisVar = nullptr;
602     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
603     return thisVar;
604 }
605 
CreateJsAsyKeyGeneratorBySpec(napi_env env,napi_callback_info info)606 napi_value NapiAsyKeyGeneratorBySpec::CreateJsAsyKeyGeneratorBySpec(napi_env env, napi_callback_info info)
607 {
608     size_t argc = PARAMS_NUM_ONE;
609     napi_value argv[PARAMS_NUM_ONE] = { nullptr };
610     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
611 
612     if (argc != PARAMS_NUM_ONE) {
613         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
614         LOGE("The input args num is invalid.");
615         return nullptr;
616     }
617 
618     napi_value instance;
619     napi_value constructor = nullptr;
620     napi_get_reference_value(env, classRef_, &constructor);
621     napi_new_instance(env, constructor, argc, argv, &instance);
622 
623     HcfAsyKeyParamsSpec *asyKeySpec = nullptr;
624     if (!GetAsyKeySpecFromNapiValue(env, argv[0], &asyKeySpec)) {
625         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get valid asyKeySpec!"));
626         LOGE("GetAsyKeySpecFromNapiValue failed!");
627         return nullptr;
628     }
629     HcfAsyKeyGeneratorBySpec *generator = nullptr;
630     HcfResult res = HcfAsyKeyGeneratorBySpecCreate(asyKeySpec, &generator);
631     FreeAsyKeySpec(asyKeySpec);
632     asyKeySpec = nullptr;
633     if (res != HCF_SUCCESS) {
634         napi_throw(env, GenerateBusinessError(env, res, "create C generator by sepc fail."));
635         LOGE("create C generator by spec fail.");
636         return nullptr;
637     }
638 
639     NapiAsyKeyGeneratorBySpec *napiAsyKeyGeneratorBySpec = new (std::nothrow) NapiAsyKeyGeneratorBySpec(generator);
640     if (napiAsyKeyGeneratorBySpec == nullptr) {
641         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi asy key generator by spec failed!"));
642         LOGE("new napi asy key generator by spec failed!");
643         HcfObjDestroy(generator);
644         generator = nullptr;
645         return nullptr;
646     }
647 
648     napi_status status = napi_wrap(env, instance, napiAsyKeyGeneratorBySpec,
649         [](napi_env env, void *data, void *hint) {
650             NapiAsyKeyGeneratorBySpec *napiAsyKeyGeneratorBySpec = static_cast<NapiAsyKeyGeneratorBySpec *>(data);
651             delete napiAsyKeyGeneratorBySpec;
652             return;
653         }, nullptr, nullptr);
654     if (status != napi_ok) {
655         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "wrap napiAsyKeyGeneratorBySpec failed!"));
656         LOGE("failed to wrap napiAsyKeyGeneratorBySpec obj!");
657         delete napiAsyKeyGeneratorBySpec;
658         return nullptr;
659     }
660     return instance;
661 }
662 
JsGetAlgorithm(napi_env env,napi_callback_info info)663 napi_value NapiAsyKeyGeneratorBySpec::JsGetAlgorithm(napi_env env, napi_callback_info info)
664 {
665     napi_value thisVar = nullptr;
666     NapiAsyKeyGeneratorBySpec *napiAsyKeyGeneratorBySpec = nullptr;
667     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
668     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiAsyKeyGeneratorBySpec));
669     if (status != napi_ok || napiAsyKeyGeneratorBySpec == nullptr) {
670         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napi asyKeyGenerator obj."));
671         LOGE("failed to unwrap napi asyKeyGenerator obj.");
672         return nullptr;
673     }
674     HcfAsyKeyGeneratorBySpec *generator = napiAsyKeyGeneratorBySpec->GetAsyKeyGeneratorBySpec();
675     if (generator == nullptr) {
676         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "fail to get generator by spec obj!"));
677         LOGE("fail to get generator by spec obj!");
678         return nullptr;
679     }
680 
681     const char *algo = generator->getAlgName(generator);
682     napi_value instance = nullptr;
683     napi_create_string_utf8(env, algo, NAPI_AUTO_LENGTH, &instance);
684     return instance;
685 }
686 
DefineAsyKeyGeneratorBySpecJSClass(napi_env env,napi_value exports)687 void NapiAsyKeyGeneratorBySpec::DefineAsyKeyGeneratorBySpecJSClass(napi_env env, napi_value exports)
688 {
689     napi_property_descriptor desc[] = {
690         DECLARE_NAPI_FUNCTION("createAsyKeyGeneratorBySpec", NapiAsyKeyGeneratorBySpec::CreateJsAsyKeyGeneratorBySpec),
691     };
692     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
693 
694     napi_property_descriptor classDesc[] = {
695         DECLARE_NAPI_FUNCTION("generateKeyPair", NapiAsyKeyGeneratorBySpec::JsGenerateKeyPair),
696         DECLARE_NAPI_FUNCTION("generateKeyPairSync", NapiAsyKeyGeneratorBySpec::JsGenerateKeyPairSync),
697         DECLARE_NAPI_FUNCTION("generatePriKey", NapiAsyKeyGeneratorBySpec::JsGeneratePriKey),
698         DECLARE_NAPI_FUNCTION("generatePriKeySync", NapiAsyKeyGeneratorBySpec::JsGeneratePriKeySync),
699         DECLARE_NAPI_FUNCTION("generatePubKey", NapiAsyKeyGeneratorBySpec::JsGeneratePubKey),
700         DECLARE_NAPI_FUNCTION("generatePubKeySync", NapiAsyKeyGeneratorBySpec::JsGeneratePubKeySync),
701         { .utf8name = "algName", .getter = NapiAsyKeyGeneratorBySpec::JsGetAlgorithm },
702     };
703     napi_value constructor = nullptr;
704     napi_define_class(env, "AsyKeyGeneratorBySpec", NAPI_AUTO_LENGTH,
705         NapiAsyKeyGeneratorBySpec::AsyKeyGeneratorBySpecConstructor,
706         nullptr, sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
707     napi_create_reference(env, constructor, 1, &classRef_);
708 }
709 } // CryptoFramework
710 } // OHOS
711