1 /*
2 * Copyright (c) 2023 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 #define HUKS_DISABLE_LOG_AT_FILE_TO_REDUCE_ROM_SIZE
16
17 #include "hks_lite_api_common.h"
18 #include "hks_lite_api.h"
19 #include "hks_log.h"
20 #include "hks_errcode_adapter.h"
21 #include "jsi.h"
22 #include "jsi_types.h"
23 #include "js_app_context.h"
24
25 #include "hks_api.h"
26 #include "hks_param.h"
27 #include "hks_template.h"
28 #include "hks_type_inner.h"
29
30 #include "securec.h"
31
32 #include <cstring>
33 #include <vector>
34
35 namespace OHOS {
36 namespace ACELite {
37 #define RELEASE_JSI_VALUE_IF_NOT_NULL(jsiValue) \
38 do { \
39 if ((jsiValue) != nullptr) { \
40 JSI::ReleaseValue(jsiValue); \
41 jsiValue = nullptr; \
42 } \
43 } while (0)
44
45 #define RELEASE_JSI_STRING_IF_NOT_NULL(jsiString) \
46 do { \
47 if ((jsiString) != nullptr) { \
48 JSI::ReleaseString(jsiString); \
49 jsiString = nullptr; \
50 } \
51 } while (0)
52
CheckIsNumberAndAssignIntParam(const JSIValue paramProperty,uint32_t paramTag,struct HksParam * outParam)53 static int32_t CheckIsNumberAndAssignIntParam(const JSIValue paramProperty, uint32_t paramTag,
54 struct HksParam *outParam)
55 {
56 int32_t ret = HKS_ERROR_INVALID_ARGUMENT;
57 JSIValue valueJSIValue = JSI::GetNamedProperty(paramProperty, HKS_PARAM_PROPERTY_VALUE);
58 if (JSI::ValueIsNumber(valueJSIValue)) {
59 int32_t paramValue = (int32_t)JSI::ValueToNumber(valueJSIValue);
60 outParam->tag = paramTag;
61 outParam->int32Param = paramValue;
62 ret = HKS_SUCCESS;
63 }
64 RELEASE_JSI_VALUE_IF_NOT_NULL(valueJSIValue);
65 return ret;
66 }
67
CheckIsNumberAndAssignUintParam(const JSIValue paramProperty,uint32_t paramTag,struct HksParam * outParam)68 static int32_t CheckIsNumberAndAssignUintParam(const JSIValue paramProperty, uint32_t paramTag,
69 struct HksParam *outParam)
70 {
71 int32_t ret = HKS_ERROR_INVALID_ARGUMENT;
72 JSIValue valueJSIValue = JSI::GetNamedProperty(paramProperty, HKS_PARAM_PROPERTY_VALUE);
73 if (JSI::ValueIsNumber(valueJSIValue)) {
74 uint32_t paramValue = (uint32_t)JSI::ValueToNumber(valueJSIValue);
75 outParam->tag = paramTag;
76 outParam->uint32Param = paramValue;
77 ret = HKS_SUCCESS;
78 }
79 RELEASE_JSI_VALUE_IF_NOT_NULL(valueJSIValue);
80 return ret;
81 }
82
CheckIsNumberAndAssignUlongParam(const JSIValue paramProperty,uint32_t paramTag,struct HksParam * outParam)83 static int32_t CheckIsNumberAndAssignUlongParam(const JSIValue paramProperty, uint32_t paramTag,
84 struct HksParam *outParam)
85 {
86 int32_t ret = HKS_ERROR_INVALID_ARGUMENT;
87 JSIValue valueJSIValue = JSI::GetNamedProperty(paramProperty, HKS_PARAM_PROPERTY_VALUE);
88 if (JSI::ValueIsNumber(valueJSIValue)) {
89 uint64_t paramValue = (uint64_t)JSI::ValueToNumber(valueJSIValue);
90 outParam->tag = paramTag;
91 outParam->uint64Param = paramValue;
92 ret = HKS_SUCCESS;
93 }
94 RELEASE_JSI_VALUE_IF_NOT_NULL(valueJSIValue);
95 return ret;
96 }
97
CheckIsBoolAndAssignBoolParam(const JSIValue paramProperty,uint32_t paramTag,struct HksParam * outParam)98 static int32_t CheckIsBoolAndAssignBoolParam(const JSIValue paramProperty, uint32_t paramTag,
99 struct HksParam *outParam)
100 {
101 int32_t ret = HKS_ERROR_INVALID_ARGUMENT;
102 JSIValue valueJSIValue = JSI::GetNamedProperty(paramProperty, HKS_PARAM_PROPERTY_VALUE);
103 if (JSI::ValueIsBoolean(valueJSIValue)) {
104 bool paramValue = (bool)JSI::ValueToBoolean(valueJSIValue);
105 outParam->tag = paramTag;
106 outParam->boolParam = paramValue;
107 ret = HKS_SUCCESS;
108 }
109 RELEASE_JSI_VALUE_IF_NOT_NULL(valueJSIValue);
110 return ret;
111 }
112
ParseUint8ArrayToHksBlob(JSIValue value,struct HksBlob * outData)113 static int32_t ParseUint8ArrayToHksBlob(JSIValue value, struct HksBlob *outData)
114 {
115 if (!JSI::ValueIsTypedArray(value)) {
116 HKS_LOG_E("value is not a typed array");
117 return HKS_ERROR_INVALID_ARGUMENT;
118 }
119 TypedArrayType arrayType;
120 size_t arraySize = 0;
121 size_t byteOffset = 0;
122 JSIValue arrayBuffer;
123 uint8_t *dataArray;
124 int32_t ret = HKS_SUCCESS;
125 do {
126 dataArray = JSI::GetTypedArrayInfo(value, arrayType, arraySize, arrayBuffer, byteOffset);
127 if (dataArray == nullptr) {
128 ret = HKS_FAILURE;
129 break;
130 }
131 if (arrayType != TypedArrayType::JSI_UINT8_ARRAY) {
132 HKS_LOG_E("value is not a uint8 array");
133 ret = HKS_ERROR_INVALID_ARGUMENT;
134 break;
135 }
136 outData->data = (uint8_t *)HksMalloc(arraySize);
137 if (outData->data == nullptr) {
138 ret = HKS_ERROR_MALLOC_FAIL;
139 break;
140 }
141 memcpy_s(outData->data, arraySize, dataArray + byteOffset, arraySize);
142 outData->size = arraySize;
143 } while (0);
144 RELEASE_JSI_VALUE_IF_NOT_NULL(arrayBuffer);
145 return ret;
146 }
147
CheckIsBytesAndAssignBlobParam(const JSIValue paramProperty,uint32_t paramTag,struct HksParam * outParam)148 static int32_t CheckIsBytesAndAssignBlobParam(const JSIValue paramProperty, uint32_t paramTag,
149 struct HksParam *outParam)
150 {
151 int32_t ret = HKS_ERROR_INVALID_ARGUMENT;
152 JSIValue valueJSIValue = JSI::GetNamedProperty(paramProperty, HKS_PARAM_PROPERTY_VALUE);
153 do {
154 if (!JSI::ValueIsTypedArray(valueJSIValue)) {
155 HKS_LOG_E("value is not array");
156 ret = HKS_ERROR_INVALID_ARGUMENT;
157 break;
158 }
159 ret = ParseUint8ArrayToHksBlob(valueJSIValue, &(outParam->blob));
160 outParam->tag = paramTag;
161 } while (0);
162 RELEASE_JSI_VALUE_IF_NOT_NULL(valueJSIValue);
163 return ret;
164 }
165
HksParseParam(const JSIValue paramProperty,struct HksParam * outParam)166 static int32_t HksParseParam(const JSIValue paramProperty, struct HksParam *outParam)
167 {
168 uint32_t paramTag = (uint32_t)JSI::GetNumberProperty(paramProperty, HKS_PARAM_PROPERTY_TAG);
169 int32_t ret;
170 switch (paramTag & HKS_TAG_TYPE_MASK) {
171 case HKS_TAG_TYPE_INT:
172 ret = CheckIsNumberAndAssignIntParam(paramProperty, paramTag, outParam);
173 break;
174 case HKS_TAG_TYPE_UINT:
175 ret = CheckIsNumberAndAssignUintParam(paramProperty, paramTag, outParam);
176 break;
177 case HKS_TAG_TYPE_ULONG:
178 ret = CheckIsNumberAndAssignUlongParam(paramProperty, paramTag, outParam);
179 break;
180 case HKS_TAG_TYPE_BOOL:
181 ret = CheckIsBoolAndAssignBoolParam(paramProperty, paramTag, outParam);
182 break;
183 case HKS_TAG_TYPE_BYTES:
184 ret = CheckIsBytesAndAssignBlobParam(paramProperty, paramTag, outParam);
185 break;
186 default:
187 HKS_LOG_E("invalid tag value 0x%" LOG_PUBLIC "x", paramTag);
188 ret = HKS_ERROR_INVALID_ARGUMENT;
189 break;
190 }
191 return ret;
192 }
193
HksParseParamsToVector(const JSIValue paramSetValue,std::vector<HksParam> & params)194 static int32_t HksParseParamsToVector(const JSIValue paramSetValue, std::vector<HksParam> ¶ms)
195 {
196 int32_t ret = HKS_SUCCESS;
197 do {
198 if (!JSI::ValueIsArray(paramSetValue)) {
199 ret = HKS_ERROR_INVALID_ARGUMENT;
200 break;
201 }
202 uint32_t paramCnt = JSI::GetArrayLength(paramSetValue);
203 if (paramCnt == 0) {
204 break;
205 }
206 for (uint32_t i = 0; i < paramCnt; ++i) {
207 JSIValue paramProperty = JSI::GetPropertyByIndex(paramSetValue, i);
208 struct HksParam param = { 0 };
209 ret = HksParseParam(paramProperty, ¶m);
210 if (ret != HKS_SUCCESS) {
211 RELEASE_JSI_VALUE_IF_NOT_NULL(paramProperty);
212 break;
213 }
214 params.push_back(param);
215 RELEASE_JSI_VALUE_IF_NOT_NULL(paramProperty);
216 }
217 } while (0);
218 return ret;
219 }
220
HksReleaseParamVectors(std::vector<HksParam> & params)221 static void HksReleaseParamVectors(std::vector<HksParam> ¶ms)
222 {
223 struct HksParam *param = params.data();
224 size_t paramCount = params.size();
225 if (param == nullptr) {
226 return;
227 }
228 while (paramCount > 0) {
229 paramCount--;
230 if ((param->tag & HKS_TAG_TYPE_MASK) == HKS_TAG_TYPE_BYTES) {
231 HKS_FREE(param->blob.data);
232 param->blob.size = 0;
233 }
234 ++param;
235 }
236 }
237
HksParseParamsToParamSet(const std::vector<HksParam> & paramsVector,struct HksParamSet ** outParamSet)238 static int32_t HksParseParamsToParamSet(const std::vector<HksParam> ¶msVector, struct HksParamSet **outParamSet)
239 {
240 int32_t ret;
241 struct HksParamSet *paramSet = nullptr;
242 do {
243 ret = HksInitParamSet(¶mSet);
244 HKS_IF_NOT_SUCC_BREAK(ret)
245 for (auto ¶m : paramsVector) {
246 ret = HksAddParams(paramSet, ¶m, 1);
247 if (ret != HKS_SUCCESS) {
248 HKS_LOG_E("add param.tag[%" LOG_PUBLIC "u] failed", param.tag);
249 break;
250 }
251 }
252 ret = HksBuildParamSet(¶mSet);
253 *outParamSet = paramSet;
254 } while (0);
255 if (ret != HKS_SUCCESS) {
256 HksFreeParamSet(¶mSet);
257 }
258 return ret;
259 }
260
GetAndPushBundleNameToVector(std::vector<HksParam> & paramsVector)261 static int32_t GetAndPushBundleNameToVector(std::vector<HksParam> ¶msVector)
262 {
263 JsAppContext *appContext = JsAppContext::GetInstance();
264 if (appContext == nullptr) {
265 HKS_LOG_E("appContext is null.");
266 return HKS_FAILURE;
267 }
268 const char *curBundleName = appContext->GetCurrentBundleName();
269 if (curBundleName == nullptr) {
270 return HKS_FAILURE;
271 }
272
273 struct HksParam curBundleNameParam = { 0 };
274 curBundleNameParam.tag = HKS_TAG_BUNDLE_NAME;
275 curBundleNameParam.blob.data = (uint8_t *)HksMalloc(strlen(curBundleName) + 1);
276 if (curBundleNameParam.blob.data == nullptr) {
277 return HKS_ERROR_MALLOC_FAIL;
278 }
279 curBundleNameParam.blob.size = strlen(curBundleName) + 1; // the last \0 need to be counted
280
281 (void)memcpy_s(curBundleNameParam.blob.data, strlen(curBundleName), curBundleName, strlen(curBundleName));
282 curBundleNameParam.blob.data[strlen(curBundleName)] = '\0';
283 paramsVector.push_back(curBundleNameParam);
284 return HKS_SUCCESS;
285 }
286
HksParseParamSetWithAdd(const JSIValue * args,uint32_t index,struct HksParamSet ** outParamSet,struct HksParam * paramsToAdd,uint32_t paramsToAddSize)287 int32_t HksParseParamSetWithAdd(const JSIValue* args, uint32_t index, struct HksParamSet **outParamSet,
288 struct HksParam *paramsToAdd, uint32_t paramsToAddSize)
289 {
290 std::vector<HksParam> paramsVector;
291
292 JSIValue paramSetValue = nullptr;
293 int32_t ret;
294 do {
295 paramSetValue = JSI::GetNamedProperty(args[index], HKS_OPTIONS_PROPERTY_PROPERTIES);
296 if (paramSetValue == nullptr) {
297 HKS_LOG_I("no properties setted, but it is tolerable");
298 } else {
299 ret = HksParseParamsToVector(paramSetValue, paramsVector);
300 if (ret != HKS_SUCCESS) {
301 HKS_LOG_E("parse params to vector failed");
302 break;
303 }
304 }
305
306 ret = GetAndPushBundleNameToVector(paramsVector);
307 if (ret != HKS_SUCCESS) {
308 HKS_LOG_E("add bundle name failed");
309 break;
310 }
311
312 if (paramsToAdd != nullptr && paramsToAddSize != 0) {
313 for (uint32_t i = 0; i < paramsToAddSize; ++i) {
314 paramsVector.push_back(paramsToAdd[i]);
315 }
316 }
317
318 ret = HksParseParamsToParamSet(paramsVector, outParamSet);
319 } while (0);
320 HksReleaseParamVectors(paramsVector);
321 RELEASE_JSI_VALUE_IF_NOT_NULL(paramSetValue);
322 return ret;
323 }
324
HksParseKeyAlias(const JSIValue * args,uint32_t index,struct HksBlob * outKeyAliasBlob)325 int32_t HksParseKeyAlias(const JSIValue* args, uint32_t index, struct HksBlob *outKeyAliasBlob)
326 {
327 if (!JSI::ValueIsString(args[index])) {
328 HKS_LOG_E("keyAlias is not a string");
329 return HKS_ERROR_INVALID_ARGUMENT;
330 }
331 char *keyAlias = JSI::ValueToString(args[index]);
332 if (keyAlias == nullptr) {
333 HKS_LOG_E("convert keyAlias jsivalue to string failed");
334 return HKS_FAILURE;
335 }
336 outKeyAliasBlob->size = strlen(keyAlias);
337 outKeyAliasBlob->data = (uint8_t *)HksMalloc(outKeyAliasBlob->size);
338 if (outKeyAliasBlob->data == nullptr) {
339 RELEASE_JSI_STRING_IF_NOT_NULL(keyAlias);
340 return HKS_ERROR_MALLOC_FAIL;
341 }
342 (void)memcpy_s(outKeyAliasBlob->data, outKeyAliasBlob->size, keyAlias, outKeyAliasBlob->size);
343 RELEASE_JSI_STRING_IF_NOT_NULL(keyAlias);
344 return HKS_SUCCESS;
345 }
346
HksParseHandle(const JSIValue * args,uint32_t index,struct HksBlob * outHandle)347 int32_t HksParseHandle(const JSIValue* args, uint32_t index, struct HksBlob *outHandle)
348 {
349 if (!JSI::ValueIsNumber(args[index])) {
350 HKS_LOG_E("handle is not a number");
351 return HKS_ERROR_INVALID_ARGUMENT;
352 }
353 uint64_t handle = (uint64_t)JSI::ValueToNumber(args[index]);
354 outHandle->data = (uint8_t *)HksMalloc(sizeof(uint64_t));
355 if (outHandle->data == nullptr) {
356 return HKS_ERROR_MALLOC_FAIL;
357 }
358 if (memcpy_s(outHandle->data, sizeof(uint64_t), &handle, sizeof(uint64_t)) != EOK) {
359 HKS_LOG_E("copy outHandle data failed!");
360 HKS_FREE_BLOB(*outHandle);
361 return HKS_ERROR_INSUFFICIENT_MEMORY;
362 }
363 outHandle->size = sizeof(uint64_t);
364 return HKS_SUCCESS;
365 }
366
HksParseInData(const JSIValue * args,uint32_t index,struct HksBlob * outInData)367 int32_t HksParseInData(const JSIValue* args, uint32_t index, struct HksBlob *outInData)
368 {
369 JSIValue valueJSIValue = JSI::GetNamedProperty(args[index], HKS_OPTIONS_PROPERTY_INDATA);
370 int32_t ret = ParseUint8ArrayToHksBlob(valueJSIValue, outInData);
371 RELEASE_JSI_VALUE_IF_NOT_NULL(valueJSIValue);
372 return ret;
373 }
374
375 // convert from huks inner error code to jsi err
HksConvertErrorCodeToError(int32_t rawErrorCode)376 JSIValue HksConvertErrorCodeToError(int32_t rawErrorCode)
377 {
378 struct HksResult result = HksConvertErrCode(rawErrorCode);
379 JSIValue res = JSI::CreateObject();
380 JSI::SetNumberProperty(res, BUSINESS_ERROR_PROPERTY_CODE, (double)result.errorCode);
381 JSI::SetStringProperty(res, BUSINESS_ERROR_PROPERTY_MESSAGE, result.errorMsg);
382 return res;
383 }
384
385 // HuksReturnResult, only outData is used in lite system
HksConstructJSIReturnResult(const struct HksLiteApiResult * result)386 JSIValue HksConstructJSIReturnResult(const struct HksLiteApiResult *result)
387 {
388 if (result->isBoolean) {
389 // the only possible res for result is boolean only for success case is the true
390 return JSI::CreateBoolean(true);
391 }
392 JSIValue res;
393 do {
394 res = JSI::CreateObject();
395 if (res == nullptr) {
396 break;
397 }
398 if (result->outData != nullptr) {
399 uint8_t *arrayBuffer = nullptr;
400 JSIValue buffer = JSI::CreateArrayBuffer(result->outData->size, arrayBuffer);
401 if (arrayBuffer == nullptr) {
402 HKS_LOG_E("create jsi array buffer failed");
403 JSI::ReleaseValue(buffer);
404 return res;
405 }
406 (void)memcpy_s(arrayBuffer, result->outData->size, result->outData->data, result->outData->size);
407 JSIValue typedArray = JSI::CreateTypedArray(TypedArrayType::JSI_UINT8_ARRAY, result->outData->size,
408 buffer, 0);
409 JSI::SetNamedProperty(res, HKS_RESULT_PROPERTY_OUTDATA, typedArray);
410 JSI::ReleaseValueList(buffer, typedArray, ARGS_END);
411 }
412 if (result->handle != nullptr) {
413 JSI::SetNumberProperty(res, HKS_HANDLE_PROPERTY_HANDLE, *((uint64_t *)result->handle->data));
414 }
415 } while (0);
416 return res;
417 }
418
HksCallbackResultFailure(const JSIValue thisVal,const JSIValue callback,int32_t error)419 void HksCallbackResultFailure(const JSIValue thisVal, const JSIValue callback, int32_t error)
420 {
421 JSIValue params[2] = { HksConvertErrorCodeToError(error), JSI::CreateNull()};
422 JSI::CallFunction(callback, thisVal, params, HKS_ARRAY_SIZE(params));
423 RELEASE_JSI_VALUE_IF_NOT_NULL(params[0]);
424 RELEASE_JSI_VALUE_IF_NOT_NULL(params[1]);
425 }
426
HksCallbackResultSuccess(const JSIValue thisVal,JSIValue callback,const struct HksLiteApiResult * result)427 void HksCallbackResultSuccess(const JSIValue thisVal, JSIValue callback, const struct HksLiteApiResult *result)
428 {
429 JSIValue params[2] = { JSI::CreateNull(), HksConstructJSIReturnResult(result) };
430 JSI::CallFunction(callback, thisVal, params, HKS_ARRAY_SIZE(params));
431 RELEASE_JSI_VALUE_IF_NOT_NULL(params[0]);
432 RELEASE_JSI_VALUE_IF_NOT_NULL(params[1]);
433 }
434
InitHuksModule(void)435 int32_t InitHuksModule(void)
436 {
437 return HksInitialize();
438 }
439 }
440 }