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_generator.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_utils.h"
24 #include "napi_key_pair.h"
25 #include "napi_pri_key.h"
26 #include "napi_pub_key.h"
27 
28 namespace OHOS {
29 namespace CryptoFramework {
30 struct GenKeyPairCtx {
31     napi_env env = nullptr;
32 
33     AsyncType asyncType = ASYNC_CALLBACK;
34     napi_ref callback = nullptr;
35     napi_deferred deferred = nullptr;
36     napi_value promise = nullptr;
37     napi_async_work asyncWork = nullptr;
38     napi_ref generatorRef = nullptr;
39 
40     HcfAsyKeyGenerator *generator = nullptr;
41     HcfParamsSpec *params = nullptr;
42 
43     HcfResult errCode = HCF_SUCCESS;
44     const char *errMsg = nullptr;
45     HcfKeyPair *returnKeyPair = nullptr;
46 };
47 
48 struct ConvertKeyCtx {
49     napi_env env = nullptr;
50 
51     AsyncType asyncType = ASYNC_CALLBACK;
52     napi_ref callback = nullptr;
53     napi_deferred deferred = nullptr;
54     napi_value promise = nullptr;
55     napi_async_work asyncWork = nullptr;
56     napi_ref generatorRef = nullptr;
57 
58     HcfAsyKeyGenerator *generator = nullptr;
59     HcfParamsSpec *params = nullptr;
60     HcfBlob *pubKey = nullptr;
61     HcfBlob *priKey = nullptr;
62 
63     HcfResult errCode = HCF_SUCCESS;
64     const char *errMsg = nullptr;
65     HcfKeyPair *returnKeyPair = nullptr;
66 };
67 
68 struct ConvertPemKeyCtx {
69     napi_env env = nullptr;
70 
71     napi_deferred deferred = nullptr;
72     napi_value promise = nullptr;
73     napi_async_work asyncWork = nullptr;
74     napi_ref generatorRef = nullptr;
75 
76     HcfAsyKeyGenerator *generator = nullptr;
77     HcfParamsSpec *params = nullptr;
78     std::string pubKey = "";
79     std::string priKey = "";
80 
81     HcfResult errCode = HCF_SUCCESS;
82     const char *errMsg = nullptr;
83     HcfKeyPair *returnKeyPair = nullptr;
84 };
85 
86 thread_local napi_ref NapiAsyKeyGenerator::classRef_ = nullptr;
87 
FreeGenKeyPairCtx(napi_env env,GenKeyPairCtx * ctx)88 static void FreeGenKeyPairCtx(napi_env env, GenKeyPairCtx *ctx)
89 {
90     if (ctx == nullptr) {
91         return;
92     }
93 
94     if (ctx->asyncWork != nullptr) {
95         napi_delete_async_work(env, ctx->asyncWork);
96         ctx->asyncWork = nullptr;
97     }
98 
99     if (ctx->callback != nullptr) {
100         napi_delete_reference(env, ctx->callback);
101         ctx->callback = nullptr;
102     }
103 
104     if (ctx->generatorRef != nullptr) {
105         napi_delete_reference(env, ctx->generatorRef);
106         ctx->generatorRef = nullptr;
107     }
108 
109     HcfFree(ctx);
110 }
111 
FreeConvertKeyCtx(napi_env env,ConvertKeyCtx * ctx)112 static void FreeConvertKeyCtx(napi_env env, ConvertKeyCtx *ctx)
113 {
114     if (ctx == nullptr) {
115         return;
116     }
117 
118     if (ctx->asyncWork != nullptr) {
119         napi_delete_async_work(env, ctx->asyncWork);
120         ctx->asyncWork = nullptr;
121     }
122 
123     if (ctx->callback != nullptr) {
124         napi_delete_reference(env, ctx->callback);
125         ctx->callback = nullptr;
126     }
127 
128     if (ctx->generatorRef != nullptr) {
129         napi_delete_reference(env, ctx->generatorRef);
130         ctx->generatorRef = nullptr;
131     }
132 
133     HcfBlobDataFree(ctx->pubKey);
134     HcfFree(ctx->pubKey);
135     HcfBlobDataClearAndFree(ctx->priKey);
136     HcfFree(ctx->priKey);
137     HcfFree(ctx);
138 }
139 
FreeConvertPemKeyCtx(napi_env env,ConvertPemKeyCtx * ctx)140 static void FreeConvertPemKeyCtx(napi_env env, ConvertPemKeyCtx *ctx)
141 {
142     if (ctx == nullptr) {
143         return;
144     }
145 
146     if (ctx->asyncWork != nullptr) {
147         napi_delete_async_work(env, ctx->asyncWork);
148         ctx->asyncWork = nullptr;
149     }
150     if (ctx->generatorRef != nullptr) {
151         napi_delete_reference(env, ctx->generatorRef);
152         ctx->generatorRef = nullptr;
153     }
154 
155     ctx->errMsg = nullptr;
156     ctx->pubKey = "";
157     ctx->priKey = "";
158     HcfFree(ctx);
159 }
160 
BuildGenKeyPairCtx(napi_env env,napi_callback_info info,GenKeyPairCtx * ctx)161 static bool BuildGenKeyPairCtx(napi_env env, napi_callback_info info, GenKeyPairCtx *ctx)
162 {
163     napi_value thisVar = nullptr;
164     size_t expectedArgc = PARAMS_NUM_ONE;
165     size_t argc = expectedArgc;
166     napi_value argv[PARAMS_NUM_ONE] = { nullptr };
167     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
168     if (argc != expectedArgc && argc != expectedArgc - 1) {
169         LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
170         return false;
171     }
172     ctx->asyncType = isCallback(env, argv[0], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
173 
174     NapiAsyKeyGenerator *napiGenerator = nullptr;
175     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiGenerator));
176     if (status != napi_ok || napiGenerator == nullptr) {
177         LOGE("failed to unwrap napi asyKeyGenerator obj.");
178         return false;
179     }
180 
181     ctx->generator = napiGenerator->GetAsyKeyGenerator();
182     ctx->params = nullptr;
183 
184     if (napi_create_reference(env, thisVar, 1, &ctx->generatorRef) != napi_ok) {
185         LOGE("create generator ref failed generator key pair!");
186         return false;
187     }
188 
189     if (ctx->asyncType == ASYNC_PROMISE) {
190         napi_create_promise(env, &ctx->deferred, &ctx->promise);
191         return true;
192     } else {
193         return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
194     }
195 }
196 
GetPkAndSkBlobFromNapiValueIfInput(napi_env env,napi_value pkValue,napi_value skValue,HcfBlob ** returnPubKey,HcfBlob ** returnPriKey)197 static bool GetPkAndSkBlobFromNapiValueIfInput(napi_env env, napi_value pkValue, napi_value skValue,
198     HcfBlob **returnPubKey, HcfBlob **returnPriKey)
199 {
200     napi_valuetype valueType;
201     napi_typeof(env, pkValue, &valueType);
202     HcfBlob *pubKey = nullptr;
203     if (valueType != napi_null) {
204         pubKey = GetBlobFromNapiDataBlob(env, pkValue);
205         if (pubKey == nullptr) {
206             LOGE("failed to get pubKey.");
207             return false;
208         }
209     }
210 
211     napi_typeof(env, skValue, &valueType);
212     HcfBlob *priKey = nullptr;
213     if (valueType != napi_null) {
214         priKey = GetBlobFromNapiDataBlob(env, skValue);
215         if (priKey == nullptr) {
216             // if the prikey get func fails, the return pointer will not take the ownership of pubkey and not free it.
217             HcfBlobDataFree(pubKey);
218             HcfFree(pubKey);
219             LOGE("failed to get priKey.");
220             return false;
221         }
222     }
223 
224     *returnPubKey = pubKey;
225     *returnPriKey = priKey;
226     return true;
227 }
228 
GetPkAndSkStringFromNapiValueIfInput(napi_env env,napi_value pkValue,napi_value skValue,std::string & returnPubKey,std::string & returnPriKey)229 static bool GetPkAndSkStringFromNapiValueIfInput(napi_env env, napi_value pkValue, napi_value skValue,
230     std::string &returnPubKey, std::string &returnPriKey)
231 {
232     size_t length = 0;
233     napi_valuetype valueTypePk;
234     napi_valuetype valueTypeSk;
235     napi_typeof(env, pkValue, &valueTypePk);
236     napi_typeof(env, skValue, &valueTypeSk);
237     if (valueTypePk == napi_null && valueTypeSk == napi_null) {
238         LOGE("valueTypePk and valueTypeSk is all null.");
239         return false;
240     }
241     if (valueTypePk != napi_null) {
242         if (valueTypePk != napi_string) {
243             LOGE("valueTypePk wrong argument type, expect string type.");
244             return false;
245         }
246         if (napi_get_value_string_utf8(env, pkValue, nullptr, 0, &length) != napi_ok) {
247             LOGE("pkValue can not get string length.");
248             return false;
249         }
250         returnPubKey.reserve(length + 1);
251         returnPubKey.resize(length);
252         if (napi_get_value_string_utf8(env, pkValue, returnPubKey.data(), (length + 1), &length) != napi_ok) {
253             LOGE("pkValue can not get string value.");
254             return false;
255         }
256     }
257     if (valueTypeSk != napi_null) {
258         if (valueTypeSk != napi_string) {
259             LOGE("valueTypeSk wrong argument type. expect string type.");
260             return false;
261         }
262         if (napi_get_value_string_utf8(env, skValue, nullptr, 0, &length) != napi_ok) {
263             LOGE("skValue can not get string length.");
264             return false;
265         }
266         returnPriKey.reserve(length + 1);
267         returnPriKey.resize(length);
268         if (napi_get_value_string_utf8(env, skValue, returnPriKey.data(), (length + 1), &length) != napi_ok) {
269             LOGE("skValue can not get string value.");
270             return false;
271         }
272     }
273     return true;
274 }
275 
BuildConvertKeyCtx(napi_env env,napi_callback_info info,ConvertKeyCtx * ctx)276 static bool BuildConvertKeyCtx(napi_env env, napi_callback_info info, ConvertKeyCtx *ctx)
277 {
278     napi_value thisVar = nullptr;
279     size_t expectedArgc = PARAMS_NUM_THREE;
280     size_t argc = expectedArgc;
281     napi_value argv[PARAMS_NUM_THREE] = { nullptr };
282     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
283     if (argc != expectedArgc && argc != expectedArgc - 1) {
284         LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
285         return false;
286     }
287     ctx->asyncType = isCallback(env, argv[expectedArgc - 1], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
288 
289     NapiAsyKeyGenerator *napiGenerator = nullptr;
290     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiGenerator));
291     if (status != napi_ok || napiGenerator == nullptr) {
292         LOGE("failed to unwrap napi asyKeyGenerator obj.");
293         return false;
294     }
295 
296     HcfBlob *pubKey = nullptr;
297     HcfBlob *priKey = nullptr;
298     if (!GetPkAndSkBlobFromNapiValueIfInput(env, argv[PARAM0], argv[PARAM1], &pubKey, &priKey)) {
299         return false;
300     }
301 
302     ctx->generator = napiGenerator->GetAsyKeyGenerator();
303     ctx->params = nullptr;
304     ctx->pubKey = pubKey;
305     ctx->priKey = priKey;
306 
307     if (napi_create_reference(env, thisVar, 1, &ctx->generatorRef) != napi_ok) {
308         LOGE("create generator ref failed when convert asym key!");
309         return false;
310     }
311 
312     if (ctx->asyncType == ASYNC_PROMISE) {
313         napi_create_promise(env, &ctx->deferred, &ctx->promise);
314         return true;
315     } else {
316         return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
317     }
318 }
319 
BuildConvertPemKeyCtx(napi_env env,napi_callback_info info,ConvertPemKeyCtx * ctx)320 static bool BuildConvertPemKeyCtx(napi_env env, napi_callback_info info, ConvertPemKeyCtx *ctx)
321 {
322     napi_value thisVar = nullptr;
323     size_t expectedArgc = PARAMS_NUM_TWO;
324     size_t argc = expectedArgc;
325     napi_value argv[PARAMS_NUM_TWO] = { nullptr };
326     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
327     if (argc != expectedArgc) {
328         LOGE("wrong argument num. require %zu arguments. [Argc]: %zu!", expectedArgc, argc);
329         return false;
330     }
331     NapiAsyKeyGenerator *napiGenerator = nullptr;
332     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiGenerator));
333     if (status != napi_ok || napiGenerator == nullptr) {
334         LOGE("failed to unwrap napi asyKeyGenerator obj.");
335         return false;
336     }
337     std::string pubKey = "";
338     std::string priKey = "";
339     if (!GetPkAndSkStringFromNapiValueIfInput(env, argv[PARAM0], argv[PARAM1], pubKey, priKey)) {
340         LOGE("GetPkAndSkStringFromNapiValueIfInput failed.");
341         return false;
342     }
343     ctx->generator = napiGenerator->GetAsyKeyGenerator();
344     ctx->params = nullptr;
345     ctx->pubKey = pubKey;
346     ctx->priKey = priKey;
347     if (napi_create_reference(env, thisVar, 1, &ctx->generatorRef) != napi_ok) {
348         LOGE("create generator ref failed when convert pem asym key!");
349         return false;
350     }
351     napi_create_promise(env, &ctx->deferred, &ctx->promise);
352     return true;
353 }
354 
ReturnGenKeyPairCallbackResult(napi_env env,GenKeyPairCtx * ctx,napi_value result)355 static void ReturnGenKeyPairCallbackResult(napi_env env, GenKeyPairCtx *ctx, napi_value result)
356 {
357     napi_value businessError = nullptr;
358     if (ctx->errCode != HCF_SUCCESS) {
359         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
360     }
361 
362     napi_value params[ARGS_SIZE_TWO] = { businessError, result };
363 
364     napi_value func = nullptr;
365     napi_get_reference_value(env, ctx->callback, &func);
366 
367     napi_value recv = nullptr;
368     napi_value callFuncRet = nullptr;
369     napi_get_undefined(env, &recv);
370     napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
371 }
372 
ReturnGenKeyPairPromiseResult(napi_env env,GenKeyPairCtx * ctx,napi_value result)373 static void ReturnGenKeyPairPromiseResult(napi_env env, GenKeyPairCtx *ctx, napi_value result)
374 {
375     if (ctx->errCode == HCF_SUCCESS) {
376         napi_resolve_deferred(env, ctx->deferred, result);
377     } else {
378         napi_reject_deferred(env, ctx->deferred,
379             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
380     }
381 }
382 
ReturnConvertKeyCallbackResult(napi_env env,ConvertKeyCtx * ctx,napi_value result)383 static void ReturnConvertKeyCallbackResult(napi_env env, ConvertKeyCtx *ctx, napi_value result)
384 {
385     napi_value businessError = nullptr;
386     if (ctx->errCode != HCF_SUCCESS) {
387         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
388     }
389 
390     napi_value params[ARGS_SIZE_TWO] = { businessError, result };
391 
392     napi_value func = nullptr;
393     napi_get_reference_value(env, ctx->callback, &func);
394 
395     napi_value recv = nullptr;
396     napi_value callFuncRet = nullptr;
397     napi_get_undefined(env, &recv);
398     napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
399 }
400 
ReturnConvertKeyPromiseResult(napi_env env,ConvertKeyCtx * ctx,napi_value result)401 static void ReturnConvertKeyPromiseResult(napi_env env, ConvertKeyCtx *ctx, napi_value result)
402 {
403     if (ctx->errCode == HCF_SUCCESS) {
404         napi_resolve_deferred(env, ctx->deferred, result);
405     } else {
406         napi_reject_deferred(env, ctx->deferred,
407             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
408     }
409 }
410 
ReturnConvertPemKeyPromiseResult(napi_env env,ConvertPemKeyCtx * ctx,napi_value result)411 static void ReturnConvertPemKeyPromiseResult(napi_env env, ConvertPemKeyCtx *ctx, napi_value result)
412 {
413     if (ctx->errCode == HCF_SUCCESS) {
414         napi_resolve_deferred(env, ctx->deferred, result);
415     } else {
416         napi_reject_deferred(env, ctx->deferred,
417             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
418     }
419 }
420 
GenKeyPairAsyncWorkProcess(napi_env env,void * data)421 static void GenKeyPairAsyncWorkProcess(napi_env env, void *data)
422 {
423     GenKeyPairCtx *ctx = static_cast<GenKeyPairCtx *>(data);
424 
425     ctx->errCode = ctx->generator->generateKeyPair(ctx->generator, ctx->params, &(ctx->returnKeyPair));
426     if (ctx->errCode != HCF_SUCCESS) {
427         LOGD("[error] generate key pair fail.");
428         ctx->errMsg = "generate key pair fail.";
429     }
430 }
431 
GenKeyPairAsyncWorkReturn(napi_env env,napi_status status,void * data)432 static void GenKeyPairAsyncWorkReturn(napi_env env, napi_status status, void *data)
433 {
434     GenKeyPairCtx *ctx = static_cast<GenKeyPairCtx *>(data);
435 
436     napi_value instance = nullptr;
437     if (ctx->errCode == HCF_SUCCESS) {
438         NapiKeyPair *napiKeyPair = new (std::nothrow) NapiKeyPair(ctx->returnKeyPair);
439         if (napiKeyPair == nullptr) {
440             napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi key pair failed!"));
441             LOGE("new napi key pair failed");
442             FreeGenKeyPairCtx(env, ctx);
443             return;
444         }
445         instance = napiKeyPair->ConvertToJsKeyPair(env);
446 
447         napi_status ret = napi_wrap(
448             env, instance, napiKeyPair,
449             [](napi_env env, void *data, void *hint) {
450                 NapiKeyPair *keyPair = static_cast<NapiKeyPair *>(data);
451                 delete keyPair;
452                 return;
453             }, nullptr, nullptr);
454         if (ret != napi_ok) {
455             LOGE("failed to wrap napiKeyPair obj!");
456             ctx->errCode = HCF_INVALID_PARAMS;
457             ctx->errMsg = "failed to wrap napiKeyPair obj!";
458             delete napiKeyPair;
459         }
460     }
461 
462     if (ctx->asyncType == ASYNC_CALLBACK) {
463         ReturnGenKeyPairCallbackResult(env, ctx, instance);
464     } else {
465         ReturnGenKeyPairPromiseResult(env, ctx, instance);
466     }
467     FreeGenKeyPairCtx(env, ctx);
468 }
469 
ConvertKeyAsyncWorkProcess(napi_env env,void * data)470 static void ConvertKeyAsyncWorkProcess(napi_env env, void *data)
471 {
472     ConvertKeyCtx *ctx = static_cast<ConvertKeyCtx *>(data);
473 
474     ctx->errCode = ctx->generator->convertKey(ctx->generator, ctx->params,
475         ctx->pubKey, ctx->priKey, &(ctx->returnKeyPair));
476     if (ctx->errCode != HCF_SUCCESS) {
477         LOGD("[error] convert key fail.");
478         ctx->errMsg = "convert key fail.";
479     }
480 }
481 
ConvertPemKeyAsyncWorkProcess(napi_env env,void * data)482 static void ConvertPemKeyAsyncWorkProcess(napi_env env, void *data)
483 {
484     ConvertPemKeyCtx *ctx = static_cast<ConvertPemKeyCtx *>(data);
485     ctx->errCode = ctx->generator->convertPemKey(ctx->generator, ctx->params,
486             ctx->pubKey.c_str(), ctx->priKey.c_str(), &(ctx->returnKeyPair));
487     if (ctx->errCode != HCF_SUCCESS) {
488         LOGE("ConvertPemKey fail.");
489         ctx->errMsg = "ConvertPemKey fail.";
490     }
491 }
492 
ConvertKeyAsyncWorkReturn(napi_env env,napi_status status,void * data)493 static void ConvertKeyAsyncWorkReturn(napi_env env, napi_status status, void *data)
494 {
495     ConvertKeyCtx *ctx = static_cast<ConvertKeyCtx *>(data);
496 
497     napi_value instance = nullptr;
498     if (ctx->errCode == HCF_SUCCESS) {
499         NapiKeyPair *napiKeyPair = new (std::nothrow) NapiKeyPair(ctx->returnKeyPair);
500         if (napiKeyPair == nullptr) {
501             napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi key pair failed!"));
502             LOGE("new napi key pair failed");
503             FreeConvertKeyCtx(env, ctx);
504             return;
505         }
506         instance = napiKeyPair->ConvertToJsKeyPair(env);
507 
508         napi_status ret = napi_wrap(
509             env, instance, napiKeyPair,
510             [](napi_env env, void *data, void *hint) {
511                 NapiKeyPair *keyPair = static_cast<NapiKeyPair *>(data);
512                 delete keyPair;
513                 return;
514             }, nullptr, nullptr);
515         if (ret != napi_ok) {
516             LOGE("failed to wrap napiKeyPair obj!");
517             ctx->errCode = HCF_INVALID_PARAMS;
518             ctx->errMsg = "failed to wrap napiKeyPair obj!";
519             delete napiKeyPair;
520         }
521     }
522 
523     if (ctx->asyncType == ASYNC_CALLBACK) {
524         ReturnConvertKeyCallbackResult(env, ctx, instance);
525     } else {
526         ReturnConvertKeyPromiseResult(env, ctx, instance);
527     }
528     FreeConvertKeyCtx(env, ctx);
529 }
530 
ConvertPemKeyAsyncWorkReturn(napi_env env,napi_status status,void * data)531 static void ConvertPemKeyAsyncWorkReturn(napi_env env, napi_status status, void *data)
532 {
533     ConvertPemKeyCtx *ctx = static_cast<ConvertPemKeyCtx *>(data);
534 
535     napi_value instance = nullptr;
536     if (ctx->errCode == HCF_SUCCESS) {
537         NapiKeyPair *napiKeyPair = new (std::nothrow) NapiKeyPair(ctx->returnKeyPair);
538         if (napiKeyPair == nullptr) {
539             LOGE("new napi key pair failed.");
540             napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi key pair failed!"));
541             HcfObjDestroy(ctx->returnKeyPair);
542             ctx->returnKeyPair = nullptr;
543             FreeConvertPemKeyCtx(env, ctx);
544             return;
545         }
546         instance = napiKeyPair->ConvertToJsKeyPair(env);
547 
548         napi_status ret = napi_wrap(
549             env, instance, napiKeyPair,
550             [](napi_env env, void *data, void *hint) {
551                 NapiKeyPair *keyPair = static_cast<NapiKeyPair *>(data);
552                 delete keyPair;
553                 return;
554             }, nullptr, nullptr);
555         if (ret != napi_ok) {
556             LOGE("failed to wrap napiKeyPair obj!");
557             ctx->errCode = HCF_INVALID_PARAMS;
558             ctx->errMsg = "failed to wrap napiKeyPair obj!";
559             ctx->returnKeyPair = nullptr;
560             delete napiKeyPair;
561         }
562     }
563 
564     ReturnConvertPemKeyPromiseResult(env, ctx, instance);
565     FreeConvertPemKeyCtx(env, ctx);
566 }
567 
NewGenKeyPairAsyncWork(napi_env env,GenKeyPairCtx * ctx)568 static napi_value NewGenKeyPairAsyncWork(napi_env env, GenKeyPairCtx *ctx)
569 {
570     napi_value resourceName = nullptr;
571     napi_create_string_utf8(env, "generatorKeyPair", NAPI_AUTO_LENGTH, &resourceName);
572 
573     napi_create_async_work(
574         env, nullptr, resourceName,
575         [](napi_env env, void *data) {
576             GenKeyPairAsyncWorkProcess(env, data);
577             return;
578         },
579         [](napi_env env, napi_status status, void *data) {
580             GenKeyPairAsyncWorkReturn(env, status, data);
581             return;
582         },
583         static_cast<void *>(ctx),
584         &ctx->asyncWork);
585 
586     napi_queue_async_work(env, ctx->asyncWork);
587     if (ctx->asyncType == ASYNC_PROMISE) {
588         return ctx->promise;
589     } else {
590         return NapiGetNull(env);
591     }
592 }
593 
NewConvertKeyAsyncWork(napi_env env,ConvertKeyCtx * ctx)594 static napi_value NewConvertKeyAsyncWork(napi_env env, ConvertKeyCtx *ctx)
595 {
596     napi_value resourceName = nullptr;
597     napi_create_string_utf8(env, "convertKey", NAPI_AUTO_LENGTH, &resourceName);
598 
599     napi_create_async_work(
600         env, nullptr, resourceName,
601         [](napi_env env, void *data) {
602             ConvertKeyAsyncWorkProcess(env, data);
603             return;
604         },
605         [](napi_env env, napi_status status, void *data) {
606             ConvertKeyAsyncWorkReturn(env, status, data);
607             return;
608         },
609         static_cast<void *>(ctx),
610         &ctx->asyncWork);
611 
612     napi_queue_async_work(env, ctx->asyncWork);
613     if (ctx->asyncType == ASYNC_PROMISE) {
614         return ctx->promise;
615     } else {
616         return NapiGetNull(env);
617     }
618 }
619 
NewConvertPemKeyAsyncWork(napi_env env,ConvertPemKeyCtx * ctx)620 static napi_value NewConvertPemKeyAsyncWork(napi_env env, ConvertPemKeyCtx *ctx)
621 {
622     napi_value resourceName = nullptr;
623     napi_create_string_utf8(env, "convertPemKey", NAPI_AUTO_LENGTH, &resourceName);
624     napi_create_async_work(
625         env, nullptr, resourceName,
626         [](napi_env env, void *data) {
627             ConvertPemKeyAsyncWorkProcess(env, data);
628             return;
629         },
630         [](napi_env env, napi_status status, void *data) {
631             ConvertPemKeyAsyncWorkReturn(env, status, data);
632             return;
633         },
634         static_cast<void *>(ctx),
635         &ctx->asyncWork);
636 
637     napi_queue_async_work(env, ctx->asyncWork);
638     return ctx->promise;
639 }
640 
NapiAsyKeyGenerator(HcfAsyKeyGenerator * generator)641 NapiAsyKeyGenerator::NapiAsyKeyGenerator(HcfAsyKeyGenerator *generator)
642 {
643     this->generator_ = generator;
644 }
645 
~NapiAsyKeyGenerator()646 NapiAsyKeyGenerator::~NapiAsyKeyGenerator()
647 {
648     HcfObjDestroy(this->generator_);
649 }
650 
GetAsyKeyGenerator()651 HcfAsyKeyGenerator *NapiAsyKeyGenerator::GetAsyKeyGenerator()
652 {
653     return this->generator_;
654 }
655 
JsGenerateKeyPair(napi_env env,napi_callback_info info)656 napi_value NapiAsyKeyGenerator::JsGenerateKeyPair(napi_env env, napi_callback_info info)
657 {
658     GenKeyPairCtx *ctx = static_cast<GenKeyPairCtx *>(HcfMalloc(sizeof(GenKeyPairCtx), 0));
659     if (ctx == nullptr) {
660         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "malloc ctx fail."));
661         LOGE("create context fail.");
662         return nullptr;
663     }
664 
665     if (!BuildGenKeyPairCtx(env, info, ctx)) {
666         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
667         LOGE("build context fail.");
668         FreeGenKeyPairCtx(env, ctx);
669         return nullptr;
670     }
671 
672     return NewGenKeyPairAsyncWork(env, ctx);
673 }
674 
GetHcfKeyPairInstance(napi_env env,HcfKeyPair * returnKeyPair,napi_value * instance)675 static bool GetHcfKeyPairInstance(napi_env env, HcfKeyPair *returnKeyPair, napi_value *instance)
676 {
677     NapiKeyPair *napiKeyPair = new (std::nothrow) NapiKeyPair(returnKeyPair);
678     if (napiKeyPair == nullptr) {
679         HcfObjDestroy(returnKeyPair);
680         LOGE("new napi key pair failed");
681         return false;
682     }
683 
684     *instance = napiKeyPair->ConvertToJsKeyPair(env);
685     napi_status ret = napi_wrap(
686         env, *instance, napiKeyPair,
687         [](napi_env env, void *data, void *hint) {
688             NapiKeyPair *keyPair = static_cast<NapiKeyPair *>(data);
689             delete keyPair;
690             return;
691         }, nullptr, nullptr);
692     if (ret != napi_ok) {
693         LOGE("failed to wrap napiKeyPair obj!");
694         delete napiKeyPair;
695         return false;
696     }
697 
698     return true;
699 }
700 
JsGenerateKeyPairSync(napi_env env,napi_callback_info info)701 napi_value NapiAsyKeyGenerator::JsGenerateKeyPairSync(napi_env env, napi_callback_info info)
702 {
703     napi_value thisVar = nullptr;
704     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
705 
706     NapiAsyKeyGenerator *napiGenerator = nullptr;
707     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiGenerator));
708     if (status != napi_ok || napiGenerator == nullptr) {
709         LOGE("failed to unwrap napi asyKeyGenerator obj.");
710         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napi asyKeyGenerator obj."));
711         return nullptr;
712     }
713 
714     HcfAsyKeyGenerator *generator = napiGenerator->GetAsyKeyGenerator();
715     if (generator == nullptr) {
716         LOGE("get generator fail.");
717         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get generator fail!"));
718         return nullptr;
719     }
720 
721     HcfParamsSpec *params = nullptr;
722     HcfKeyPair *returnKeyPair = nullptr;
723     HcfResult errCode = generator->generateKeyPair(generator, params, &returnKeyPair);
724     if (errCode != HCF_SUCCESS) {
725         LOGE("generate key pair fail.");
726         napi_throw(env, GenerateBusinessError(env, errCode, "generate key pair fail."));
727         return nullptr;
728     }
729 
730     napi_value instance = nullptr;
731     if (!GetHcfKeyPairInstance(env, returnKeyPair, &instance)) {
732         LOGE("failed to get generate key pair instance!");
733         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "failed to get generate key pair instance!"));
734         return nullptr;
735     }
736 
737     return instance;
738 }
739 
JsConvertKey(napi_env env,napi_callback_info info)740 napi_value NapiAsyKeyGenerator::JsConvertKey(napi_env env, napi_callback_info info)
741 {
742     ConvertKeyCtx *ctx = static_cast<ConvertKeyCtx *>(HcfMalloc(sizeof(ConvertKeyCtx), 0));
743     if (ctx == nullptr) {
744         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail!"));
745         LOGE("create context fail.");
746         return nullptr;
747     }
748 
749     if (!BuildConvertKeyCtx(env, info, ctx)) {
750         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
751         LOGE("build context fail.");
752         FreeConvertKeyCtx(env, ctx);
753         return nullptr;
754     }
755 
756     return NewConvertKeyAsyncWork(env, ctx);
757 }
758 
HcfFreePubKeyAndPriKey(HcfBlob * pubKey,HcfBlob * priKey)759 static void HcfFreePubKeyAndPriKey(HcfBlob *pubKey, HcfBlob *priKey)
760 {
761     HcfBlobDataFree(pubKey);
762     HcfFree(pubKey);
763     HcfBlobDataClearAndFree(priKey);
764     HcfFree(priKey);
765 }
766 
JsConvertKeySync(napi_env env,napi_callback_info info)767 napi_value NapiAsyKeyGenerator::JsConvertKeySync(napi_env env, napi_callback_info info)
768 {
769     napi_value thisVar = nullptr;
770     size_t argc = PARAMS_NUM_TWO;
771     napi_value argv[PARAMS_NUM_TWO] = { nullptr };
772     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
773     if (argc != PARAMS_NUM_TWO) {
774         LOGE("wrong argument num. require %d arguments. [Argc]: %zu!", PARAMS_NUM_TWO, argc);
775         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "wrong argument num."));
776         return nullptr;
777     }
778 
779     NapiAsyKeyGenerator *napiGenerator = nullptr;
780     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiGenerator));
781     if (status != napi_ok || napiGenerator == nullptr) {
782         LOGE("failed to unwrap napi asyKeyGenerator obj.");
783         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napi asyKeyGenerator obj."));
784         return nullptr;
785     }
786 
787     HcfBlob *pubKey = nullptr;
788     HcfBlob *priKey = nullptr;
789     if (!GetPkAndSkBlobFromNapiValueIfInput(env, argv[PARAM0], argv[PARAM1], &pubKey, &priKey)) {
790         LOGE("failed to unwrap napi asyKeyGenerator obj.");
791         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napi asyKeyGenerator obj."));
792         return nullptr;
793     }
794 
795     HcfAsyKeyGenerator *generator = napiGenerator->GetAsyKeyGenerator();
796     if (generator == nullptr) {
797         HcfFreePubKeyAndPriKey(pubKey, priKey);
798         LOGE("get generator fail.");
799         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get generator fail!"));
800         return nullptr;
801     }
802 
803     HcfParamsSpec *params = nullptr;
804     HcfKeyPair *returnKeyPair = nullptr;
805     HcfResult errCode = generator->convertKey(generator, params, pubKey, priKey, &(returnKeyPair));
806     HcfFreePubKeyAndPriKey(pubKey, priKey);
807     if (errCode != HCF_SUCCESS) {
808         LOGE("convert key fail.");
809         napi_throw(env, GenerateBusinessError(env, errCode, "convert key fail."));
810         return nullptr;
811     }
812 
813     napi_value instance = nullptr;
814     if (!GetHcfKeyPairInstance(env, returnKeyPair, &instance)) {
815         LOGE("failed to get convert key instance!");
816         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "failed to get convert key instance!"));
817         return nullptr;
818     }
819 
820     return instance;
821 }
822 
JsConvertPemKey(napi_env env,napi_callback_info info)823 napi_value NapiAsyKeyGenerator::JsConvertPemKey(napi_env env, napi_callback_info info)
824 {
825     ConvertPemKeyCtx *ctx = static_cast<ConvertPemKeyCtx *>(HcfMalloc(sizeof(ConvertPemKeyCtx), 0));
826     if (ctx == nullptr) {
827         LOGE("create context fail.");
828         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail!"));
829         return nullptr;
830     }
831     if (!BuildConvertPemKeyCtx(env, info, ctx)) {
832         LOGE("build context fail.");
833         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
834         FreeConvertPemKeyCtx(env, ctx);
835         return nullptr;
836     }
837     return NewConvertPemKeyAsyncWork(env, ctx);
838 }
839 
ConvertPemKeySync(std::string & pubKey,std::string & priKey,HcfAsyKeyGenerator * generator,HcfKeyPair ** returnKeyPair)840 static HcfResult ConvertPemKeySync(std::string &pubKey,  std::string &priKey, HcfAsyKeyGenerator *generator,
841     HcfKeyPair **returnKeyPair)
842 {
843     HcfResult errCode = generator->convertPemKey(generator, nullptr,
844            pubKey.c_str(), priKey.c_str(), returnKeyPair);
845     if (errCode != HCF_SUCCESS) {
846         LOGE("convertPemKey error!");
847         return errCode;
848     }
849     return HCF_SUCCESS;
850 }
851 
JsConvertPemKeySync(napi_env env,napi_callback_info info)852 napi_value NapiAsyKeyGenerator::JsConvertPemKeySync(napi_env env, napi_callback_info info)
853 {
854     napi_value thisVar = nullptr;
855     size_t expectedArgc = PARAMS_NUM_TWO;
856     size_t argc = expectedArgc;
857     napi_value argv[PARAMS_NUM_TWO] = { nullptr };
858     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
859     if (argc != expectedArgc) {
860         LOGE("wrong argument num. require %zu arguments. [Argc]: %zu!", expectedArgc, argc);
861         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "invalid parameters."));
862         return nullptr;
863     }
864 
865     NapiAsyKeyGenerator *napiGenerator = nullptr;
866     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiGenerator));
867     if (status != napi_ok || napiGenerator == nullptr) {
868         LOGE("failed to unwrap napi asyKeyGenerator obj.");
869         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napi asyKeyGenerator obj."));
870         return nullptr;
871     }
872 
873     std::string pubKey = "";
874     std::string priKey = "";
875     if (!GetPkAndSkStringFromNapiValueIfInput(env, argv[PARAM0], argv[PARAM1], pubKey, priKey)) {
876         LOGE("GetPkAndSkStringFromNapiValueIfInput failed.");
877         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "GetPkAndSkStringFromNapiValueIfInput failed."));
878         return nullptr;
879     }
880 
881     HcfAsyKeyGenerator *generator = napiGenerator->GetAsyKeyGenerator();
882     if (generator == nullptr) {
883         LOGE("GetAsyKeyGenerator failed!");
884         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "GetAsyKeyGenerator failed!"));
885         return nullptr;
886     }
887 
888     HcfKeyPair *returnKeyPair = nullptr;
889     HcfResult errCode = ConvertPemKeySync(pubKey, priKey, generator, &(returnKeyPair));
890     if (errCode != HCF_SUCCESS) {
891         LOGE("ConvertPemKeySync error!");
892         napi_throw(env, GenerateBusinessError(env, errCode, "ConvertPemKeySync error!"));
893         return nullptr;
894     }
895 
896     NapiKeyPair *napiKeyPair = new (std::nothrow) NapiKeyPair(returnKeyPair);
897     if (napiKeyPair == nullptr) {
898         LOGE("new napi key pair failed");
899         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "malloc context failed."));
900         HcfObjDestroy(returnKeyPair);
901         returnKeyPair = nullptr;
902         return nullptr;
903     }
904 
905     napi_value instance = napiKeyPair->ConvertToJsKeyPair(env);
906     return instance;
907 }
908 
AsyKeyGeneratorConstructor(napi_env env,napi_callback_info info)909 napi_value NapiAsyKeyGenerator::AsyKeyGeneratorConstructor(napi_env env, napi_callback_info info)
910 {
911     napi_value thisVar = nullptr;
912     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
913     return thisVar;
914 }
915 
NapiWrapAsyKeyGen(napi_env env,napi_value instance,NapiAsyKeyGenerator * napiAsyKeyGenerator)916 static napi_value NapiWrapAsyKeyGen(napi_env env, napi_value instance, NapiAsyKeyGenerator *napiAsyKeyGenerator)
917 {
918     napi_status status = napi_wrap(
919         env, instance, napiAsyKeyGenerator,
920         [](napi_env env, void *data, void *hint) {
921             NapiAsyKeyGenerator *napiAsyKeyGenerator = static_cast<NapiAsyKeyGenerator *>(data);
922             delete napiAsyKeyGenerator;
923             return;
924         }, nullptr, nullptr);
925     if (status != napi_ok) {
926         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to wrap napiAsyKeyGenerator obj!"));
927         delete napiAsyKeyGenerator;
928         napiAsyKeyGenerator = nullptr;
929         LOGE("failed to wrap napiAsyKeyGenerator obj!");
930         return nullptr;
931     }
932     return instance;
933 }
934 
CreateJsAsyKeyGenerator(napi_env env,napi_callback_info info)935 napi_value NapiAsyKeyGenerator::CreateJsAsyKeyGenerator(napi_env env, napi_callback_info info)
936 {
937     size_t expectedArgc = PARAMS_NUM_ONE;
938     size_t argc = expectedArgc;
939     napi_value argv[PARAMS_NUM_ONE] = { nullptr };
940     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
941     if (argc != expectedArgc) {
942         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
943         LOGE("The input args num is invalid.");
944         return NapiGetNull(env);
945     }
946 
947     napi_value instance;
948     napi_value constructor = nullptr;
949     napi_get_reference_value(env, classRef_, &constructor);
950     napi_new_instance(env, constructor, argc, argv, &instance);
951 
952     std::string algName;
953     if (!GetStringFromJSParams(env, argv[0], algName)) {
954         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get algoName."));
955         LOGE("failed to get algoName.");
956         return NapiGetNull(env);
957     }
958 
959     HcfAsyKeyGenerator *generator = nullptr;
960     HcfResult res = HcfAsyKeyGeneratorCreate(algName.c_str(), &generator);
961     if (res != HCF_SUCCESS) {
962         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "create c generator fail."));
963         LOGE("create c generator fail.");
964         return NapiGetNull(env);
965     }
966 
967     NapiAsyKeyGenerator *napiAsyKeyGenerator = new (std::nothrow) NapiAsyKeyGenerator(generator);
968     if (napiAsyKeyGenerator == nullptr) {
969         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi asy key napi generator failed!"));
970         LOGE("new napi asy key napi generator failed");
971         HcfObjDestroy(generator);
972         return NapiGetNull(env);
973     }
974 
975     napi_value napiAlgName = nullptr;
976     napi_create_string_utf8(env, algName.c_str(), NAPI_AUTO_LENGTH, &napiAlgName);
977     napi_set_named_property(env, instance, CRYPTO_TAG_ALG_NAME.c_str(), napiAlgName);
978 
979     return NapiWrapAsyKeyGen(env, instance, napiAsyKeyGenerator);
980 }
981 
DefineAsyKeyGeneratorJSClass(napi_env env,napi_value exports)982 void NapiAsyKeyGenerator::DefineAsyKeyGeneratorJSClass(napi_env env, napi_value exports)
983 {
984     napi_property_descriptor desc[] = {
985         DECLARE_NAPI_FUNCTION("createAsyKeyGenerator", NapiAsyKeyGenerator::CreateJsAsyKeyGenerator),
986     };
987     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
988 
989     napi_property_descriptor classDesc[] = {
990         DECLARE_NAPI_FUNCTION("generateKeyPair", NapiAsyKeyGenerator::JsGenerateKeyPair),
991         DECLARE_NAPI_FUNCTION("generateKeyPairSync", NapiAsyKeyGenerator::JsGenerateKeyPairSync),
992         DECLARE_NAPI_FUNCTION("convertKey", NapiAsyKeyGenerator::JsConvertKey),
993         DECLARE_NAPI_FUNCTION("convertKeySync", NapiAsyKeyGenerator::JsConvertKeySync),
994         DECLARE_NAPI_FUNCTION("convertPemKey", NapiAsyKeyGenerator::JsConvertPemKey),
995         DECLARE_NAPI_FUNCTION("convertPemKeySync", NapiAsyKeyGenerator::JsConvertPemKeySync),
996     };
997     napi_value constructor = nullptr;
998     napi_define_class(env, "AsyKeyGenerator", NAPI_AUTO_LENGTH, NapiAsyKeyGenerator::AsyKeyGeneratorConstructor,
999         nullptr, sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
1000     napi_create_reference(env, constructor, 1, &classRef_);
1001 }
1002 } // CryptoFramework
1003 } // OHOS
1004