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], &paramsSpec)) {
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