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