1 /*
2 * Copyright (C) 2023-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_kdf.h"
17
18 #include "securec.h"
19 #include "memory.h"
20
21 #include "napi_utils.h"
22 #include "napi_crypto_framework_defines.h"
23 #include "detailed_pbkdf2_params.h"
24 #include "detailed_hkdf_params.h"
25
26 #define PBKDF2_ALG_SIZE 6
27
28 namespace OHOS {
29 namespace CryptoFramework {
30 thread_local napi_ref NapiKdf::classRef_ = nullptr;
31
32 struct KdfCtx {
33 napi_env env = nullptr;
34
35 AsyncType asyncType = ASYNC_CALLBACK;
36 napi_ref callback = nullptr;
37 napi_deferred deferred = nullptr;
38 napi_value promise = nullptr;
39 napi_async_work asyncWork = nullptr;
40 napi_ref kdfRef = nullptr;
41
42 HcfResult errCode = HCF_SUCCESS;
43 const char *errMsg = nullptr;
44 HcfKdfParamsSpec *paramsSpec = nullptr;
45 HcfKdf *kdf = nullptr;
46 };
47
FreeKdfParamsSpec(HcfKdfParamsSpec * params)48 static void FreeKdfParamsSpec(HcfKdfParamsSpec *params)
49 {
50 if (params == nullptr) {
51 return;
52 }
53 if (PBKDF2_ALG_NAME.compare(params->algName) == 0) {
54 HcfPBKDF2ParamsSpec *tmp = reinterpret_cast<HcfPBKDF2ParamsSpec *>(params);
55 HcfBlobDataClearAndFree(&(tmp->password));
56 HcfBlobDataClearAndFree(&(tmp->salt));
57 HcfBlobDataClearAndFree(&(tmp->output));
58 tmp->base.algName = nullptr;
59 } else if (HKDF_ALG_NAME.compare(params->algName) == 0) {
60 HcfHkdfParamsSpec *tmp = reinterpret_cast<HcfHkdfParamsSpec *>(params);
61 HcfBlobDataClearAndFree(&(tmp->key));
62 HcfBlobDataClearAndFree(&(tmp->salt));
63 HcfBlobDataClearAndFree(&(tmp->info));
64 HcfBlobDataClearAndFree(&(tmp->output));
65 tmp->base.algName = nullptr;
66 }
67 HcfFree(params);
68 }
69
FreeCryptoFwkCtx(napi_env env,KdfCtx * context)70 static void FreeCryptoFwkCtx(napi_env env, KdfCtx *context)
71 {
72 if (context == nullptr) {
73 return;
74 }
75 if (context->asyncWork != nullptr) {
76 napi_delete_async_work(env, context->asyncWork);
77 context->asyncWork = nullptr;
78 }
79
80 if (context->callback != nullptr) {
81 napi_delete_reference(env, context->callback);
82 context->callback = nullptr;
83 }
84
85 if (context->kdfRef != nullptr) {
86 napi_delete_reference(env, context->kdfRef);
87 context->kdfRef = nullptr;
88 }
89
90 FreeKdfParamsSpec(context->paramsSpec);
91 context->paramsSpec = nullptr;
92 context->errMsg = nullptr;
93 context->kdf = nullptr;
94 HcfFree(context);
95 }
96
ReturnCallbackResult(napi_env env,KdfCtx * context,napi_value result)97 static void ReturnCallbackResult(napi_env env, KdfCtx *context, napi_value result)
98 {
99 napi_value businessError = nullptr;
100 if (context->errCode != HCF_SUCCESS) {
101 businessError = GenerateBusinessError(env, context->errCode, context->errMsg);
102 }
103 napi_value params[ARGS_SIZE_TWO] = { businessError, result };
104
105 napi_value func = nullptr;
106 napi_get_reference_value(env, context->callback, &func);
107
108 napi_value recv = nullptr;
109 napi_value callFuncRet = nullptr;
110 napi_get_undefined(env, &recv);
111 napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
112 }
113
ReturnPromiseResult(napi_env env,KdfCtx * context,napi_value result)114 static void ReturnPromiseResult(napi_env env, KdfCtx *context, napi_value result)
115 {
116 if (context->errCode == HCF_SUCCESS) {
117 napi_resolve_deferred(env, context->deferred, result);
118 } else {
119 napi_reject_deferred(env, context->deferred,
120 GenerateBusinessError(env, context->errCode, context->errMsg));
121 }
122 }
123
KdfGenSecretExecute(napi_env env,void * data)124 static void KdfGenSecretExecute(napi_env env, void *data)
125 {
126 KdfCtx *context = static_cast<KdfCtx *>(data);
127 HcfKdf *kdf = context->kdf;
128 context->errCode = kdf->generateSecret(kdf, context->paramsSpec);
129 if (context->errCode != HCF_SUCCESS) {
130 LOGD("[error] KDF generateSecret failed!");
131 context->errMsg = "KDF generateSecret failed";
132 return;
133 }
134 }
135
KdfGenSecretComplete(napi_env env,napi_status status,void * data)136 static void KdfGenSecretComplete(napi_env env, napi_status status, void *data)
137 {
138 KdfCtx *context = static_cast<KdfCtx *>(data);
139 napi_value returnBlob = nullptr;
140 if (PBKDF2_ALG_NAME.compare(context->paramsSpec->algName) == 0) {
141 HcfPBKDF2ParamsSpec *params = reinterpret_cast<HcfPBKDF2ParamsSpec *>(context->paramsSpec);
142 returnBlob = ConvertBlobToNapiValue(env, &(params->output));
143 } else if (HKDF_ALG_NAME.compare(context->paramsSpec->algName) == 0) {
144 HcfHkdfParamsSpec *params = reinterpret_cast<HcfHkdfParamsSpec *>(context->paramsSpec);
145 returnBlob = ConvertBlobToNapiValue(env, &(params->output));
146 }
147
148 if (returnBlob == nullptr) {
149 LOGE("returnOutBlob is nullptr!");
150 returnBlob = NapiGetNull(env);
151 }
152 if (context->asyncType == ASYNC_CALLBACK) {
153 ReturnCallbackResult(env, context, returnBlob);
154 } else {
155 ReturnPromiseResult(env, context, returnBlob);
156 }
157 FreeCryptoFwkCtx(env, context);
158 }
159
GetInt32FromKdfParams(napi_env env,napi_value arg,const std::string & name,int32_t & retInt)160 static bool GetInt32FromKdfParams(napi_env env, napi_value arg, const std::string &name, int32_t &retInt)
161 {
162 // int attribute
163 napi_value dataInt = nullptr;
164 napi_valuetype valueType = napi_undefined;
165 napi_status status = napi_get_named_property(env, arg, name.c_str(), &dataInt);
166 napi_typeof(env, dataInt, &valueType);
167 if ((status != napi_ok) || (dataInt == nullptr) || (valueType == napi_undefined)) {
168 LOGE("failed to get valid napi int");
169 return false;
170 }
171 return GetInt32FromJSParams(env, dataInt, retInt);
172 }
173
GetCharArrayFromUint8Arr(napi_env env,napi_value data,HcfBlob * retBlob)174 static bool GetCharArrayFromUint8Arr(napi_env env, napi_value data, HcfBlob *retBlob)
175 {
176 size_t length = 0;
177 size_t offset = 0;
178 void *rawData = nullptr;
179 napi_value arrayBuffer = nullptr;
180 napi_typedarray_type arrayType;
181 // Warning: Do not release the rawData returned by this interface because the rawData is managed by VM.
182 napi_status status = napi_get_typedarray_info(env, data, &arrayType, &length,
183 reinterpret_cast<void **>(&rawData), &arrayBuffer, &offset);
184 if ((status != napi_ok)) {
185 LOGE("failed to get valid rawData.");
186 return false;
187 }
188 if (arrayType != napi_uint8_array) {
189 LOGE("input data is not uint8 array.");
190 return false;
191 }
192 // input empty uint8Arr, ex: new Uint8Arr(), the length is 0 and rawData is nullptr;
193 if ((length == 0) || (rawData == nullptr)) {
194 LOGD("napi Uint8Arr is null");
195 return true;
196 }
197 if (length > INT_MAX) {
198 LOGE("Beyond the size");
199 return false;
200 }
201 uint8_t *tmp = static_cast<uint8_t *>(HcfMalloc(length, 0));
202 if (tmp == nullptr) {
203 LOGE("malloc blob data failed!");
204 return false;
205 }
206 (void)memcpy_s(tmp, length, rawData, length);
207 retBlob->data = tmp;
208 retBlob->len = length;
209 return true;
210 }
211
GetCharArrayFromJsString(napi_env env,napi_value arg,HcfBlob * retBlob)212 static bool GetCharArrayFromJsString(napi_env env, napi_value arg, HcfBlob *retBlob)
213 {
214 size_t length = 0;
215 if (napi_get_value_string_utf8(env, arg, nullptr, 0, &length) != napi_ok) {
216 LOGE("can not get char string length");
217 return false;
218 }
219 if (length > INT_MAX) {
220 LOGE("password length should not exceed INT_MAX");
221 return false;
222 }
223 if (length == 0) {
224 LOGD("empty string");
225 return true;
226 }
227 char *tmpPassword = static_cast<char *>(HcfMalloc(length + 1, 0));
228 if (tmpPassword == nullptr) {
229 LOGE("malloc string failed");
230 return false;
231 }
232 if (napi_get_value_string_utf8(env, arg, tmpPassword, (length + 1), &length) != napi_ok) {
233 LOGE("can not get char string value");
234 HcfFree(tmpPassword);
235 return false;
236 }
237 retBlob->data = reinterpret_cast<uint8_t *>(tmpPassword);
238 retBlob->len = length;
239 return true;
240 }
241
GetKeyOrPwdFromKdfParams(napi_env env,napi_value arg,const std::string & name,HcfBlob * retBlob)242 static bool GetKeyOrPwdFromKdfParams(napi_env env, napi_value arg, const std::string &name, HcfBlob *retBlob)
243 {
244 napi_value data = nullptr;
245 napi_valuetype valueType = napi_undefined;
246 napi_status status = napi_get_named_property(env, arg, name.c_str(), &data);
247 napi_typeof(env, data, &valueType);
248 if ((status != napi_ok) || (data == nullptr) || (valueType == napi_undefined)) {
249 LOGE("failed to get valid password");
250 return false;
251 }
252 if (valueType == napi_string) {
253 if (GetCharArrayFromJsString(env, data, retBlob) != true) {
254 LOGE("get char string failed");
255 return false;
256 }
257 } else {
258 if (GetCharArrayFromUint8Arr(env, data, retBlob) != true) {
259 LOGE("get uint8arr failed");
260 return false;
261 }
262 }
263 return true;
264 }
265
GetBlobFromKdfParamsSpec(napi_env env,napi_value arg,const std::string & name)266 static HcfBlob *GetBlobFromKdfParamsSpec(napi_env env, napi_value arg, const std::string &name)
267 {
268 // get uint8Array attribute
269 napi_value data = nullptr;
270 napi_valuetype valueType = napi_undefined;
271 napi_status status = napi_get_named_property(env, arg, name.c_str(), &data);
272 napi_typeof(env, data, &valueType);
273 if ((status != napi_ok) || (data == nullptr) || (valueType == napi_undefined)) {
274 LOGE("failed to get valid salt");
275 return nullptr;
276 }
277
278 return GetBlobFromNapiUint8Arr(env, data);
279 }
280
SetPBKDF2ParamsSpecAttribute(int iter,const HcfBlob & out,HcfBlob * salt,const HcfBlob & password,HcfPBKDF2ParamsSpec * tmp)281 static void SetPBKDF2ParamsSpecAttribute(int iter, const HcfBlob &out, HcfBlob *salt, const HcfBlob &password,
282 HcfPBKDF2ParamsSpec *tmp)
283 {
284 tmp->iterations = iter;
285 tmp->output = out;
286 tmp->salt.data = salt->data;
287 tmp->salt.len = salt->len;
288 tmp->password = password;
289 tmp->base.algName = PBKDF2_ALG_NAME.c_str();
290 }
291
SetHkdfParamsSpecAttribute(const HcfBlob & out,const HcfBlob * salt,const HcfBlob & key,const HcfBlob * info,HcfHkdfParamsSpec * tmpParams)292 static void SetHkdfParamsSpecAttribute(const HcfBlob &out, const HcfBlob *salt, const HcfBlob &key,
293 const HcfBlob *info, HcfHkdfParamsSpec *tmpParams)
294 {
295 tmpParams->output = out;
296 tmpParams->salt = *salt;
297 tmpParams->key = key;
298 tmpParams->info = *info;
299 tmpParams->base.algName = HKDF_ALG_NAME.c_str();
300 }
301
GetPBKDF2ParamsSpec(napi_env env,napi_value arg,HcfKdfParamsSpec ** params)302 static bool GetPBKDF2ParamsSpec(napi_env env, napi_value arg, HcfKdfParamsSpec **params)
303 {
304 // get attribute from params
305 // int attribute
306 int iter = -1;
307 int keySize = -1;
308 if (!GetInt32FromKdfParams(env, arg, PBKDF2_PARAMS_ITER, iter) ||
309 !GetInt32FromKdfParams(env, arg, KDF_PARAMS_KEY_SIZE, keySize)) {
310 LOGE("failed to get valid num");
311 return false;
312 }
313 if (iter <= 0 || keySize <= 0) {
314 LOGE("iter and keySize should larger than 0");
315 return false;
316 }
317 HcfBlob out = { .data = static_cast<uint8_t *>(HcfMalloc(keySize, 0)), .len = keySize };
318 if (out.data == nullptr) {
319 LOGE("output malloc failed!");
320 return false;
321 }
322 HcfBlob tmpPassword = { .data = nullptr, .len = 0 };
323 HcfBlob *salt = nullptr;
324 HcfPBKDF2ParamsSpec *tmp = nullptr;
325 do {
326 // get password
327 if (!GetKeyOrPwdFromKdfParams(env, arg, PBKDF2_PARAMS_PASSWORD, &tmpPassword)) {
328 LOGE("failed to get password");
329 break;
330 }
331 // get salt attribute
332 salt = GetBlobFromKdfParamsSpec(env, arg, KDF_PARAMS_SALT);
333 if (salt == nullptr) {
334 LOGE("fail to get salt");
335 break;
336 }
337 // malloc params
338 tmp = static_cast<HcfPBKDF2ParamsSpec *>(HcfMalloc(sizeof(HcfPBKDF2ParamsSpec), 0));
339 if (tmp == nullptr) {
340 LOGE("pbkdf2 spec malloc failed!");
341 break;
342 }
343 SetPBKDF2ParamsSpecAttribute(iter, out, salt, tmpPassword, tmp);
344 // only need the data and data length of the salt, so free the blob pointer.
345 HcfFree(salt);
346 *params = reinterpret_cast<HcfKdfParamsSpec *>(tmp);
347 return true;
348 } while (0);
349 HcfBlobDataClearAndFree(&tmpPassword);
350 HcfBlobDataClearAndFree(salt);
351 HcfFree(salt);
352 HcfFree(out.data);
353 return false;
354 }
355
GetHkdfParamsSpec(napi_env env,napi_value arg,HcfKdfParamsSpec ** params)356 static bool GetHkdfParamsSpec(napi_env env, napi_value arg, HcfKdfParamsSpec **params)
357 {
358 int keySize = -1;
359 if (!GetInt32FromKdfParams(env, arg, KDF_PARAMS_KEY_SIZE, keySize)) {
360 LOGE("failed to get valid num");
361 return false;
362 }
363 if (keySize <= 0) {
364 LOGE("keySize should larger than 0");
365 return false;
366 }
367 HcfBlob out = { .data = static_cast<uint8_t *>(HcfMalloc(keySize, 0)), .len = keySize };
368 if (out.data == nullptr) {
369 LOGE("output malloc failed!");
370 return false;
371 }
372
373 HcfBlob *salt = nullptr;
374 HcfBlob key = { .data = nullptr, .len = 0 };
375 HcfBlob *info = nullptr;
376 HcfHkdfParamsSpec *tmpParams = nullptr;
377 do {
378 // get key
379 if (!GetKeyOrPwdFromKdfParams(env, arg, HKDF_PARAMS_KEY, &key)) {
380 LOGE("failed to get key");
381 break;
382 }
383
384 // get info、salt
385 info = GetBlobFromKdfParamsSpec(env, arg, HKDF_PARAMS_INFO);
386 salt = GetBlobFromKdfParamsSpec(env, arg, KDF_PARAMS_SALT);
387 if (info == nullptr or salt == nullptr) {
388 LOGE("fail to get info or salt");
389 break;
390 }
391
392 // malloc tmpParams
393 tmpParams = static_cast<HcfHkdfParamsSpec *>(HcfMalloc(sizeof(HcfHkdfParamsSpec), 0));
394 if (tmpParams == nullptr) {
395 LOGE("hkdf spec malloc failed!");
396 break;
397 }
398 SetHkdfParamsSpecAttribute(out, salt, key, info, tmpParams);
399 // only need the data and data length of the salt, so free the blob pointer.
400 HcfFree(salt);
401 HcfFree(info);
402 *params = reinterpret_cast<HcfKdfParamsSpec *>(tmpParams);
403 return true;
404 } while (0);
405 HcfBlobDataClearAndFree(salt);
406 HcfBlobDataClearAndFree(&key);
407 HcfBlobDataClearAndFree(info);
408 HcfFree(salt);
409 HcfFree(info);
410 HcfFree(out.data);
411 return false;
412 }
413
GetKdfParamsSpec(napi_env env,napi_value arg,HcfKdfParamsSpec ** params)414 static bool GetKdfParamsSpec(napi_env env, napi_value arg, HcfKdfParamsSpec **params)
415 {
416 napi_value data = nullptr;
417 napi_valuetype valueType = napi_undefined;
418 if ((env == nullptr) || (arg == nullptr) || (params == nullptr)) {
419 LOGE("Invalid params!");
420 return false;
421 }
422
423 napi_status status = napi_get_named_property(env, arg, ALGO_PARAMS.c_str(), &data);
424 napi_typeof(env, data, &valueType);
425 if ((status != napi_ok) || (data == nullptr) || (valueType == napi_undefined)) {
426 LOGE("failed to get valid algo name!");
427 return false;
428 }
429 std::string algoName;
430 if (!GetStringFromJSParams(env, data, algoName)) {
431 LOGE("GetStringFromJSParams failed!");
432 return false;
433 }
434 if (algoName.compare(PBKDF2_ALG_NAME) == 0) {
435 return GetPBKDF2ParamsSpec(env, arg, params);
436 } else if (algoName.compare(HKDF_ALG_NAME) == 0) {
437 return GetHkdfParamsSpec(env, arg, params);
438 } else {
439 LOGE("Not support that alg");
440 return false;
441 }
442 }
443
BuildKdfGenSecretCtx(napi_env env,napi_callback_info info,KdfCtx * context)444 static bool BuildKdfGenSecretCtx(napi_env env, napi_callback_info info, KdfCtx *context)
445 {
446 napi_value thisVar = nullptr;
447 size_t expectedArgsCount = ARGS_SIZE_TWO;
448 size_t argc = expectedArgsCount;
449 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
450 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
451 if ((argc != expectedArgsCount) && (argc != expectedArgsCount - CALLBACK_SIZE)) {
452 LOGE("The arguments count is not expected!");
453 return false;
454 }
455
456 NapiKdf *napiKdf = nullptr;
457 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiKdf));
458 if (status != napi_ok || napiKdf == nullptr) {
459 LOGE("failed to unwrap NapiKdf obj!");
460 return false;
461 }
462
463 context->kdf = napiKdf->GetKdf();
464 if (!GetKdfParamsSpec(env, argv[PARAM0], &(context->paramsSpec))) {
465 LOGE("get kdf paramsspec failed!");
466 return false;
467 }
468 context->asyncType = isCallback(env, argv[expectedArgsCount - 1], argc, expectedArgsCount) ?
469 ASYNC_CALLBACK : ASYNC_PROMISE;
470
471 if (napi_create_reference(env, thisVar, 1, &context->kdfRef) != napi_ok) {
472 LOGE("create kdf ref failed when derive secret key using kdf!");
473 return false;
474 }
475
476 if (context->asyncType == ASYNC_PROMISE) {
477 napi_create_promise(env, &context->deferred, &context->promise);
478 return true;
479 } else {
480 return GetCallbackFromJSParams(env, argv[PARAM1], &context->callback);
481 }
482 }
483
NewKdfJsGenSecretAsyncWork(napi_env env,KdfCtx * context)484 static napi_value NewKdfJsGenSecretAsyncWork(napi_env env, KdfCtx *context)
485 {
486 napi_create_async_work(
487 env, nullptr, GetResourceName(env, "KdfGenerateSecret"),
488 [](napi_env env, void *data) {
489 KdfGenSecretExecute(env, data);
490 return;
491 },
492 [](napi_env env, napi_status status, void *data) {
493 KdfGenSecretComplete(env, status, data);
494 return;
495 },
496 static_cast<void *>(context),
497 &context->asyncWork);
498
499 napi_queue_async_work(env, context->asyncWork);
500 if (context->asyncType == ASYNC_PROMISE) {
501 return context->promise;
502 } else {
503 return NapiGetNull(env);
504 }
505 }
506
NapiKdf(HcfKdf * kdfObj)507 NapiKdf::NapiKdf(HcfKdf *kdfObj)
508 {
509 this->kdf = kdfObj;
510 }
511
~NapiKdf()512 NapiKdf::~NapiKdf()
513 {
514 HcfObjDestroy(this->kdf);
515 }
516
GetKdf() const517 HcfKdf *NapiKdf::GetKdf() const
518 {
519 return this->kdf;
520 }
521
JsKdfGenerateSecret(napi_env env,napi_callback_info info)522 napi_value NapiKdf::JsKdfGenerateSecret(napi_env env, napi_callback_info info)
523 {
524 KdfCtx *context = static_cast<KdfCtx *>(HcfMalloc(sizeof(KdfCtx), 0));
525 if (context == nullptr) {
526 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "malloc context failed"));
527 LOGE("malloc context failed!");
528 return nullptr;
529 }
530
531 if (!BuildKdfGenSecretCtx(env, info, context)) {
532 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
533 LOGE("build context fail.");
534 FreeCryptoFwkCtx(env, context);
535 return nullptr;
536 }
537
538 return NewKdfJsGenSecretAsyncWork(env, context);
539 }
540
NewKdfJsGenSecretSyncWork(napi_env env,HcfKdfParamsSpec * paramsSpec)541 static napi_value NewKdfJsGenSecretSyncWork(napi_env env, HcfKdfParamsSpec *paramsSpec)
542 {
543 napi_value returnBlob = nullptr;
544 if (PBKDF2_ALG_NAME.compare(paramsSpec->algName) == 0) {
545 HcfPBKDF2ParamsSpec *params = reinterpret_cast<HcfPBKDF2ParamsSpec *>(paramsSpec);
546 returnBlob = ConvertBlobToNapiValue(env, &(params->output));
547 } else if (HKDF_ALG_NAME.compare(paramsSpec->algName) == 0) {
548 HcfHkdfParamsSpec *params = reinterpret_cast<HcfHkdfParamsSpec *>(paramsSpec);
549 returnBlob = ConvertBlobToNapiValue(env, &(params->output));
550 }
551 if (returnBlob == nullptr) {
552 LOGE("returnBlob is nullptr!");
553 napi_throw(env, GenerateBusinessError(env, HCF_ERR_NAPI, "returnBlob is nullptr!"));
554 returnBlob = NapiGetNull(env);
555 }
556 FreeKdfParamsSpec(paramsSpec);
557 paramsSpec = nullptr;
558 return returnBlob;
559 }
560
JsKdfGenerateSecretSync(napi_env env,napi_callback_info info)561 napi_value NapiKdf::JsKdfGenerateSecretSync(napi_env env, napi_callback_info info)
562 {
563 napi_value thisVar = nullptr;
564 size_t argc = ARGS_SIZE_ONE;
565 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
566 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
567 if (argc != ARGS_SIZE_ONE) {
568 LOGE("The arguments count is not expected!");
569 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The arguments count is not expected!"));
570 return nullptr;
571 }
572 NapiKdf *napiKdf = nullptr;
573 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiKdf));
574 if (status != napi_ok || napiKdf == nullptr) {
575 LOGE("failed to unwrap NapiKdf obj!");
576 napi_throw(env, GenerateBusinessError(env, HCF_ERR_NAPI, "failed to unwrap NapiKdf obj!"));
577 return nullptr;
578 }
579 HcfKdf *kdf = napiKdf->GetKdf();
580 if (kdf == nullptr) {
581 LOGE("fail to get kdf obj!");
582 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "fail to get kdf obj!"));
583 return nullptr;
584 }
585 HcfKdfParamsSpec *paramsSpec = nullptr;
586 if (!GetKdfParamsSpec(env, argv[PARAM0], ¶msSpec)) {
587 LOGE("get kdf paramsspec failed!");
588 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get kdf paramsspec failed!"));
589 FreeKdfParamsSpec(paramsSpec);
590 paramsSpec = nullptr;
591 return nullptr;
592 }
593 HcfResult errCode = kdf->generateSecret(kdf, paramsSpec);
594 if (errCode != HCF_SUCCESS) {
595 LOGE("KDF generateSecret failed!");
596 napi_throw(env, GenerateBusinessError(env, errCode, "KDF generateSecret failed!"));
597 FreeKdfParamsSpec(paramsSpec);
598 return nullptr;
599 }
600 napi_value returnBlob = NewKdfJsGenSecretSyncWork(env, paramsSpec);
601 return returnBlob;
602 }
603
JsGetAlgorithm(napi_env env,napi_callback_info info)604 napi_value NapiKdf::JsGetAlgorithm(napi_env env, napi_callback_info info)
605 {
606 napi_value thisVar = nullptr;
607 NapiKdf *napiKdf = nullptr;
608
609 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
610 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiKdf));
611 if (status != napi_ok || napiKdf == nullptr) {
612 LOGE("failed to unwrap NapiKdf obj!");
613 return nullptr;
614 }
615
616 HcfKdf *kdf = napiKdf->GetKdf();
617 if (kdf == nullptr) {
618 LOGE("fail to get kdf obj!");
619 return nullptr;
620 }
621
622 const char *algoName = kdf->getAlgorithm(kdf);
623 napi_value instance = nullptr;
624 napi_create_string_utf8(env, algoName, NAPI_AUTO_LENGTH, &instance);
625 return instance;
626 }
627
KdfConstructor(napi_env env,napi_callback_info info)628 napi_value NapiKdf::KdfConstructor(napi_env env, napi_callback_info info)
629 {
630 napi_value thisVar = nullptr;
631 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
632 return thisVar;
633 }
634
CreateJsKdf(napi_env env,napi_callback_info info)635 napi_value NapiKdf::CreateJsKdf(napi_env env, napi_callback_info info)
636 {
637 size_t expectedArgc = ARGS_SIZE_ONE;
638 size_t argc = expectedArgc;
639 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
640 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
641 if (argc != expectedArgc) {
642 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
643 LOGE("The input args num is invalid.");
644 return nullptr;
645 }
646 std::string algoName;
647 if (!GetStringFromJSParams(env, argv[PARAM0], algoName)) {
648 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Failed to get algorithm."));
649 LOGE("Failed to get algorithm.");
650 return nullptr;
651 }
652 HcfKdf *kdf = nullptr;
653 HcfResult res = HcfKdfCreate(algoName.c_str(), &kdf);
654 if (res != HCF_SUCCESS) {
655 napi_throw(env, GenerateBusinessError(env, res, "create C obj failed."));
656 LOGE("create c kdf obj failed.");
657 return nullptr;
658 }
659 napi_value instance = nullptr;
660 napi_value constructor = nullptr;
661 napi_get_reference_value(env, classRef_, &constructor);
662 napi_new_instance(env, constructor, 0, nullptr, &instance);
663 NapiKdf *napiKdf = new (std::nothrow) NapiKdf(kdf);
664 if (napiKdf == nullptr) {
665 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new kdf napi obj failed."));
666 HcfObjDestroy(kdf);
667 LOGE("create kdf napi obj failed");
668 return nullptr;
669 }
670 napi_status status = napi_wrap(env, instance, napiKdf,
671 [](napi_env env, void *data, void *hint) {
672 NapiKdf *kdf = static_cast<NapiKdf *>(data);
673 delete kdf;
674 return;
675 }, nullptr, nullptr);
676 if (status != napi_ok) {
677 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to wrap NapiKdf obj!"));
678 delete napiKdf;
679 LOGE("failed to wrap NapiKdf obj!");
680 return nullptr;
681 }
682 return instance;
683 }
684
DefineKdfJSClass(napi_env env,napi_value exports)685 void NapiKdf::DefineKdfJSClass(napi_env env, napi_value exports)
686 {
687 napi_property_descriptor desc[] = {
688 DECLARE_NAPI_FUNCTION("createKdf", NapiKdf::CreateJsKdf),
689 };
690 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
691 napi_property_descriptor classDesc[] = {
692 DECLARE_NAPI_FUNCTION("generateSecret", NapiKdf::JsKdfGenerateSecret),
693 DECLARE_NAPI_FUNCTION("generateSecretSync", NapiKdf::JsKdfGenerateSecretSync),
694 {.utf8name = "algName", .getter = NapiKdf::JsGetAlgorithm},
695 };
696 napi_value constructor = nullptr;
697 napi_define_class(env, "Kdf", NAPI_AUTO_LENGTH, KdfConstructor, nullptr,
698 sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
699 napi_create_reference(env, constructor, 1, &classRef_);
700 }
701 } // CryptoFramework
702 } // OHOS
703