• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "huks_napi_common_item.h"
17 
18 #include <string>
19 #include <vector>
20 
21 #include "hks_errcode_adapter.h"
22 #include "hks_log.h"
23 #include "hks_param.h"
24 #include "hks_type.h"
25 #include "securec.h"
26 
27 namespace HuksNapiItem {
28 namespace {
29 constexpr int HKS_MAX_DATA_LEN = 0x6400000; // The maximum length is 100M
30 constexpr size_t ASYNCCALLBACK_ARGC = 2;
31 }  // namespace
32 
ParseKeyAlias(napi_env env,napi_value object,HksBlob * & alias)33 napi_value ParseKeyAlias(napi_env env, napi_value object, HksBlob *&alias)
34 {
35     napi_valuetype valueType = napi_valuetype::napi_undefined;
36     napi_status status = napi_typeof(env, object, &valueType);
37     if (status != napi_ok) {
38         HKS_LOG_E("could not get object type");
39         return nullptr;
40     }
41 
42     if (valueType != napi_valuetype::napi_string) {
43         napi_throw_error(env, std::to_string(HUKS_ERR_CODE_ILLEGAL_ARGUMENT).c_str(), "the type of alias isn't string");
44         HKS_LOG_E("no string type");
45         return nullptr;
46     }
47 
48     size_t length = 0;
49     status = napi_get_value_string_utf8(env, object, nullptr, 0, &length);
50     if (status != napi_ok) {
51         HKS_LOG_E("could not get string length");
52         return nullptr;
53     }
54 
55     if (length > HKS_MAX_DATA_LEN) {
56         napi_throw_error(env, std::to_string(HUKS_ERR_CODE_ILLEGAL_ARGUMENT).c_str(),
57             "the length of alias is too long");
58         HKS_LOG_E("input key alias length too large");
59         return nullptr;
60     }
61 
62     char *data = static_cast<char *>(HksMalloc(length + 1));
63     if (data == nullptr) {
64         HKS_LOG_E("could not alloc memory");
65         return nullptr;
66     }
67     (void)memset_s(data, length + 1, 0, length + 1);
68 
69     size_t result = 0;
70     status = napi_get_value_string_utf8(env, object, data, length + 1, &result);
71     if (status != napi_ok) {
72         HksFree(data);
73         HKS_LOG_E("could not get string");
74         return nullptr;
75     }
76 
77     alias = static_cast<HksBlob *>(HksMalloc(sizeof(HksBlob)));
78     if (alias == nullptr) {
79         HksFree(data);
80         HKS_LOG_E("could not alloc memory");
81         return nullptr;
82     }
83     alias->data = reinterpret_cast<uint8_t *>(data);
84     alias->size = static_cast<uint32_t>(length & UINT32_MAX);
85 
86     return GetInt32(env, 0);
87 }
88 
GetUint8Array(napi_env env,napi_value object,HksBlob & arrayBlob)89 napi_value GetUint8Array(napi_env env, napi_value object, HksBlob &arrayBlob)
90 {
91     napi_typedarray_type arrayType;
92     napi_value arrayBuffer = nullptr;
93     size_t length = 0;
94     size_t offset = 0;
95     void *rawData = nullptr;
96 
97     NAPI_CALL(
98         env, napi_get_typedarray_info(env, object, &arrayType, &length, &rawData, &arrayBuffer, &offset));
99     if (arrayType != napi_uint8_array) {
100         napi_throw_error(env, std::to_string(HUKS_ERR_CODE_ILLEGAL_ARGUMENT).c_str(),
101             "the type of data is not Uint8Array");
102         HKS_LOG_E("the type of  data is not Uint8Array");
103         return nullptr;
104     }
105 
106     if (length > HKS_MAX_DATA_LEN) {
107         napi_throw_error(env, std::to_string(HUKS_ERR_CODE_ILLEGAL_ARGUMENT).c_str(),
108             "the length of data is too long");
109         HKS_LOG_E("data len is too large, len = %" LOG_PUBLIC "zx", length);
110         return nullptr;
111     }
112     if (length == 0) {
113         HKS_LOG_I("the created memory length just 1 Byte");
114         // the created memory length just 1 Byte
115         arrayBlob.data = static_cast<uint8_t *>(HksMalloc(1));
116     } else {
117         arrayBlob.data = static_cast<uint8_t *>(HksMalloc(length));
118     }
119     if (arrayBlob.data == nullptr) {
120         return nullptr;
121     }
122     (void)memcpy_s(arrayBlob.data, length, rawData, length);
123     arrayBlob.size = static_cast<uint32_t>(length);
124 
125     return GetInt32(env, 0);
126 }
127 
CheckParamValueType(napi_env env,uint32_t tag,napi_value value)128 static napi_value CheckParamValueType(napi_env env, uint32_t tag, napi_value value)
129 {
130     napi_value result = nullptr;
131     napi_valuetype valueType = napi_valuetype::napi_undefined;
132     napi_status status = napi_typeof(env, value, &valueType);
133     if (status != napi_ok) {
134         HKS_LOG_E("could not get object type");
135         return nullptr;
136     }
137 
138     switch (tag & HKS_TAG_TYPE_MASK) {
139         case HKS_TAG_TYPE_INT:
140             if (valueType == napi_valuetype::napi_number) {
141                 result = GetInt32(env, 0);
142             }
143             break;
144         case HKS_TAG_TYPE_UINT:
145             if (valueType == napi_valuetype::napi_number) {
146                 result = GetInt32(env, 0);
147             }
148             break;
149         case HKS_TAG_TYPE_ULONG:
150             if (valueType == napi_valuetype::napi_number) {
151                 result = GetInt32(env, 0);
152             }
153             break;
154         case HKS_TAG_TYPE_BOOL:
155             if (valueType == napi_valuetype::napi_boolean) {
156                 result = GetInt32(env, 0);
157             }
158             break;
159         case HKS_TAG_TYPE_BYTES:
160             if (valueType == napi_valuetype::napi_object) {
161                 result = GetInt32(env, 0);
162             }
163             break;
164         default:
165             HKS_LOG_E("invalid tag value 0x%" LOG_PUBLIC "x", tag);
166             break;
167     }
168 
169     if (result == nullptr) {
170         napi_throw_error(env, std::to_string(HUKS_ERR_CODE_ILLEGAL_ARGUMENT).c_str(),
171             "the value of the tag is of an incorrect type");
172         HKS_LOG_E("invalid tag or the type of value, tag = 0x%" LOG_PUBLIC "x, type = %" LOG_PUBLIC "u",
173             tag, valueType);
174     }
175     return result;
176 }
177 
GetHksParam(napi_env env,napi_value object,HksParam & param)178 static napi_value GetHksParam(napi_env env, napi_value object, HksParam &param)
179 {
180     napi_value tag = GetPropertyFromOptions(env, object, HKS_PARAM_PROPERTY_TAG);
181     if (tag == nullptr) {
182         HKS_LOG_E("get param tag failed");
183         return nullptr;
184     }
185     NAPI_CALL(env, napi_get_value_uint32(env, tag, &param.tag));
186 
187     napi_value value = GetPropertyFromOptions(env, object, HKS_PARAM_PROPERTY_VALUE);
188     if (value == nullptr) {
189         HKS_LOG_E("get param value failed");
190         return nullptr;
191     }
192 
193     if (CheckParamValueType(env, param.tag, value) == nullptr) {
194         return nullptr;
195     }
196 
197     napi_value result = nullptr;
198     switch (param.tag & HKS_TAG_TYPE_MASK) {
199         case HKS_TAG_TYPE_INT:
200             NAPI_CALL(env, napi_get_value_int32(env, value, &param.int32Param));
201             result = GetInt32(env, 0);
202             break;
203         case HKS_TAG_TYPE_UINT:
204             NAPI_CALL(env, napi_get_value_uint32(env, value, &param.uint32Param));
205             result = GetInt32(env, 0);
206             break;
207         case HKS_TAG_TYPE_ULONG:
208             NAPI_CALL(env, napi_get_value_int64(env, value, reinterpret_cast<int64_t *>(&param.uint64Param)));
209             result = GetInt32(env, 0);
210             break;
211         case HKS_TAG_TYPE_BOOL:
212             NAPI_CALL(env, napi_get_value_bool(env, value, &param.boolParam));
213             result = GetInt32(env, 0);
214             break;
215         case HKS_TAG_TYPE_BYTES:
216             result = GetUint8Array(env, value, param.blob);
217             if (result == nullptr) {
218                 HKS_LOG_E("get uint8 array fail.");
219             } else {
220                 HKS_LOG_D("tag 0x%" LOG_PUBLIC "x, len 0x%" LOG_PUBLIC "x", param.tag, param.blob.size);
221             }
222             break;
223         default:
224             HKS_LOG_E("invalid tag value 0x%" LOG_PUBLIC "x", param.tag);
225             break;
226     }
227 
228     return result;
229 }
230 
FreeParsedParams(std::vector<HksParam> & params)231 void FreeParsedParams(std::vector<HksParam> &params)
232 {
233     HksParam *param = params.data();
234     size_t paramCount = params.size();
235     if (param == nullptr) {
236         return;
237     }
238     while (paramCount > 0) {
239         paramCount--;
240         if ((param->tag & HKS_TAG_TYPE_MASK) == HKS_TAG_TYPE_BYTES) {
241             HKS_FREE_PTR(param->blob.data);
242             param->blob.size = 0;
243         }
244         ++param;
245     }
246 }
247 
ParseParams(napi_env env,napi_value object,std::vector<HksParam> & params)248 napi_value ParseParams(napi_env env, napi_value object, std::vector<HksParam> &params)
249 {
250     bool hasNextElement = false;
251     napi_value result = nullptr;
252     size_t index = 0;
253     while ((napi_has_element(env, object, index, &hasNextElement) == napi_ok) && hasNextElement) {
254         napi_value element = nullptr;
255         NAPI_CALL(env, napi_get_element(env, object, index, &element));
256 
257         HksParam param = { 0 };
258         result = GetHksParam(env, element, param);
259         if (result == nullptr) {
260             HKS_LOG_E("get param failed when parse input params.");
261             return nullptr;
262         }
263 
264         params.push_back(param);
265         index++;
266     }
267     return GetInt32(env, 0);
268 }
269 
AddParams(const std::vector<HksParam> & params,struct HksParamSet * & paramSet)270 static int32_t AddParams(const std::vector<HksParam> &params, struct HksParamSet *&paramSet)
271 {
272     for (auto &param : params) {
273         int32_t ret = HksAddParams(paramSet, &param, 1);
274         if (ret != HKS_SUCCESS) {
275             HKS_LOG_E("add param.tag[%" LOG_PUBLIC "x] failed", param.tag);
276             return ret;
277         }
278     }
279     return HKS_SUCCESS;
280 }
281 
ParseHksParamSetOrAddParam(napi_env env,napi_value object,HksParamSet * & paramSet,HksParam * addParam)282 static napi_value ParseHksParamSetOrAddParam(napi_env env, napi_value object, HksParamSet *&paramSet,
283     HksParam *addParam)
284 {
285     if (paramSet != nullptr) {
286         HKS_LOG_E("param input invalid");
287         return nullptr;
288     }
289 
290     std::vector<HksParam> params;
291     HksParamSet *outParamSet = nullptr;
292     do {
293         if (HksInitParamSet(&outParamSet) != HKS_SUCCESS) {
294             HKS_LOG_E("paramset init failed");
295             break;
296         }
297 
298         if (ParseParams(env, object, params) == nullptr) {
299             HKS_LOG_E("parse params failed");
300             break;
301         }
302 
303         if (addParam != nullptr) {
304             params.push_back(*addParam);
305         }
306 
307         if (AddParams(params, outParamSet) != HKS_SUCCESS) {
308             HKS_LOG_E("add params failed");
309             break;
310         }
311 
312         if (HksBuildParamSet(&outParamSet) != HKS_SUCCESS) {
313             HKS_LOG_E("HksBuildParamSet failed");
314             break;
315         }
316 
317         FreeParsedParams(params);
318         paramSet = outParamSet;
319         return GetInt32(env, 0);
320     } while (0);
321 
322     HksFreeParamSet(&outParamSet);
323     FreeParsedParams(params);
324     return nullptr;
325 }
326 
ParseHksParamSet(napi_env env,napi_value object,HksParamSet * & paramSet)327 static napi_value ParseHksParamSet(napi_env env, napi_value object, HksParamSet *&paramSet)
328 {
329     return ParseHksParamSetOrAddParam(env, object, paramSet, nullptr);
330 }
331 
ParseHksParamSetAndAddParam(napi_env env,napi_value object,HksParamSet * & paramSet,HksParam * addParam)332 napi_value ParseHksParamSetAndAddParam(napi_env env, napi_value object, HksParamSet *&paramSet, HksParam *addParam)
333 {
334     return ParseHksParamSetOrAddParam(env, object, paramSet, addParam);
335 }
336 
GetCallback(napi_env env,napi_value object)337 napi_ref GetCallback(napi_env env, napi_value object)
338 {
339     napi_valuetype valueType = napi_valuetype::napi_undefined;
340     napi_status status = napi_typeof(env, object, &valueType);
341     if (status != napi_ok) {
342         HKS_LOG_E("could not get object type");
343         return nullptr;
344     }
345 
346     if (valueType != napi_valuetype::napi_function) {
347         napi_throw_error(env, std::to_string(HUKS_ERR_CODE_ILLEGAL_ARGUMENT).c_str(),
348             "the type of callback isn't function");
349         HKS_LOG_E("invalid type");
350         return nullptr;
351     }
352 
353     napi_ref ref = nullptr;
354     status = napi_create_reference(env, object, 1, &ref);
355     if (status != napi_ok) {
356         HKS_LOG_E("could not create reference");
357         return nullptr;
358     }
359     return ref;
360 }
361 
GenerateAarrayBuffer(napi_env env,uint8_t * data,uint32_t size)362 static napi_value GenerateAarrayBuffer(napi_env env, uint8_t *data, uint32_t size)
363 {
364     uint8_t *buffer = static_cast<uint8_t *>(HksMalloc(size));
365     if (buffer == nullptr) {
366         return nullptr;
367     }
368 
369     napi_value outBuffer = nullptr;
370     (void)memcpy_s(buffer, size, data, size);
371 
372     napi_status status = napi_create_external_arraybuffer(
373         env, buffer, size, [](napi_env env, void *data, void *hint) { HksFree(data); }, nullptr, &outBuffer);
374     if (status == napi_ok) {
375         // free by finalize callback
376         buffer = nullptr;
377     } else {
378         HksFree(buffer);
379     }
380 
381     return outBuffer;
382 }
383 
GenerateHksParam(napi_env env,const HksParam & param)384 static napi_value GenerateHksParam(napi_env env, const HksParam &param)
385 {
386     napi_value hksParam = nullptr;
387     NAPI_CALL(env, napi_create_object(env, &hksParam));
388 
389     napi_value tag = nullptr;
390     NAPI_CALL(env, napi_create_uint32(env, param.tag, &tag));
391     NAPI_CALL(env, napi_set_named_property(env, hksParam, HKS_PARAM_PROPERTY_TAG.c_str(), tag));
392 
393     napi_value value = nullptr;
394     switch (param.tag & HKS_TAG_TYPE_MASK) {
395         case HKS_TAG_TYPE_INT:
396             NAPI_CALL(env, napi_create_int32(env, param.int32Param, &value));
397             break;
398         case HKS_TAG_TYPE_UINT:
399             NAPI_CALL(env, napi_create_uint32(env, param.uint32Param, &value));
400             break;
401         case HKS_TAG_TYPE_ULONG:
402             NAPI_CALL(env, napi_create_int64(env, param.uint64Param, &value));
403             break;
404         case HKS_TAG_TYPE_BOOL:
405             NAPI_CALL(env, napi_get_boolean(env, param.boolParam, &value));
406             break;
407         case HKS_TAG_TYPE_BYTES:
408             value = GenerateAarrayBuffer(env, param.blob.data, param.blob.size);
409             break;
410         default:
411             value = GetNull(env);
412             break;
413     }
414     NAPI_CALL(env, napi_set_named_property(env, hksParam, HKS_PARAM_PROPERTY_VALUE.c_str(), value));
415 
416     return hksParam;
417 }
418 
GenerateHksParamArray(napi_env env,const HksParamSet & paramSet)419 static napi_value GenerateHksParamArray(napi_env env, const HksParamSet &paramSet)
420 {
421     napi_value paramArray = nullptr;
422     NAPI_CALL(env, napi_create_array(env, &paramArray));
423 
424     for (uint32_t i = 0; i < paramSet.paramsCnt; i++) {
425         napi_value element = nullptr;
426         element = GenerateHksParam(env, paramSet.params[i]);
427         napi_set_element(env, paramArray, i, element);
428     }
429 
430     return paramArray;
431 }
432 
GenerateStringArray(napi_env env,const struct HksBlob * blob,uint32_t blobCount)433 static napi_value GenerateStringArray(napi_env env, const struct HksBlob *blob, uint32_t blobCount)
434 {
435     if (blobCount == 0 || blob == nullptr) {
436         return nullptr;
437     }
438     napi_value array = nullptr;
439     NAPI_CALL(env, napi_create_array(env, &array));
440     for (uint32_t i = 0; i < blobCount; i++) {
441         napi_value element = nullptr;
442         napi_create_string_latin1(env, (const char *)blob[i].data, blob[i].size, &element);
443         napi_set_element(env, array, i, element);
444     }
445     return array;
446 }
447 
FreeHksCertChain(HksCertChain * & certChain)448 void FreeHksCertChain(HksCertChain *&certChain)
449 {
450     if (certChain == nullptr) {
451         return;
452     }
453 
454     if (certChain->certsCount > 0 && certChain->certs != nullptr) {
455         for (uint32_t i = 0; i < certChain->certsCount; i++) {
456             if (certChain->certs[i].data != nullptr) {
457                 HksFree(certChain->certs[i].data);
458                 certChain->certs[i].data = nullptr;
459             }
460         }
461     }
462 
463     HksFree(certChain);
464     certChain = nullptr;
465 }
466 
GetHandleValue(napi_env env,napi_value object,struct HksBlob * & handleBlob)467 napi_value GetHandleValue(napi_env env, napi_value object, struct HksBlob *&handleBlob)
468 {
469     if (handleBlob != nullptr) {
470         HKS_LOG_E("param input invalid");
471         return nullptr;
472     }
473 
474     napi_valuetype valueType = napi_valuetype::napi_undefined;
475     napi_status status = napi_typeof(env, object, &valueType);
476     if (status != napi_ok) {
477         HKS_LOG_E("could not get object type");
478         return nullptr;
479     }
480 
481     if (valueType != napi_valuetype::napi_number) {
482         napi_throw_error(env, std::to_string(HUKS_ERR_CODE_ILLEGAL_ARGUMENT).c_str(),
483             "the type of handle isn't number");
484         return nullptr;
485     }
486 
487     uint32_t handleTmp = 0;
488     status = napi_get_value_uint32(env, object, &handleTmp);
489     if (status != napi_ok) {
490         HKS_LOG_E("Retrieve field failed");
491         return nullptr;
492     }
493 
494     uint64_t handle = static_cast<uint64_t>(handleTmp);
495 
496     handleBlob = static_cast<struct HksBlob *>(HksMalloc(sizeof(struct HksBlob)));
497     if (handleBlob == nullptr) {
498         HKS_LOG_E("could not alloc memory");
499         return nullptr;
500     }
501 
502     handleBlob->data = static_cast<uint8_t *>(HksMalloc(sizeof(uint64_t)));
503     if (handleBlob->data == nullptr) {
504         HKS_FREE_PTR(handleBlob);
505         HKS_LOG_E("could not alloc memory");
506         return nullptr;
507     }
508     handleBlob->size = sizeof(uint64_t);
509 
510     if (memcpy_s(handleBlob->data, sizeof(uint64_t), &handle, sizeof(uint64_t)) != EOK) {
511         // the memory of handleBlob free by finalize callback
512         return nullptr;
513     }
514 
515     return GetInt32(env, 0);
516 }
517 
DeleteCommonAsyncContext(napi_env env,napi_async_work & asyncWork,napi_ref & callback,struct HksBlob * & blob,struct HksParamSet * & paramSet)518 void DeleteCommonAsyncContext(napi_env env, napi_async_work &asyncWork, napi_ref &callback,
519     struct HksBlob *&blob, struct HksParamSet *&paramSet)
520 {
521     if (asyncWork != nullptr) {
522         napi_delete_async_work(env, asyncWork);
523         asyncWork = nullptr;
524     }
525 
526     if (callback != nullptr) {
527         napi_delete_reference(env, callback);
528         callback = nullptr;
529     }
530 
531     if (blob != nullptr) {
532         FreeHksBlob(blob);
533     }
534 
535     if (paramSet != nullptr) {
536         HksFreeParamSet(&paramSet);
537     }
538 }
539 
GetPropertyFromOptions(napi_env env,napi_value value,const std::string propertyStr)540 napi_value GetPropertyFromOptions(napi_env env, napi_value value, const std::string propertyStr)
541 {
542     napi_valuetype valueType = napi_valuetype::napi_undefined;
543     napi_status status = napi_typeof(env, value, &valueType);
544     if (status != napi_ok) {
545         HKS_LOG_E("could not get object type");
546         return nullptr;
547     }
548 
549     if (valueType != napi_valuetype::napi_object) {
550         napi_throw_error(env, std::to_string(HUKS_ERR_CODE_ILLEGAL_ARGUMENT).c_str(),
551             "the type is not object");
552         HKS_LOG_E("no object type");
553         return nullptr;
554     }
555 
556     napi_value property = nullptr;
557     status = napi_get_named_property(env, value,
558         propertyStr.c_str(), &property);
559     if (status != napi_ok || property == nullptr) {
560         napi_throw_error(env, std::to_string(HUKS_ERR_CODE_ILLEGAL_ARGUMENT).c_str(),
561             "get value failed, maybe the target does not exist");
562         HKS_LOG_E("could not get property %" LOG_PUBLIC "s", propertyStr.c_str());
563         return nullptr;
564     }
565 
566     return property;
567 }
568 
ParseGetHksParamSet(napi_env env,napi_value value,HksParamSet * & paramSet)569 static napi_value ParseGetHksParamSet(napi_env env, napi_value value, HksParamSet *&paramSet)
570 {
571     napi_value property = GetPropertyFromOptions(env, value, HKS_OPTIONS_PROPERTY_PROPERTIES);
572     if (property == nullptr) {
573         return nullptr;
574     }
575 
576     napi_value result = ParseHksParamSet(env, property, paramSet);
577     if (result == nullptr) {
578         HKS_LOG_E("could not get paramset");
579         return nullptr;
580     }
581 
582     return GetInt32(env, 0);
583 }
584 
ParseHandleAndHksParamSet(napi_env env,napi_value * argv,size_t & index,HksBlob * & handleBlob,HksParamSet * & paramSet)585 napi_value ParseHandleAndHksParamSet(napi_env env, napi_value *argv, size_t &index,
586     HksBlob *&handleBlob, HksParamSet *&paramSet)
587 {
588     // the index is controlled by the caller and needs to ensure that it does not overflow
589     if (argv == nullptr || handleBlob != nullptr || paramSet != nullptr) {
590         HKS_LOG_E("param input invalid");
591         return nullptr;
592     }
593 
594     napi_value result = GetHandleValue(env, argv[index], handleBlob);
595     if (result == nullptr) {
596         HKS_LOG_E("could not get handle value");
597         return nullptr;
598     }
599 
600     index++;
601     result = ParseGetHksParamSet(env, argv[index], paramSet);
602     if (result == nullptr) {
603         HKS_LOG_E("could not get hksParamSet");
604         return nullptr;
605     }
606 
607     return GetInt32(env, 0);
608 }
609 
ParseKeyAliasAndHksParamSet(napi_env env,napi_value * argv,size_t & index,HksBlob * & keyAliasBlob,HksParamSet * & paramSet)610 napi_value ParseKeyAliasAndHksParamSet(napi_env env, napi_value *argv, size_t &index,
611     HksBlob *&keyAliasBlob, HksParamSet *&paramSet)
612 {
613     // the index is controlled by the caller and needs to ensure that it does not overflow
614     if (argv == nullptr || keyAliasBlob != nullptr || paramSet != nullptr) {
615         HKS_LOG_E("param input invalid");
616         return nullptr;
617     }
618 
619     napi_value result = ParseKeyAlias(env, argv[index], keyAliasBlob);
620     if (result == nullptr) {
621         HKS_LOG_E("could not get keyAlias");
622         return nullptr;
623     }
624 
625     index++;
626     result = ParseGetHksParamSet(env, argv[index], paramSet);
627     if (result == nullptr) {
628         HKS_LOG_E("get hksParamSet failed");
629         return nullptr;
630     }
631 
632     return GetInt32(env, 0);
633 }
634 
ParseKeyData(napi_env env,napi_value value,HksBlob * & keyDataBlob)635 napi_value ParseKeyData(napi_env env, napi_value value, HksBlob *&keyDataBlob)
636 {
637     if (keyDataBlob != nullptr) {
638         HKS_LOG_E("param input invalid");
639         return nullptr;
640     }
641 
642     napi_value inData = GetPropertyFromOptions(env, value, HKS_OPTIONS_PROPERTY_INDATA);
643     if (inData == nullptr) {
644         HKS_LOG_E("get indata property failed");
645         return nullptr;
646     }
647 
648     keyDataBlob = static_cast<struct HksBlob *>(HksMalloc(sizeof(HksBlob)));
649     if (keyDataBlob == nullptr) {
650         HKS_LOG_E("could not alloc memory");
651         return nullptr;
652     }
653     (void)memset_s(keyDataBlob, sizeof(HksBlob), 0, sizeof(HksBlob));
654 
655     if (GetUint8Array(env, inData, *keyDataBlob) == nullptr) {
656         FreeHksBlob(keyDataBlob);
657         HKS_LOG_E("could not get indata");
658         return nullptr;
659     }
660 
661     return GetInt32(env, 0);
662 }
663 
AddHandleOrChallenge(napi_env env,napi_value & object,const struct HksBlob * handle,const struct HksBlob * challenge)664 static napi_value AddHandleOrChallenge(napi_env env, napi_value &object,
665     const struct HksBlob *handle, const struct HksBlob *challenge)
666 {
667     napi_value addResult = nullptr;
668 
669     // add handle
670     if ((handle != nullptr) && (handle->data != nullptr) && (handle->size == sizeof(uint64_t))) {
671         void *handleData = static_cast<void *>(handle->data);
672         uint64_t tempHandle = *(static_cast<uint64_t *>(handleData));
673         uint32_t handleValue = static_cast<uint32_t>(tempHandle); /* Temporarily only use 32 bit handle */
674         napi_value handlejs = nullptr;
675         NAPI_CALL(env, napi_create_uint32(env, handleValue, &handlejs));
676         NAPI_CALL(env, napi_set_named_property(env, object, HKS_HANDLE_PROPERTY_HANDLE.c_str(), handlejs));
677         addResult = GetInt32(env, 0);
678     }
679 
680     // add challenge
681     if ((challenge != nullptr) && (challenge->size != 0) && (challenge->data != nullptr)) {
682         napi_value challengejs = nullptr;
683         napi_value outBuffer = GenerateAarrayBuffer(env, challenge->data, challenge->size);
684         if (outBuffer == nullptr) {
685             HKS_LOG_E("add token failed");
686             return nullptr;
687         }
688 
689         NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, challenge->size, outBuffer, 0, &challengejs));
690         NAPI_CALL(env, napi_set_named_property(env, object, HKS_HANDLE_PROPERTY_CHALLENGE.c_str(), challengejs));
691         addResult = GetInt32(env, 0);
692     }
693 
694     return addResult;
695 }
696 
AddOutDataParamSetOrCertChain(napi_env env,napi_value & object,const struct HksBlob * outData,const HksParamSet * paramSet,const struct HksCertChain * certChain)697 static napi_value AddOutDataParamSetOrCertChain(napi_env env, napi_value &object,
698     const struct HksBlob *outData, const HksParamSet *paramSet, const struct HksCertChain *certChain)
699 {
700     napi_value addResult = nullptr;
701 
702     // add outData
703     if ((outData != nullptr) && (outData->data != nullptr) && (outData->size != 0)) {
704         napi_value outDataJs = nullptr;
705         napi_value outBuffer = GenerateAarrayBuffer(env, outData->data, outData->size);
706         if (outBuffer == nullptr) {
707             HKS_LOG_E("add outData failed");
708             return nullptr;
709         }
710         NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, outData->size, outBuffer, 0, &outDataJs));
711         NAPI_CALL(env, napi_set_named_property(env, object, HKS_RESULT_PROPERTY_OUTDATA.c_str(), outDataJs));
712         addResult = GetInt32(env, 0);
713     }
714 
715     // add paramSet
716     if (paramSet != nullptr) {
717         napi_value properties = nullptr;
718         properties = GenerateHksParamArray(env, *paramSet);
719         if (properties == nullptr) {
720             HKS_LOG_E("add paramSet failed");
721             return nullptr;
722         }
723         NAPI_CALL(env, napi_set_named_property(env, object, HKS_RESULT_PRPPERTY_PROPERTIES.c_str(), properties));
724         addResult = GetInt32(env, 0);
725     }
726 
727     // add certChain
728     if ((certChain != nullptr) && (certChain->certs != nullptr) && (certChain->certsCount != 0)) {
729         napi_value certChainJs = GenerateStringArray(env, certChain->certs, certChain->certsCount);
730         if (certChainJs == nullptr) {
731             HKS_LOG_E("add certChain failed");
732             return nullptr;
733         }
734         NAPI_CALL(env, napi_set_named_property(env, object, HKS_RESULT_PRPPERTY_CERTCHAINS.c_str(), certChainJs));
735         addResult = GetInt32(env, 0);
736     }
737 
738     return addResult;
739 }
740 
GenerateResult(napi_env env,const struct HksSuccessReturnResult resultData)741 static napi_value GenerateResult(napi_env env, const struct HksSuccessReturnResult resultData)
742 {
743     napi_value result = nullptr;
744 
745     if (resultData.isOnlyReturnBoolResult) {
746         if (napi_get_boolean(env, true, &result) != napi_ok) {
747             return GetNull(env);
748         }
749         return result;
750     }
751 
752     if (napi_create_object(env, &result) != napi_ok) {
753         return GetNull(env);
754     }
755 
756     napi_value status1 = AddHandleOrChallenge(env, result, resultData.handle, resultData.challenge);
757     napi_value status2 = AddOutDataParamSetOrCertChain(env, result,
758         resultData.outData, resultData.paramSet, resultData.certChain);
759     if (status1 == nullptr && status2 == nullptr) {
760         return GetNull(env);
761     }
762 
763     return result;
764 }
765 
GenerateBusinessError(napi_env env,int32_t errorCode)766 static napi_value GenerateBusinessError(napi_env env, int32_t errorCode)
767 {
768     napi_value businessError = nullptr;
769     napi_status status = napi_create_object(env, &businessError);
770     if (status != napi_ok) {
771         HKS_LOG_E("create object failed");
772         return GetNull(env);
773     }
774 
775     struct HksResult errInfo = HksConvertErrCode(errorCode);
776     // add errorCode
777     napi_value code = nullptr;
778     status = napi_create_int32(env, errInfo.errorCode, &code);
779     if (status != napi_ok || code == nullptr) {
780         code = GetNull(env);
781     }
782     status = napi_set_named_property(env, businessError, BUSINESS_ERROR_PROPERTY_CODE.c_str(), code);
783     if (status != napi_ok) {
784         HKS_LOG_E("set errorCode failed");
785         return GetNull(env);
786     }
787 
788     // add errorMessage
789     napi_value msg = GetNull(env);
790     if (errInfo.errorMsg != nullptr) {
791 #ifdef HUKS_NAPI_ERRORCODE_WITH_MESSAGE
792         uint32_t errorMsgLen = strlen(errInfo.errorMsg);
793         uint8_t errorMsgBuf[errorMsgLen];
794         (void)memcpy_s(errorMsgBuf, errorMsgLen, errInfo.errorMsg, errorMsgLen);
795         struct HksBlob msgBlob = { errorMsgLen, errorMsgBuf };
796         msg = GenerateStringArray(env, &msgBlob, sizeof(msgBlob) / sizeof(struct HksBlob));
797         msg = ((msg == nullptr) ? GetNull(env) : msg);
798 #endif
799     }
800     status = napi_set_named_property(env, businessError, BUSINESS_ERROR_PROPERTY_MESSAGE.c_str(), msg);
801     if (status != napi_ok) {
802         HKS_LOG_E("set errorMsg failed");
803         return GetNull(env);
804     }
805 
806     // add errorData
807     napi_value data = GetNull(env);
808     status = napi_set_named_property(env, businessError, BUSINESS_ERROR_PROPERTY_DATA.c_str(), data);
809     if (status != napi_ok) {
810         HKS_LOG_E("set errorData failed");
811         return GetNull(env);
812     }
813 
814     return businessError;
815 }
816 
CallbackResultFailure(napi_env env,napi_ref callback,int32_t error)817 static void CallbackResultFailure(napi_env env, napi_ref callback, int32_t error)
818 {
819     if (error == HKS_SUCCESS) {
820         HKS_LOG_E("callback: failure cannot be executed");
821         return;
822     }
823 
824     napi_value func = nullptr;
825     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callback, &func));
826 
827     napi_value recv = nullptr;
828     napi_value result = nullptr;
829     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &recv));
830 
831     napi_value businessError = GenerateBusinessError(env, error);
832     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, recv, func, 1, &businessError, &result));
833 }
834 
CallbackResultSuccess(napi_env env,napi_ref callback,const struct HksSuccessReturnResult resultData)835 static void CallbackResultSuccess(napi_env env, napi_ref callback, const struct HksSuccessReturnResult resultData)
836 {
837     napi_value params[ASYNCCALLBACK_ARGC] = { GetNull(env), GenerateResult(env, resultData) };
838     napi_value func = nullptr;
839     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callback, &func));
840 
841     napi_value recv = nullptr;
842     napi_value result = nullptr;
843     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &recv));
844     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, recv, func, ASYNCCALLBACK_ARGC, params, &result));
845 }
846 
PromiseResultFailure(napi_env env,napi_deferred deferred,int32_t error)847 static void PromiseResultFailure(napi_env env, napi_deferred deferred, int32_t error)
848 {
849     if (error == HKS_SUCCESS) {
850         HKS_LOG_E("promise: failure cannot be executed");
851         return;
852     }
853     napi_value result = nullptr;
854     result = GenerateBusinessError(env, error);
855     napi_reject_deferred(env, deferred, result);
856 }
857 
PromiseResultSuccess(napi_env env,napi_deferred deferred,const struct HksSuccessReturnResult resultData)858 static void PromiseResultSuccess(napi_env env, napi_deferred deferred,
859     const struct HksSuccessReturnResult resultData)
860 {
861     napi_value result = nullptr;
862     result = GenerateResult(env, resultData);
863     napi_resolve_deferred(env, deferred, result);
864 }
865 
SuccessReturnResultInit(struct HksSuccessReturnResult & resultData)866 void SuccessReturnResultInit(struct HksSuccessReturnResult &resultData)
867 {
868     resultData.isOnlyReturnBoolResult = false;
869     resultData.handle = nullptr;
870     resultData.challenge = nullptr;
871     resultData.outData = nullptr;
872     resultData.paramSet = nullptr;
873     resultData.certChain = nullptr;
874 }
875 
HksReturnNapiResult(napi_env env,napi_ref callback,napi_deferred deferred,int32_t errorCode,const struct HksSuccessReturnResult resultData)876 void HksReturnNapiResult(napi_env env, napi_ref callback, napi_deferred deferred, int32_t errorCode,
877     const struct HksSuccessReturnResult resultData)
878 {
879     if (callback == nullptr) {
880         if (errorCode == HKS_SUCCESS) {
881             PromiseResultSuccess(env, deferred, resultData);
882         } else {
883             PromiseResultFailure(env, deferred, errorCode);
884         }
885     } else {
886         if (errorCode == HKS_SUCCESS) {
887             CallbackResultSuccess(env, callback, resultData);
888         } else {
889             CallbackResultFailure(env, callback, errorCode);
890         }
891     }
892 }
893 }  // namespace HuksNapiItem
894