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 ¶m)
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, ¶m.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, ¶m.int32Param));
197 result = GetInt32(env, 0);
198 break;
199 case HKS_TAG_TYPE_UINT:
200 NAPI_CALL(env, napi_get_value_uint32(env, value, ¶m.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 *>(¶m.uint64Param)));
205 result = GetInt32(env, 0);
206 break;
207 case HKS_TAG_TYPE_BOOL:
208 NAPI_CALL(env, napi_get_value_bool(env, value, ¶m.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> ¶ms)
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> ¶ms)
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 *¶mSet,
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 *¶mSet)
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 ¶m)
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 ¶mSet)
406 {
407 napi_value paramArray = nullptr;
408 NAPI_CALL(env, napi_create_array(env, ¶mArray));
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 *¶mSet)
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(¶mSet);
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 *¶mSet)
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 *¶mSet)
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 *¶mSet)
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