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