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