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