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