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 #include <string>
16 #include <unordered_map>
17 #include "securec.h"
18 #include "js_async_work.h"
19 #include "devattest_errno.h"
20 #include "devattest_interface.h"
21 #include "devattest_log.h"
22 #include "native_device_attest.h"
23 using namespace std;
24
25 namespace OHOS {
26 namespace ACELite {
27 static const std::unordered_map<uint32_t, std::string> g_errorStringMap = {
28 {DEVATTEST_ERR_JS_IS_NOT_SYSTEM_APP,
29 "This api is system api, Please use the system application to call this api"},
30 {DEVATTEST_ERR_JS_PARAMETER_ERROR, "Input paramters wrong"},
31 {DEVATTEST_ERR_JS_SYSTEM_SERVICE_EXCEPTION, "System service exception, please try again or reboot your device"},
32 };
33
GetErrorMessage(uint32_t errorCode)34 string GetErrorMessage(uint32_t errorCode)
35 {
36 auto iter = g_errorStringMap.find(errorCode);
37 if (iter != g_errorStringMap.end()) {
38 return iter->second;
39 } else {
40 return "Unknown error, please reboot your device and try again";
41 }
42 }
43
GetJsiErrorMessage(int32_t errorCode)44 static JSIValue GetJsiErrorMessage(int32_t errorCode)
45 {
46 JSIValue error = JSI::CreateObject();
47 if (error == nullptr) {
48 return nullptr;
49 }
50 if (errorCode == DEVATTEST_FAIL) {
51 errorCode = DEVATTEST_ERR_JS_SYSTEM_SERVICE_EXCEPTION;
52 }
53 JSI::SetStringProperty(error, "message", GetErrorMessage(errorCode).c_str());
54 JSI::SetNumberProperty(error, "code", errorCode);
55 return error;
56 }
57
58
FailCallBack(const JSIValue thisVal, const JSIValue args, int32_t ret)59 void FailCallBack(const JSIValue thisVal, const JSIValue args, int32_t ret)
60 {
61 if (JSI::ValueIsUndefined(args)) {
62 return;
63 }
64 JSIValue error = GetJsiErrorMessage(ret);
65 JSIValue data = JSI::CreateUndefined();
66 JSIValue argv[ARGC_TWO] = {error, data};
67 JSI::CallFunction(args, thisVal, argv, ARGC_TWO);
68 JSI::ReleaseValueList(error, data, ARGS_END);
69 }
70
SuccessCallBack(const JSIValue thisVal, const JSIValue args, JSIValue jsiValue)71 void SuccessCallBack(const JSIValue thisVal, const JSIValue args, JSIValue jsiValue)
72 {
73 if (JSI::ValueIsUndefined(args)) {
74 return;
75 }
76 JSIValue error = JSI::CreateUndefined();
77 JSIValue argv[ARGC_TWO] = {error, jsiValue};
78 JSI::CallFunction(args, thisVal, argv, ARGC_TWO);
79 JSI::ReleaseValueList(error, ARGS_END);
80 }
81
IsValidParam(const JSIValue* args, uint8_t argsNum)82 bool IsValidParam(const JSIValue* args, uint8_t argsNum)
83 {
84 if ((argsNum == 1) && !JSI::ValueIsUndefined(args[0])) {
85 return true;
86 }
87 return false;
88 }
89
ExecuteAsyncWork(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum, AsyncWorkHandler ExecuteFunc)90 JSIValue ExecuteAsyncWork(const JSIValue thisVal, const JSIValue* args,
91 uint8_t argsNum, AsyncWorkHandler ExecuteFunc)
92 {
93 JSIValue undefValue = JSI::CreateUndefined();
94 if (args == NULL) {
95 return GetJsiErrorMessage(DEVATTEST_ERR_JS_PARAMETER_ERROR);
96 }
97 if (!IsValidParam(args, argsNum)) {
98 FailCallBack(thisVal, *args, DEVATTEST_ERR_JS_PARAMETER_ERROR);
99 return undefValue;
100 }
101 FuncParams* params = new(std::nothrow) FuncParams();
102 if (params == nullptr) {
103 FailCallBack(thisVal, *args, DEVATTEST_ERR_JS_SYSTEM_SERVICE_EXCEPTION);
104 return undefValue;
105 }
106 params->thisVal = JSI::AcquireValue(thisVal);
107 params->args = JSI::AcquireValue(args[0]);
108 JsAsyncWork::DispatchAsyncWork(ExecuteFunc, reinterpret_cast<void *>(params));
109 return undefValue;
110 }
111
SetJsResult(JSIValue *result, AttestResultInfo *attestResultInfo)112 int32_t SetJsResult(JSIValue *result, AttestResultInfo *attestResultInfo)
113 {
114 JSI::SetNumberProperty(*result, "authResult", attestResultInfo->authResult);
115 JSI::SetNumberProperty(*result, "softwareResult", attestResultInfo->softwareResult);
116
117 JSIValue array = JSI::CreateNull();
118 size_t size = sizeof(attestResultInfo->softwareResultDetail) / sizeof(int32_t);
119 if (size > 0) {
120 bool isArray = false;
121 array = JSI::CreateArray(size);
122 isArray = JSI::ValueIsArray(array);
123 if (!isArray) {
124 HILOGE("JSI_create_array fail");
125 return DEVATTEST_FAIL;
126 }
127 JSIValue element = JSI::CreateNull();
128 for (size_t i = 0; i != size; ++i) {
129 element = JSI::CreateNumber(attestResultInfo->softwareResultDetail[i]);
130 JSI::SetPropertyByIndex(array, i, element);
131 JSI::ReleaseValue(element);
132 }
133 }
134 JSI::SetNamedProperty(*result, "softwareResultDetail", array);
135
136 JSI::SetStringProperty(*result, "ticket", attestResultInfo->ticket);
137 return DEVATTEST_SUCCESS;
138 }
139
GetAttestResultInfo(JSIValue *result)140 int32_t GetAttestResultInfo(JSIValue *result)
141 {
142 AttestResultInfo attestResultInfo = { 0 };
143 attestResultInfo.ticket = NULL;
144 int32_t ret = GetAttestStatus(&attestResultInfo);
145 if (ret != DEVATTEST_SUCCESS) {
146 HILOGE("[GetAttestResultInfo] Failed to GetAttestStatus");
147 return ret;
148 }
149
150 if (attestResultInfo.ticket == NULL) {
151 return ret;
152 }
153
154 ret = SetJsResult(result, &attestResultInfo);
155 free(attestResultInfo.ticket);
156 attestResultInfo.ticket = NULL;
157 return ret;
158 }
159
ExecuteGetAttestResult(void* data)160 void ExecuteGetAttestResult(void* data)
161 {
162 FuncParams* params = reinterpret_cast<FuncParams *>(data);
163 if (params == nullptr) {
164 return;
165 }
166 JSIValue args = params->args;
167 JSIValue thisVal = params->thisVal;
168 JSIValue result = JSI::CreateObject();
169 int32_t ret = GetAttestResultInfo(&result);
170 if (ret != DEVATTEST_SUCCESS) {
171 FailCallBack(thisVal, args, ret);
172 } else {
173 SuccessCallBack(thisVal, args, result);
174 }
175 JSI::ReleaseValueList(args, thisVal, result, ARGS_END);
176 delete params;
177 params = nullptr;
178 return;
179 }
180
GetAttestResultInfoSync(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)181 JSIValue NativeDeviceAttest::GetAttestResultInfoSync(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
182 {
183 HILOGI("[GetAttestResultInfoSync] In.");
184 AttestResultInfo attestResultInfo = { 0 };
185 attestResultInfo.ticket = NULL;
186
187 int32_t ret = GetAttestStatus(&attestResultInfo);
188 if (ret != DEVATTEST_SUCCESS) {
189 HILOGE("[GetAttestResultInfoSync] Failed to GetAttestStatus");
190 return GetJsiErrorMessage(ret);
191 }
192
193 if (attestResultInfo.ticket == NULL) {
194 return GetJsiErrorMessage(DEVATTEST_ERR_JS_SYSTEM_SERVICE_EXCEPTION);
195 }
196
197 JSIValue result = JSI::CreateObject();
198 ret = SetJsResult(&result, &attestResultInfo);
199 if (ret != DEVATTEST_SUCCESS) {
200 JSI::ReleaseValueList(result, ARGS_END);
201 return GetJsiErrorMessage(DEVATTEST_ERR_JS_SYSTEM_SERVICE_EXCEPTION);
202 }
203
204 free(attestResultInfo.ticket);
205 attestResultInfo.ticket = NULL;
206
207 return result;
208 }
209
GetAttestResultInfoAsync(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)210 JSIValue NativeDeviceAttest::GetAttestResultInfoAsync(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
211 {
212 HILOGI("[GetAttestResultInfoAsync] In.");
213 return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteGetAttestResult);
214 }
215
216
InitDeviceAttestModule(JSIValue exports)217 void InitDeviceAttestModule(JSIValue exports)
218 {
219 JSI::SetModuleAPI(exports, "getAttestStatus", NativeDeviceAttest::GetAttestResultInfoAsync);
220 JSI::SetModuleAPI(exports, "getAttestStatusSync", NativeDeviceAttest::GetAttestResultInfoSync);
221 }
222 } // namespace ACELite
223 } // namespace OHOS