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