1 /*
2  * Copyright (c) 2022 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 "dslm_core_process.h"
17 
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <unistd.h>
22 
23 #include "securec.h"
24 
25 #include "device_security_defines.h"
26 #include "dslm_callback_info.h"
27 #include "dslm_core_defines.h"
28 #include "dslm_cred.h"
29 #include "dslm_credential.h"
30 #include "dslm_device_list.h"
31 #include "dslm_fsm_process.h"
32 #include "dslm_hievent.h"
33 #include "dslm_hitrace.h"
34 #include "dslm_messenger_wrapper.h"
35 #include "dslm_msg_serialize.h"
36 #include "dslm_msg_utils.h"
37 #include "dslm_notify_node.h"
38 #include "utils_datetime.h"
39 #include "utils_log.h"
40 #include "utils_mutex.h"
41 #include "utils_state_machine.h"
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 #define MAX_NOTIFY_SIZE 64
48 #define DEFAULT_TYPE 10
49 
50 static const DeviceIdentify *RefreshDeviceOnlineStatus(const DeviceIdentify *deviceId);
51 
OnPeerMsgRequestInfoReceived(const DeviceIdentify * deviceId,const uint8_t * msg,uint32_t len)52 int32_t OnPeerMsgRequestInfoReceived(const DeviceIdentify *deviceId, const uint8_t *msg, uint32_t len)
53 {
54     if (deviceId == NULL || msg == NULL || len == 0) {
55         return ERR_INVALID_PARA;
56     }
57 
58     SECURITY_LOG_DEBUG("msg is %s", (char *)msg);
59     MessageBuff buff = {.length = len, .buff = (uint8_t *)msg};
60 
61     RequestObject reqObject;
62     (void)memset_s(&reqObject, sizeof(RequestObject), 0, sizeof(RequestObject));
63 
64     // Parse the msg
65     int32_t ret = ParseDeviceSecInfoRequest(&buff, &reqObject);
66     if (ret != SUCCESS) {
67         return ret;
68     }
69 
70     // process
71     DslmCredBuff *cred = NULL;
72     ret = DefaultRequestDslmCred(deviceId, &reqObject, &cred);
73     if (ret != SUCCESS) {
74         return ret;
75     }
76 
77     // build and send response
78     MessageBuff *resBuff = NULL;
79     ret = BuildDeviceSecInfoResponse(reqObject.challenge, cred, &resBuff);
80     if (ret == SUCCESS) {
81         SendMsgToDevice(0, deviceId, resBuff->buff, resBuff->length);
82         FreeMessageBuff(resBuff);
83     }
84     DestroyDslmCred(cred);
85 
86     return SUCCESS;
87 }
88 
OnPeerMsgResponseInfoReceived(const DeviceIdentify * deviceId,const uint8_t * msg,uint32_t len)89 int32_t OnPeerMsgResponseInfoReceived(const DeviceIdentify *deviceId, const uint8_t *msg, uint32_t len)
90 {
91     if (deviceId == NULL || msg == NULL || len == 0) {
92         return ERR_INVALID_PARA;
93     }
94     SECURITY_LOG_DEBUG("msg is %s", (char *)msg);
95 
96     DslmDeviceInfo *deviceInfo = GetDslmDeviceInfo(deviceId);
97     if (deviceInfo == NULL) {
98         SECURITY_LOG_ERROR("no existed device");
99         return ERR_NOEXIST_DEVICE;
100     }
101 
102     MessageBuff buff = {
103         .length = len,
104         .buff = (uint8_t *)msg,
105     };
106 
107     ScheduleDslmStateMachine(deviceInfo, EVENT_CRED_RSP, &buff);
108     ReportHiEventInfoSync(deviceInfo);
109     return SUCCESS;
110 }
111 
OnMsgSendResultNotifier(const DeviceIdentify * deviceId,uint64_t transNo,uint32_t result)112 int32_t OnMsgSendResultNotifier(const DeviceIdentify *deviceId, uint64_t transNo, uint32_t result)
113 {
114     SECURITY_LOG_INFO("msg trans is %{public}u result %{public}u", (uint32_t)transNo, result);
115 
116     if (result == SUCCESS) {
117         return SUCCESS;
118     }
119 
120     DslmDeviceInfo *deviceInfo = GetDslmDeviceInfo(deviceId);
121     if (deviceInfo == NULL) {
122         return SUCCESS;
123     }
124 
125     SECURITY_LOG_INFO("current DslmDeviceInfo transNum is %{public}u", (uint32_t)deviceInfo->transNum);
126     if (deviceInfo->transNum != transNo) {
127         return SUCCESS;
128     }
129 
130     if (deviceInfo->credInfo.credLevel != 0) {
131         return SUCCESS;
132     }
133 
134     ScheduleDslmStateMachine(deviceInfo, EVENT_MSG_SEND_FAILED, &result);
135 
136     return SUCCESS;
137 }
138 
OnRequestDeviceSecLevelInfo(const DeviceIdentify * deviceId,const RequestOption * option,uint32_t owner,uint32_t cookie,RequestCallback callback)139 int32_t OnRequestDeviceSecLevelInfo(const DeviceIdentify *deviceId, const RequestOption *option, uint32_t owner,
140     uint32_t cookie, RequestCallback callback)
141 {
142     if (deviceId == NULL || option == NULL || callback == NULL) {
143         SECURITY_LOG_ERROR("invalid params");
144         return ERR_INVALID_PARA;
145     }
146 
147     if (GetMessengerStatus() != true) {
148         SECURITY_LOG_ERROR("softbus service not startup complete");
149         return ERR_MSG_NOT_INIT;
150     }
151 
152     const DeviceIdentify *curr = RefreshDeviceOnlineStatus(deviceId);
153 
154     DslmDeviceInfo *deviceInfo = GetDslmDeviceInfo(curr);
155     if (deviceInfo == NULL) {
156         SECURITY_LOG_ERROR("input device not exist");
157         return ERR_NOEXIST_DEVICE;
158     }
159 
160     ReportHiEventAppInvoke(deviceInfo);
161 
162     if (deviceInfo->onlineStatus != ONLINE_STATUS_ONLINE) {
163         SECURITY_LOG_ERROR("input device not online");
164         return ERR_NOT_ONLINE;
165     }
166 
167     if (deviceInfo->notifyListSize >= MAX_NOTIFY_SIZE) {
168         SECURITY_LOG_ERROR("input device's notifyList is overloaded");
169         return ERR_SA_BUSY;
170     }
171 
172     DslmNotifyListNode notifyNode;
173     (void)memset_s(&notifyNode, sizeof(notifyNode), 0, sizeof(notifyNode));
174     notifyNode.owner = owner;
175     notifyNode.cookie = cookie;
176     notifyNode.requestCallback = callback;
177     notifyNode.start = GetMillisecondSinceBoot();
178     notifyNode.keep = option->timeout * 1000; // 1000 ms per second
179     ScheduleDslmStateMachine(deviceInfo, EVENT_SDK_GET, &notifyNode);
180     return SUCCESS;
181 }
182 
OnPeerStatusReceiver(const DeviceIdentify * deviceId,uint32_t status,int32_t level)183 int32_t OnPeerStatusReceiver(const DeviceIdentify *deviceId, uint32_t status, int32_t level)
184 {
185     DslmDeviceInfo *info = CreatOrGetDslmDeviceInfo(deviceId);
186     if (info == NULL) {
187         return SUCCESS;
188     }
189 
190     if (info->onlineStatus == status) {
191         return SUCCESS;
192     }
193 
194     uint32_t event = (status == ONLINE_STATUS_ONLINE) ? EVENT_DEVICE_ONLINE : EVENT_DEVICE_OFFLINE;
195 
196     ScheduleDslmStateMachine(info, event, &level);
197     return SUCCESS;
198 }
199 
InitSelfDeviceSecureLevel(void)200 bool InitSelfDeviceSecureLevel(void)
201 {
202     int32_t level = 0;
203     const DeviceIdentify *device = GetSelfDevice(&level);
204     if (device->length == 0) {
205         SECURITY_LOG_ERROR("GetSelfDevice failed");
206         ReportHiEventInitSelfFailed("GetSelfDevice failed");
207         return false;
208     }
209 
210     DslmDeviceInfo *info = CreatOrGetDslmDeviceInfo(device);
211     if (info == NULL) {
212         SECURITY_LOG_ERROR("CreatOrGetDslmDeviceInfo failed");
213         ReportHiEventInitSelfFailed("CreatOrGetDslmDeviceInfo failed");
214         return false;
215     }
216 
217     info->onlineStatus = ONLINE_STATUS_ONLINE;
218     info->osType = DEFAULT_TYPE;
219     if (info->lastOnlineTime == 0) {
220         info->lastOnlineTime = GetMillisecondSinceBoot();
221     }
222     if (level > 0) {
223         info->credInfo.credLevel = (uint32_t)level;
224     }
225     if (info->credInfo.credLevel > 0) {
226         info->result = SUCCESS;
227         info->machine.currState = STATE_SUCCESS;
228         return true;
229     }
230 
231     info->machine.currState = STATE_FAILED;
232     int32_t ret = DefaultInitDslmCred(&info->credInfo);
233     if (ret == SUCCESS && info->credInfo.credLevel > 0) {
234         info->machine.currState = STATE_SUCCESS;
235         info->result = SUCCESS;
236         return true;
237     }
238 
239     ret = OnPeerStatusReceiver(device, ONLINE_STATUS_ONLINE, level);
240     if (ret != SUCCESS) {
241         SECURITY_LOG_ERROR("make self online failed");
242     }
243     return true;
244 }
245 
InitDslmProcess(void)246 bool InitDslmProcess(void)
247 {
248     static bool isInited = false;
249     static Mutex initMutex = INITED_MUTEX;
250 
251     if (GetMessengerStatus() == false) {
252         return false;
253     }
254 
255     if (isInited == true) {
256         return true;
257     }
258 
259     LockMutex(&initMutex);
260     bool result = InitSelfDeviceSecureLevel();
261     if (result) {
262         isInited = true;
263     }
264     UnlockMutex(&initMutex);
265     return isInited;
266 }
267 
DeinitDslmProcess(void)268 bool DeinitDslmProcess(void)
269 {
270     return true;
271 }
272 
RefreshDeviceOnlineStatus(const DeviceIdentify * deviceId)273 static const DeviceIdentify *RefreshDeviceOnlineStatus(const DeviceIdentify *deviceId)
274 {
275     int32_t level = 0;
276     if (deviceId == NULL) {
277         return NULL;
278     }
279 
280     if (deviceId->identity[0] == 0) {
281         SECURITY_LOG_INFO("RefreshDeviceOnlineStatus to self");
282         return GetSelfDevice(&level);
283     }
284 
285     if (GetPeerDeviceOnlineStatus(deviceId, &level)) {
286         (void)OnPeerStatusReceiver(deviceId, ONLINE_STATUS_ONLINE, level);
287     }
288 
289     if (IsSameDevice(deviceId, GetSelfDevice(&level))) {
290         (void)InitSelfDeviceSecureLevel();
291     }
292 
293     return deviceId;
294 }
295 
296 #ifdef __cplusplus
297 }
298 #endif
299