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