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