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