• 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 #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