• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &params)
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, &param);
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> &params)
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> &paramsVector, struct HksParamSet **outParamSet)
239 {
240     int32_t ret;
241     struct HksParamSet *paramSet = nullptr;
242     do {
243         ret = HksInitParamSet(&paramSet);
244         HKS_IF_NOT_SUCC_BREAK(ret)
245         for (auto &param : paramsVector) {
246             ret = HksAddParams(paramSet, &param, 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(&paramSet);
253         *outParamSet = paramSet;
254     } while (0);
255     if (ret != HKS_SUCCESS) {
256         HksFreeParamSet(&paramSet);
257     }
258     return ret;
259 }
260 
GetAndPushBundleNameToVector(std::vector<HksParam> & paramsVector)261 static int32_t GetAndPushBundleNameToVector(std::vector<HksParam> &paramsVector)
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 }