• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "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_CALL(env, napi_typeof(env, object, &valueType));
37 
38     if (valueType != napi_valuetype::napi_string) {
39         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "the type of alias isn't string");
40         HKS_LOG_E("no string type");
41         return nullptr;
42     }
43 
44     size_t length = 0;
45     napi_status status = napi_get_value_string_utf8(env, object, nullptr, 0, &length);
46     if (status != napi_ok) {
47         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "could not get string length");
48         HKS_LOG_E("could not get string length %" LOG_PUBLIC "d", status);
49         return nullptr;
50     }
51 
52     if (length > HKS_MAX_DATA_LEN) {
53         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "the length of alias is too long");
54         HKS_LOG_E("input key alias length %" LOG_PUBLIC "zu too large", length);
55         return nullptr;
56     }
57 
58     char *data = static_cast<char *>(HksMalloc(length + 1));
59     if (data == nullptr) {
60         HksNapiThrowInsufficientMemory(env);
61         HKS_LOG_E("could not alloc memory");
62         return nullptr;
63     }
64     (void)memset_s(data, length + 1, 0, length + 1);
65 
66     size_t result = 0;
67     status = napi_get_value_string_utf8(env, object, data, length + 1, &result);
68     if (status != napi_ok) {
69         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "could not get string");
70         HKS_FREE(data);
71         HKS_LOG_E("could not get string %" LOG_PUBLIC "d", status);
72         return nullptr;
73     }
74 
75     alias = static_cast<HksBlob *>(HksMalloc(sizeof(HksBlob)));
76     if (alias == nullptr) {
77         HksNapiThrowInsufficientMemory(env);
78         HKS_FREE(data);
79         HKS_LOG_E("could not alloc memory");
80         return nullptr;
81     }
82     alias->data = reinterpret_cast<uint8_t *>(data);
83     alias->size = static_cast<uint32_t>(length & UINT32_MAX);
84 
85     return GetInt32(env, 0);
86 }
87 
GetUint8Array(napi_env env,napi_value object,HksBlob & arrayBlob)88 napi_value GetUint8Array(napi_env env, napi_value object, HksBlob &arrayBlob)
89 {
90     napi_typedarray_type arrayType;
91     napi_value arrayBuffer = nullptr;
92     size_t length = 0;
93     size_t offset = 0;
94     void *rawData = nullptr;
95 
96     NAPI_CALL(
97         env, napi_get_typedarray_info(env, object, &arrayType, &length, &rawData, &arrayBuffer, &offset));
98     if (arrayType != napi_uint8_array) {
99         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT,
100             "the type of data is not Uint8Array");
101         HKS_LOG_E("the type of  data is not Uint8Array");
102         return nullptr;
103     }
104 
105     if (length > HKS_MAX_DATA_LEN) {
106         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT,
107             "the length of data is too long");
108         HKS_LOG_E("data len is too large, len = %" LOG_PUBLIC "zx", length);
109         return nullptr;
110     }
111     if (length == 0) {
112         HKS_LOG_I("the created memory length just 1 Byte");
113         // the created memory length just 1 Byte
114         arrayBlob.data = static_cast<uint8_t *>(HksMalloc(1));
115     } else {
116         arrayBlob.data = static_cast<uint8_t *>(HksMalloc(length));
117     }
118     if (arrayBlob.data == nullptr) {
119         return nullptr;
120     }
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_CALL(env, napi_typeof(env, value, &valueType));
133 
134     switch (tag & HKS_TAG_TYPE_MASK) {
135         case HKS_TAG_TYPE_INT:
136             if (valueType == napi_valuetype::napi_number) {
137                 result = GetInt32(env, 0);
138             }
139             break;
140         case HKS_TAG_TYPE_UINT:
141             if (valueType == napi_valuetype::napi_number) {
142                 result = GetInt32(env, 0);
143             }
144             break;
145         case HKS_TAG_TYPE_ULONG:
146             if (valueType == napi_valuetype::napi_number) {
147                 result = GetInt32(env, 0);
148             }
149             break;
150         case HKS_TAG_TYPE_BOOL:
151             if (valueType == napi_valuetype::napi_boolean) {
152                 result = GetInt32(env, 0);
153             }
154             break;
155         case HKS_TAG_TYPE_BYTES:
156             if (valueType == napi_valuetype::napi_object) {
157                 result = GetInt32(env, 0);
158             }
159             break;
160         default:
161             HKS_LOG_E("invalid tag value 0x%" LOG_PUBLIC "x", tag);
162             break;
163     }
164 
165     if (result == nullptr) {
166         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT,
167             "the value of the tag is of an incorrect type");
168         HKS_LOG_E("invalid tag or the type of value, tag = 0x%" LOG_PUBLIC "x, type = %" LOG_PUBLIC "u",
169             tag, valueType);
170     }
171     return result;
172 }
173 
GetHksParam(napi_env env,napi_value object,HksParam & param)174 static napi_value GetHksParam(napi_env env, napi_value object, HksParam &param)
175 {
176     napi_value tag = GetPropertyFromOptions(env, object, HKS_PARAM_PROPERTY_TAG);
177     if (tag == nullptr) {
178         HKS_LOG_E("get param tag failed");
179         return nullptr;
180     }
181     NAPI_CALL(env, napi_get_value_uint32(env, tag, &param.tag));
182 
183     napi_value value = GetPropertyFromOptions(env, object, HKS_PARAM_PROPERTY_VALUE);
184     if (value == nullptr) {
185         HKS_LOG_E("get param value failed");
186         return nullptr;
187     }
188 
189     if (CheckParamValueType(env, param.tag, value) == nullptr) {
190         return nullptr;
191     }
192 
193     napi_value result = nullptr;
194     switch (param.tag & HKS_TAG_TYPE_MASK) {
195         case HKS_TAG_TYPE_INT:
196             NAPI_CALL(env, napi_get_value_int32(env, value, &param.int32Param));
197             result = GetInt32(env, 0);
198             break;
199         case HKS_TAG_TYPE_UINT:
200             NAPI_CALL(env, napi_get_value_uint32(env, value, &param.uint32Param));
201             result = GetInt32(env, 0);
202             break;
203         case HKS_TAG_TYPE_ULONG:
204             NAPI_CALL(env, napi_get_value_int64(env, value, reinterpret_cast<int64_t *>(&param.uint64Param)));
205             result = GetInt32(env, 0);
206             break;
207         case HKS_TAG_TYPE_BOOL:
208             NAPI_CALL(env, napi_get_value_bool(env, value, &param.boolParam));
209             result = GetInt32(env, 0);
210             break;
211         case HKS_TAG_TYPE_BYTES:
212             result = GetUint8Array(env, value, param.blob);
213             if (result == nullptr) {
214                 HKS_LOG_E("get uint8 array fail.");
215             } else {
216                 HKS_LOG_D("tag 0x%" LOG_PUBLIC "x, len 0x%" LOG_PUBLIC "x", param.tag, param.blob.size);
217             }
218             break;
219         default:
220             HKS_LOG_E("invalid tag value 0x%" LOG_PUBLIC "x", param.tag);
221             break;
222     }
223 
224     return result;
225 }
226 
FreeParsedParams(std::vector<HksParam> & params)227 void FreeParsedParams(std::vector<HksParam> &params)
228 {
229     for (HksParam &p : params) {
230         if (GetTagType(static_cast<HksTag>(p.tag)) == HKS_TAG_TYPE_BYTES) {
231             HKS_FREE_BLOB(p.blob);
232         }
233     }
234 }
235 
ParseParams(napi_env env,napi_value object,std::vector<HksParam> & params)236 napi_value ParseParams(napi_env env, napi_value object, std::vector<HksParam> &params)
237 {
238     bool hasNextElement = false;
239     napi_value result = nullptr;
240     size_t index = 0;
241     while ((napi_has_element(env, object, index, &hasNextElement) == napi_ok) && hasNextElement) {
242         napi_value element = nullptr;
243         NAPI_CALL(env, napi_get_element(env, object, index, &element));
244 
245         HksParam param = { 0 };
246         result = GetHksParam(env, element, param);
247         if (result == nullptr) {
248             HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "GetHksParam fail");
249             HKS_LOG_E("get param failed when parse input params.");
250             return nullptr;
251         }
252 
253         params.push_back(param);
254         index++;
255     }
256     return GetInt32(env, 0);
257 }
258 
ParseHksParamSetAndAddParam(napi_env env,napi_value object,HksParamSet * & paramSet,const std::vector<HksParam> & addParams)259 napi_value ParseHksParamSetAndAddParam(napi_env env, napi_value object, HksParamSet *&paramSet,
260     const std::vector<HksParam> &addParams)
261 {
262     if (paramSet != nullptr) {
263         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "paramSet is nullptr");
264         HKS_LOG_E("param input invalid");
265         return nullptr;
266     }
267 
268     std::vector<HksParam> params{};
269     HksParamSet *outParamSet = nullptr;
270     do {
271         if (HksInitParamSet(&outParamSet) != HKS_SUCCESS) {
272             HksNapiThrowInsufficientMemory(env);
273             HKS_LOG_E("paramset init failed");
274             break;
275         }
276 
277         if (ParseParams(env, object, params) == nullptr) {
278             HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "ParseParams fail");
279             HKS_LOG_E("parse params failed");
280             break;
281         }
282 
283         if (!addParams.empty()) {
284             // the memory of some blobs in addParams is allocated before stepping into current function,
285             // and we will FreeParsedParams(params) later, therefore we can not append addParams into params.
286             if (HksAddParams(outParamSet, addParams.data(), addParams.size()) != HKS_SUCCESS) {
287                 HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "HksAddParams addParams fail");
288                 HKS_LOG_E("add params addParams failed");
289                 break;
290             }
291         }
292 
293         if (!params.empty()) {
294             if (HksAddParams(outParamSet, params.data(), params.size()) != HKS_SUCCESS) {
295                 HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "HksAddParams fail");
296                 HKS_LOG_E("add params failed");
297                 break;
298             }
299         }
300 
301         if (HksBuildParamSet(&outParamSet) != HKS_SUCCESS) {
302             HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "HksBuildParamSet fail");
303             HKS_LOG_E("HksBuildParamSet failed");
304             break;
305         }
306 
307         FreeParsedParams(params);
308         paramSet = outParamSet;
309         return GetInt32(env, 0);
310     } while (0);
311 
312     HksFreeParamSet(&outParamSet);
313     FreeParsedParams(params);
314     return nullptr;
315 }
316 
ParseHksParamSetWithToken(napi_env env,struct HksBlob * & token,napi_value object,HksParamSet * & paramSet)317 napi_value ParseHksParamSetWithToken(napi_env env, struct HksBlob *&token, napi_value object, HksParamSet *&paramSet)
318 {
319     std::vector<HksParam> params {};
320     if (CheckBlob(token) == HKS_SUCCESS) { /* has token param */
321         params.emplace_back(HksParam{
322             .tag = HKS_TAG_AUTH_TOKEN,
323             .blob = *token
324         });
325     }
326     return ParseHksParamSetAndAddParam(env, object, paramSet, params);
327 }
328 
GetCallback(napi_env env,napi_value object)329 napi_ref GetCallback(napi_env env, napi_value object)
330 {
331     napi_valuetype valueType = napi_valuetype::napi_undefined;
332     NAPI_CALL(env, napi_typeof(env, object, &valueType));
333 
334     if (valueType != napi_valuetype::napi_function) {
335         HKS_LOG_I("no callback fun, process as promise func");
336         return nullptr;
337     }
338 
339     napi_ref ref = nullptr;
340     napi_status status = napi_create_reference(env, object, 1, &ref);
341     if (status != napi_ok) {
342         HKS_LOG_E("could not create reference");
343         return nullptr;
344     }
345     return ref;
346 }
347 
GenerateArrayBuffer(napi_env env,uint8_t * data,uint32_t size)348 static napi_value GenerateArrayBuffer(napi_env env, uint8_t *data, uint32_t size)
349 {
350     uint8_t *buffer = static_cast<uint8_t *>(HksMalloc(size));
351     if (buffer == nullptr) {
352         return nullptr;
353     }
354 
355     napi_value outBuffer = nullptr;
356     (void)memcpy_s(buffer, size, data, size);
357 
358     napi_status status = napi_create_external_arraybuffer(
359         env, buffer, size, [](napi_env env, void *data, void *hint) { HKS_FREE(data); }, nullptr, &outBuffer);
360     if (status == napi_ok) {
361         // free by finalize callback
362         buffer = nullptr;
363     } else {
364         HKS_FREE(buffer);
365     }
366 
367     return outBuffer;
368 }
369 
GenerateHksParam(napi_env env,const HksParam & param)370 static napi_value GenerateHksParam(napi_env env, const HksParam &param)
371 {
372     napi_value hksParam = nullptr;
373     NAPI_CALL(env, napi_create_object(env, &hksParam));
374 
375     napi_value tag = nullptr;
376     NAPI_CALL(env, napi_create_uint32(env, param.tag, &tag));
377     NAPI_CALL(env, napi_set_named_property(env, hksParam, HKS_PARAM_PROPERTY_TAG.c_str(), tag));
378 
379     napi_value value = nullptr;
380     switch (param.tag & HKS_TAG_TYPE_MASK) {
381         case HKS_TAG_TYPE_INT:
382             NAPI_CALL(env, napi_create_int32(env, param.int32Param, &value));
383             break;
384         case HKS_TAG_TYPE_UINT:
385             NAPI_CALL(env, napi_create_uint32(env, param.uint32Param, &value));
386             break;
387         case HKS_TAG_TYPE_ULONG:
388             NAPI_CALL(env, napi_create_int64(env, param.uint64Param, &value));
389             break;
390         case HKS_TAG_TYPE_BOOL:
391             NAPI_CALL(env, napi_get_boolean(env, param.boolParam, &value));
392             break;
393         case HKS_TAG_TYPE_BYTES:
394             value = GenerateArrayBuffer(env, param.blob.data, param.blob.size);
395             break;
396         default:
397             value = GetNull(env);
398             break;
399     }
400     NAPI_CALL(env, napi_set_named_property(env, hksParam, HKS_PARAM_PROPERTY_VALUE.c_str(), value));
401 
402     return hksParam;
403 }
404 
GenerateHksParamArray(napi_env env,const HksParamSet & paramSet)405 static napi_value GenerateHksParamArray(napi_env env, const HksParamSet &paramSet)
406 {
407     napi_value paramArray = nullptr;
408     NAPI_CALL(env, napi_create_array(env, &paramArray));
409 
410     for (uint32_t i = 0; i < paramSet.paramsCnt; i++) {
411         napi_value element = nullptr;
412         element = GenerateHksParam(env, paramSet.params[i]);
413         napi_set_element(env, paramArray, i, element);
414     }
415 
416     return paramArray;
417 }
418 
GenerateStringArray(napi_env env,const struct HksBlob * blob,uint32_t blobCount)419 static napi_value GenerateStringArray(napi_env env, const struct HksBlob *blob, uint32_t blobCount)
420 {
421     if (blobCount == 0 || blob == nullptr) {
422         return nullptr;
423     }
424     napi_value array = nullptr;
425     NAPI_CALL(env, napi_create_array(env, &array));
426     for (uint32_t i = 0; i < blobCount; i++) {
427         napi_value element = nullptr;
428         napi_create_string_latin1(env, (const char *)blob[i].data, blob[i].size, &element);
429         napi_set_element(env, array, i, element);
430     }
431     return array;
432 }
433 
FreeHksCertChain(HksCertChain * & certChain,uint32_t certChainCapacity)434 void FreeHksCertChain(HksCertChain *&certChain, uint32_t certChainCapacity)
435 {
436     if (certChain == nullptr) {
437         return;
438     }
439 
440     if (certChainCapacity > 0 && certChain->certs != nullptr) {
441         for (uint32_t i = 0; i < certChainCapacity; i++) {
442             if (certChain->certs[i].data != nullptr) {
443                 HKS_FREE(certChain->certs[i].data);
444                 certChain->certs[i].data = nullptr;
445             }
446         }
447     }
448     HKS_FREE(certChain->certs);
449     HKS_FREE(certChain);
450     certChain = nullptr;
451 }
452 
FreeHksKeyAliasSet(HksKeyAliasSet * & keyAliasSet,uint32_t cnt)453 void FreeHksKeyAliasSet(HksKeyAliasSet *&keyAliasSet, uint32_t cnt)
454 {
455     if (keyAliasSet == nullptr) {
456         return;
457     }
458 
459     if (cnt > 0 && keyAliasSet->aliases != nullptr) {
460         for (uint32_t i = 0; i < cnt; i++) {
461             HKS_FREE_BLOB(keyAliasSet->aliases[i]);
462         }
463     }
464     HKS_FREE(keyAliasSet->aliases);
465     HKS_FREE(keyAliasSet);
466     keyAliasSet = nullptr;
467 }
468 
GetHandleValue(napi_env env,napi_value object,struct HksBlob * & handleBlob)469 napi_value GetHandleValue(napi_env env, napi_value object, struct HksBlob *&handleBlob)
470 {
471     if (handleBlob != nullptr) {
472         HKS_LOG_E("param input invalid");
473         return nullptr;
474     }
475 
476     napi_valuetype valueType = napi_valuetype::napi_undefined;
477     NAPI_CALL(env, napi_typeof(env, object, &valueType));
478 
479     if (valueType != napi_valuetype::napi_number) {
480         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT,
481             "the type of handle isn't number");
482         return nullptr;
483     }
484 
485     uint32_t handleTmp = 0;
486     napi_status status = napi_get_value_uint32(env, object, &handleTmp);
487     if (status != napi_ok) {
488         HKS_LOG_E("Retrieve field failed");
489         return nullptr;
490     }
491 
492     uint64_t handle = static_cast<uint64_t>(handleTmp);
493 
494     handleBlob = static_cast<struct HksBlob *>(HksMalloc(sizeof(struct HksBlob)));
495     if (handleBlob == nullptr) {
496         HKS_LOG_E("could not alloc memory");
497         return nullptr;
498     }
499 
500     handleBlob->data = static_cast<uint8_t *>(HksMalloc(sizeof(uint64_t)));
501     if (handleBlob->data == nullptr) {
502         HKS_FREE(handleBlob);
503         HKS_LOG_E("could not alloc memory");
504         return nullptr;
505     }
506     handleBlob->size = sizeof(uint64_t);
507 
508     if (memcpy_s(handleBlob->data, sizeof(uint64_t), &handle, sizeof(uint64_t)) != EOK) {
509         // the memory of handleBlob free by finalize callback
510         return nullptr;
511     }
512 
513     return GetInt32(env, 0);
514 }
515 
GetUserIdValue(napi_env env,napi_value object,int & userId)516 napi_value GetUserIdValue(napi_env env, napi_value object, int &userId)
517 {
518     napi_valuetype valueType = napi_valuetype::napi_undefined;
519     NAPI_CALL(env, napi_typeof(env, object, &valueType));
520 
521     if (valueType != napi_valuetype::napi_number) {
522         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "the type of userId isn't number");
523         HKS_LOG_E("valueType %" LOG_PUBLIC "d not napi_number", valueType);
524         return nullptr;
525     }
526 
527     napi_status status = napi_get_value_int32(env, object, &userId);
528     if (status != napi_ok) {
529         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "get int32 userId failed");
530         HKS_LOG_E("get int32 userId failed %" LOG_PUBLIC "d", status);
531         return nullptr;
532     }
533 
534     return GetInt32(env, 0);
535 }
536 
DeleteCommonAsyncContext(napi_env env,napi_async_work & asyncWork,napi_ref & callback,struct HksBlob * & blob,struct HksParamSet * & paramSet)537 void DeleteCommonAsyncContext(napi_env env, napi_async_work &asyncWork, napi_ref &callback,
538     struct HksBlob *&blob, struct HksParamSet *&paramSet)
539 {
540     if (asyncWork != nullptr) {
541         napi_delete_async_work(env, asyncWork);
542         asyncWork = nullptr;
543     }
544 
545     if (callback != nullptr) {
546         napi_delete_reference(env, callback);
547         callback = nullptr;
548     }
549 
550     if (blob != nullptr) {
551         FreeHksBlob(blob);
552     }
553 
554     if (paramSet != nullptr) {
555         HksFreeParamSet(&paramSet);
556     }
557 }
558 
GetPropertyFromOptions(napi_env env,napi_value value,const std::string propertyStr)559 napi_value GetPropertyFromOptions(napi_env env, napi_value value, const std::string propertyStr)
560 {
561     napi_valuetype valueType = napi_valuetype::napi_undefined;
562     NAPI_CALL(env, napi_typeof(env, value, &valueType));
563 
564     if (valueType != napi_valuetype::napi_object) {
565         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT,
566             "the type is not object");
567         HKS_LOG_E("no object type");
568         return nullptr;
569     }
570 
571     napi_value property = nullptr;
572     napi_status status = napi_get_named_property(env, value,
573         propertyStr.c_str(), &property);
574     if (status != napi_ok || property == nullptr) {
575         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT,
576             "get value failed, maybe the target does not exist");
577         HKS_LOG_E("could not get property %" LOG_PUBLIC "s", propertyStr.c_str());
578         return nullptr;
579     }
580 
581     return property;
582 }
583 
ParseGetHksParamSet(napi_env env,napi_value value,HksParamSet * & paramSet)584 napi_value ParseGetHksParamSet(napi_env env, napi_value value, HksParamSet *&paramSet)
585 {
586     napi_value property = GetPropertyFromOptions(env, value, HKS_OPTIONS_PROPERTY_PROPERTIES);
587     if (property == nullptr) {
588         return nullptr;
589     }
590 
591     napi_value result = ParseHksParamSetAndAddParam(env, property, paramSet);
592     if (result == nullptr) {
593         HKS_LOG_E("could not get paramset");
594         return nullptr;
595     }
596 
597     return GetInt32(env, 0);
598 }
599 
ParseGetHksParamSetAsUser(napi_env env,int userId,napi_value value,HksParamSet * & paramSet)600 static napi_value ParseGetHksParamSetAsUser(napi_env env, int userId, napi_value value, HksParamSet *&paramSet)
601 {
602     napi_value property = GetPropertyFromOptions(env, value, HKS_OPTIONS_PROPERTY_PROPERTIES);
603     if (property == nullptr) {
604         return nullptr;
605     }
606 
607     napi_value result = ParseHksParamSetAndAddParam(env, property, paramSet,
608         {{.tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = userId}});
609     if (result == nullptr) {
610         HKS_LOG_E("could not get paramset");
611         return nullptr;
612     }
613 
614     return GetInt32(env, 0);
615 }
616 
ParseKeyAliasAndHksParamSet(napi_env env,napi_value * argv,size_t & index,HksBlob * & keyAliasBlob,HksParamSet * & paramSet)617 napi_value ParseKeyAliasAndHksParamSet(napi_env env, napi_value *argv, size_t &index,
618     HksBlob *&keyAliasBlob, HksParamSet *&paramSet)
619 {
620     // the index is controlled by the caller and needs to ensure that it does not overflow
621     if (argv == nullptr || keyAliasBlob != nullptr || paramSet != nullptr) {
622         HKS_LOG_E("param input invalid");
623         return nullptr;
624     }
625 
626     napi_value result = ParseKeyAlias(env, argv[index], keyAliasBlob);
627     if (result == nullptr) {
628         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "could not get key alias");
629         HKS_LOG_E("could not get keyAlias");
630         return nullptr;
631     }
632 
633     index++;
634     result = ParseGetHksParamSet(env, argv[index], paramSet);
635     if (result == nullptr) {
636         HKS_LOG_E("get hksParamSet failed");
637         return nullptr;
638     }
639 
640     return GetInt32(env, 0);
641 }
642 
ParseKeyAliasAndHksParamSetAsUser(napi_env env,int userId,napi_value * argv,size_t & index,std::pair<HksBlob * &,HksParamSet * &> out)643 napi_value ParseKeyAliasAndHksParamSetAsUser(napi_env env, int userId, napi_value *argv, size_t &index,
644     std::pair<HksBlob *&, HksParamSet *&> out)
645 {
646     auto &[ keyAliasBlob, paramSet ] = out;
647     // the index is controlled by the caller and needs to ensure that it does not overflow
648     if (argv == nullptr || keyAliasBlob != nullptr || paramSet != nullptr) {
649         HKS_LOG_E("param input invalid");
650         return nullptr;
651     }
652 
653     napi_value result = ParseKeyAlias(env, argv[index], keyAliasBlob);
654     if (result == nullptr) {
655         HksNapiThrow(env, HUKS_ERR_CODE_ILLEGAL_ARGUMENT, "could not get key alias");
656         HKS_LOG_E("could not get keyAlias");
657         return nullptr;
658     }
659 
660     index++;
661     result = ParseGetHksParamSetAsUser(env, userId, argv[index], paramSet);
662     if (result == nullptr) {
663         HKS_LOG_E("get hksParamSet failed");
664         return nullptr;
665     }
666 
667     return GetInt32(env, 0);
668 }
669 
ParseKeyData(napi_env env,napi_value value,HksBlob * & keyDataBlob)670 napi_value ParseKeyData(napi_env env, napi_value value, HksBlob *&keyDataBlob)
671 {
672     if (keyDataBlob != nullptr) {
673         HKS_LOG_E("param input invalid");
674         return nullptr;
675     }
676 
677     napi_value inData = GetPropertyFromOptions(env, value, HKS_OPTIONS_PROPERTY_INDATA);
678     if (inData == nullptr) {
679         HKS_LOG_E("get indata property failed");
680         return nullptr;
681     }
682 
683     keyDataBlob = static_cast<struct HksBlob *>(HksMalloc(sizeof(HksBlob)));
684     if (keyDataBlob == nullptr) {
685         HKS_LOG_E("could not alloc memory");
686         return nullptr;
687     }
688     (void)memset_s(keyDataBlob, sizeof(HksBlob), 0, sizeof(HksBlob));
689 
690     if (GetUint8Array(env, inData, *keyDataBlob) == nullptr) {
691         FreeHksBlob(keyDataBlob);
692         HKS_LOG_E("could not get indata");
693         return nullptr;
694     }
695 
696     return GetInt32(env, 0);
697 }
698 
AddHandleOrChallenge(napi_env env,napi_value & object,const struct HksBlob * handle,const struct HksBlob * challenge)699 static napi_value AddHandleOrChallenge(napi_env env, napi_value &object,
700     const struct HksBlob *handle, const struct HksBlob *challenge)
701 {
702     napi_value addResult = nullptr;
703 
704     // add handle
705     if ((handle != nullptr) && (handle->data != nullptr) && (handle->size == sizeof(uint64_t))) {
706         void *handleData = static_cast<void *>(handle->data);
707         uint64_t tempHandle = *(static_cast<uint64_t *>(handleData));
708         uint32_t handleValue = static_cast<uint32_t>(tempHandle); /* Temporarily only use 32 bit handle */
709         napi_value handlejs = nullptr;
710         NAPI_CALL(env, napi_create_uint32(env, handleValue, &handlejs));
711         NAPI_CALL(env, napi_set_named_property(env, object, HKS_HANDLE_PROPERTY_HANDLE.c_str(), handlejs));
712         addResult = GetInt32(env, 0);
713     }
714 
715     // add challenge
716     if ((challenge != nullptr) && (challenge->size != 0) && (challenge->data != nullptr)) {
717         napi_value challengejs = nullptr;
718         napi_value outBuffer = GenerateArrayBuffer(env, challenge->data, challenge->size);
719         if (outBuffer == nullptr) {
720             HKS_LOG_E("add token failed");
721             return nullptr;
722         }
723 
724         NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, challenge->size, outBuffer, 0, &challengejs));
725         NAPI_CALL(env, napi_set_named_property(env, object, HKS_HANDLE_PROPERTY_CHALLENGE.c_str(), challengejs));
726         addResult = GetInt32(env, 0);
727     }
728 
729     return addResult;
730 }
731 
AddOutDataParamSetOrCertChain(napi_env env,napi_value & object,const struct HksBlob * outData,const HksParamSet * paramSet,const struct HksCertChain * certChain)732 static napi_value AddOutDataParamSetOrCertChain(napi_env env, napi_value &object,
733     const struct HksBlob *outData, const HksParamSet *paramSet, const struct HksCertChain *certChain)
734 {
735     napi_value addResult = nullptr;
736 
737     // add outData
738     if ((outData != nullptr) && (outData->data != nullptr) && (outData->size != 0)) {
739         napi_value outDataJs = nullptr;
740         napi_value outBuffer = GenerateArrayBuffer(env, outData->data, outData->size);
741         if (outBuffer == nullptr) {
742             HKS_LOG_E("add outData failed");
743             return nullptr;
744         }
745         NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, outData->size, outBuffer, 0, &outDataJs));
746         NAPI_CALL(env, napi_set_named_property(env, object, HKS_RESULT_PROPERTY_OUTDATA.c_str(), outDataJs));
747         addResult = GetInt32(env, 0);
748     }
749 
750     // add paramSet
751     if (paramSet != nullptr) {
752         napi_value properties = nullptr;
753         properties = GenerateHksParamArray(env, *paramSet);
754         if (properties == nullptr) {
755             HKS_LOG_E("add paramSet failed");
756             return nullptr;
757         }
758         NAPI_CALL(env, napi_set_named_property(env, object, HKS_RESULT_PRPPERTY_PROPERTIES.c_str(), properties));
759         addResult = GetInt32(env, 0);
760     }
761 
762     // add certChain
763     if ((certChain != nullptr) && (certChain->certs != nullptr) && (certChain->certsCount != 0)) {
764         napi_value certChainJs = GenerateStringArray(env, certChain->certs, certChain->certsCount);
765         if (certChainJs == nullptr) {
766             HKS_LOG_E("add certChain failed");
767             return nullptr;
768         }
769         NAPI_CALL(env, napi_set_named_property(env, object, HKS_RESULT_PRPPERTY_CERTCHAINS.c_str(), certChainJs));
770         addResult = GetInt32(env, 0);
771     }
772 
773     return addResult;
774 }
775 
GenerateResult(napi_env env,const struct HksSuccessReturnResult resultData)776 static napi_value GenerateResult(napi_env env, const struct HksSuccessReturnResult resultData)
777 {
778     napi_value result = nullptr;
779 
780     if (resultData.isOnlyReturnBoolResult) {
781         if (napi_get_boolean(env, resultData.boolReturned, &result) != napi_ok) {
782             return GetNull(env);
783         }
784         return result;
785     }
786 
787     if (napi_create_object(env, &result) != napi_ok) {
788         return GetNull(env);
789     }
790 
791     napi_value status1 = AddHandleOrChallenge(env, result, resultData.handle, resultData.challenge);
792     napi_value status2 = AddOutDataParamSetOrCertChain(env, result,
793         resultData.outData, resultData.paramSet, resultData.certChain);
794     if (status1 == nullptr && status2 == nullptr) {
795         return GetNull(env);
796     }
797 
798     return result;
799 }
800 
GenerateBusinessError(napi_env env,int32_t errorCode)801 static napi_value GenerateBusinessError(napi_env env, int32_t errorCode)
802 {
803     napi_value businessError = nullptr;
804     napi_status status = napi_create_object(env, &businessError);
805     if (status != napi_ok) {
806         HKS_LOG_E("create object failed");
807         return GetNull(env);
808     }
809 
810     struct HksResult errInfo = HksConvertErrCode(errorCode);
811     // add errorCode
812     napi_value code = nullptr;
813     status = napi_create_int32(env, errInfo.errorCode, &code);
814     if (status != napi_ok || code == nullptr) {
815         code = GetNull(env);
816     }
817     status = napi_set_named_property(env, businessError, BUSINESS_ERROR_PROPERTY_CODE.c_str(), code);
818     if (status != napi_ok) {
819         HKS_LOG_E("set errorCode failed");
820         return GetNull(env);
821     }
822 
823     // add errorMessage
824     napi_value msg = GetNull(env);
825     if (errInfo.errorMsg != nullptr) {
826 #ifdef HUKS_NAPI_ERRORCODE_WITH_MESSAGE
827         uint32_t errorMsgLen = strlen(errInfo.errorMsg);
828         uint8_t errorMsgBuf[errorMsgLen];
829         (void)memcpy_s(errorMsgBuf, errorMsgLen, errInfo.errorMsg, errorMsgLen);
830         struct HksBlob msgBlob = { errorMsgLen, errorMsgBuf };
831         msg = GenerateStringArray(env, &msgBlob, 1);
832         msg = ((msg == nullptr) ? GetNull(env) : msg);
833 #endif
834     }
835     status = napi_set_named_property(env, businessError, BUSINESS_ERROR_PROPERTY_MESSAGE.c_str(), msg);
836     if (status != napi_ok) {
837         HKS_LOG_E("set errorMsg failed");
838         return GetNull(env);
839     }
840 
841     // add errorData
842     napi_value data = GetNull(env);
843     status = napi_set_named_property(env, businessError, BUSINESS_ERROR_PROPERTY_DATA.c_str(), data);
844     if (status != napi_ok) {
845         HKS_LOG_E("set errorData failed");
846         return GetNull(env);
847     }
848 
849     return businessError;
850 }
851 
CallbackResultFailure(napi_env env,napi_ref callback,int32_t error)852 static void CallbackResultFailure(napi_env env, napi_ref callback, int32_t error)
853 {
854     if (error == HKS_SUCCESS) {
855         HKS_LOG_E("callback: failure cannot be executed");
856         return;
857     }
858 
859     napi_value func = nullptr;
860     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callback, &func));
861 
862     napi_value recv = nullptr;
863     napi_value result = nullptr;
864     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &recv));
865 
866     napi_value businessError = GenerateBusinessError(env, error);
867     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, recv, func, 1, &businessError, &result));
868 }
869 
CallbackResultSuccess(napi_env env,napi_ref callback,const struct HksSuccessReturnResult resultData)870 static void CallbackResultSuccess(napi_env env, napi_ref callback, const struct HksSuccessReturnResult resultData)
871 {
872     napi_value params[ASYNCCALLBACK_ARGC] = { GetNull(env), GenerateResult(env, resultData) };
873     napi_value func = nullptr;
874     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callback, &func));
875 
876     napi_value recv = nullptr;
877     napi_value result = nullptr;
878     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &recv));
879     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, recv, func, ASYNCCALLBACK_ARGC, params, &result));
880 }
881 
PromiseResultFailure(napi_env env,napi_deferred deferred,int32_t error)882 static void PromiseResultFailure(napi_env env, napi_deferred deferred, int32_t error)
883 {
884     if (error == HKS_SUCCESS) {
885         HKS_LOG_E("promise: failure cannot be executed");
886         return;
887     }
888     napi_value result = nullptr;
889     result = GenerateBusinessError(env, error);
890     napi_reject_deferred(env, deferred, result);
891 }
892 
PromiseResultSuccess(napi_env env,napi_deferred deferred,const struct HksSuccessReturnResult resultData)893 static void PromiseResultSuccess(napi_env env, napi_deferred deferred,
894     const struct HksSuccessReturnResult resultData)
895 {
896     napi_value result = nullptr;
897     result = GenerateResult(env, resultData);
898     napi_resolve_deferred(env, deferred, result);
899 }
900 
SuccessReturnResultInit(struct HksSuccessReturnResult & resultData)901 void SuccessReturnResultInit(struct HksSuccessReturnResult &resultData)
902 {
903     resultData.isOnlyReturnBoolResult = false;
904     resultData.boolReturned = false;
905     resultData.handle = nullptr;
906     resultData.challenge = nullptr;
907     resultData.outData = nullptr;
908     resultData.paramSet = nullptr;
909     resultData.certChain = nullptr;
910 }
911 
SuccessListAliasesReturnResultInit(struct HksSuccessListAliasesResult & resultData)912 void SuccessListAliasesReturnResultInit(struct HksSuccessListAliasesResult &resultData)
913 {
914     resultData.aliasSet = nullptr;
915 }
916 
HksReturnNapiResult(napi_env env,napi_ref callback,napi_deferred deferred,int32_t errorCode,const struct HksSuccessReturnResult resultData)917 void HksReturnNapiResult(napi_env env, napi_ref callback, napi_deferred deferred, int32_t errorCode,
918     const struct HksSuccessReturnResult resultData)
919 {
920     if (callback == nullptr) {
921         if (errorCode == HKS_SUCCESS) {
922             PromiseResultSuccess(env, deferred, resultData);
923         } else {
924             PromiseResultFailure(env, deferred, errorCode);
925         }
926     } else {
927         if (errorCode == HKS_SUCCESS) {
928             CallbackResultSuccess(env, callback, resultData);
929         } else {
930             CallbackResultFailure(env, callback, errorCode);
931         }
932     }
933 }
934 
HksReturnKeyExistResult(napi_env env,napi_ref callback,napi_deferred deferred,int32_t errorCode,const struct HksSuccessReturnResult resultData)935 void HksReturnKeyExistResult(napi_env env, napi_ref callback, napi_deferred deferred, int32_t errorCode,
936     const struct HksSuccessReturnResult resultData)
937 {
938     if (callback == nullptr) {
939         if (errorCode == HKS_SUCCESS || errorCode == HKS_ERROR_NOT_EXIST) {
940             PromiseResultSuccess(env, deferred, resultData);
941         } else {
942             PromiseResultFailure(env, deferred, errorCode);
943         }
944     } else {
945         if (errorCode == HKS_SUCCESS || errorCode == HKS_ERROR_NOT_EXIST) {
946             CallbackResultSuccess(env, callback, resultData);
947         } else {
948             CallbackResultFailure(env, callback, errorCode);
949         }
950     }
951 }
952 
CreateJsError(napi_env env,int32_t errCode,const char * errorMsg)953 napi_value CreateJsError(napi_env env, int32_t errCode, const char *errorMsg)
954 {
955     napi_value code = nullptr;
956     NAPI_CALL(env, napi_create_int32(env, errCode, &code));
957 
958     napi_value message = nullptr;
959     NAPI_CALL(env, napi_create_string_utf8(env, errorMsg, strlen(errorMsg), &message));
960 
961     napi_value result = nullptr;
962     NAPI_CALL(env, napi_create_error(env, code, message, &result));
963     return result;
964 }
965 
GenerateListAliasesResult(napi_env env,const struct HksSuccessListAliasesResult resultData)966 static napi_value GenerateListAliasesResult(napi_env env, const struct HksSuccessListAliasesResult resultData)
967 {
968     napi_value result = nullptr;
969 
970     if (napi_create_object(env, &result) != napi_ok) {
971         return GetNull(env);
972     }
973     // add aliases
974     if ((resultData.aliasSet != nullptr) && (resultData.aliasSet->aliases != nullptr) &&
975         (resultData.aliasSet->aliasesCnt != 0)) {
976         napi_value keyAliasesJs = GenerateStringArray(env, resultData.aliasSet->aliases,
977             resultData.aliasSet->aliasesCnt);
978         if (keyAliasesJs == nullptr) {
979             HKS_LOG_E("add keyAliases failed");
980             return GetNull(env);
981         }
982         NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PRPPERTY_ALIASES.c_str(), keyAliasesJs));
983     } else {
984         napi_value array = nullptr;
985         NAPI_CALL(env, napi_create_array(env, &array));
986         NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PRPPERTY_ALIASES.c_str(), array));
987     }
988     return result;
989 }
990 
PromiseListAliasesResultSuccess(napi_env env,napi_deferred deferred,const struct HksSuccessListAliasesResult resultData)991 static void PromiseListAliasesResultSuccess(napi_env env, napi_deferred deferred,
992     const struct HksSuccessListAliasesResult resultData)
993 {
994     napi_value result = nullptr;
995     result = GenerateListAliasesResult(env, resultData);
996     napi_resolve_deferred(env, deferred, result);
997 }
998 
HksReturnListAliasesResult(napi_env env,napi_ref callback,napi_deferred deferred,int32_t errorCode,const struct HksSuccessListAliasesResult resultData)999 void HksReturnListAliasesResult(napi_env env, napi_ref callback, napi_deferred deferred, int32_t errorCode,
1000     const struct HksSuccessListAliasesResult resultData)
1001 {
1002     // now not support callback
1003     if (callback == nullptr) {
1004         if (errorCode == HKS_SUCCESS) {
1005             PromiseListAliasesResultSuccess(env, deferred, resultData);
1006         } else {
1007             PromiseResultFailure(env, deferred, errorCode);
1008         }
1009     }
1010 }
1011 }  // namespace HuksNapiItem
1012