1 /*
2  * Copyright (c) 2023-2024 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 "auth_hichain_adapter.h"
17 
18 #include <string.h>
19 
20 #include "auth_common.h"
21 #include "auth_hichain.h"
22 #include "auth_log.h"
23 #include "auth_session_fsm.h"
24 #include "bus_center_manager.h"
25 #include "device_auth.h"
26 #include "device_auth_defines.h"
27 #include "lnn_ohos_account_adapter.h"
28 #include "softbus_adapter_mem.h"
29 #include "softbus_errcode.h"
30 #include "softbus_json_utils.h"
31 
32 #define AUTH_APPID "softbus_auth"
33 #define GROUP_ID "groupId"
34 #define GROUP_TYPE "groupType"
35 #define AUTH_ID "authId"
36 #define RETRY_TIMES 16
37 #define RETRY_MILLSECONDS 500
38 #define SAME_ACCOUNT_GROUY_TYPE 1
39 static const GroupAuthManager *g_hichain = NULL;
40 #define CUST_UDID_LEN 16
41 
InitHichain(void)42 static const GroupAuthManager *InitHichain(void)
43 {
44     int32_t ret = InitDeviceAuthService();
45     if (ret != 0) {
46         AUTH_LOGE(AUTH_INIT, "hichain InitDeviceAuthService failed err=%{public}d", ret);
47         return NULL;
48     }
49     const GroupAuthManager *gaIns = GetGaInstance();
50     if (gaIns == NULL) {
51         AUTH_LOGE(AUTH_INIT, "hichain GetGaInstance failed");
52         DestroyDeviceAuthService();
53         return NULL;
54     }
55     AUTH_LOGI(AUTH_INIT, "hichain init succ");
56     return gaIns;
57 }
58 
RegChangeListener(const char *appId, DataChangeListener *listener)59 int32_t RegChangeListener(const char *appId, DataChangeListener *listener)
60 {
61     AUTH_CHECK_AND_RETURN_RET_LOGE(appId != NULL, SOFTBUS_ERR, AUTH_HICHAIN,
62         "appId is null");
63     AUTH_CHECK_AND_RETURN_RET_LOGE(listener != NULL, SOFTBUS_ERR, AUTH_HICHAIN,
64         "listener is null");
65     if (g_hichain == NULL) {
66         g_hichain = InitHichain();
67     }
68     AUTH_CHECK_AND_RETURN_RET_LOGE(g_hichain != NULL, SOFTBUS_ERR, AUTH_HICHAIN,
69         "hichain not initialized");
70 
71     const DeviceGroupManager *gmInstance = GetGmInstance();
72     AUTH_CHECK_AND_RETURN_RET_LOGE(gmInstance != NULL, SOFTBUS_ERR, AUTH_HICHAIN,
73         "hichain GetGmInstance failed");
74 
75     int32_t ret = gmInstance->regDataChangeListener(appId, listener);
76     AUTH_CHECK_AND_RETURN_RET_LOGE(ret == 0, SOFTBUS_ERR, AUTH_HICHAIN,
77         "hichain regDataChangeListener failed=%{public}d", ret);
78 
79     return SOFTBUS_OK;
80 }
81 
UnregChangeListener(const char *appId)82 int32_t UnregChangeListener(const char *appId)
83 {
84     AUTH_CHECK_AND_RETURN_RET_LOGE(appId != NULL, SOFTBUS_INVALID_PARAM, AUTH_HICHAIN,
85         "appId is null");
86     const DeviceGroupManager *gmInstance = GetGmInstance();
87     AUTH_CHECK_AND_RETURN_RET_LOGE(gmInstance != NULL, SOFTBUS_ERR, AUTH_HICHAIN,
88         "hichain GetGmInstance failed");
89     int32_t ret = gmInstance->unRegDataChangeListener(appId);
90     AUTH_CHECK_AND_RETURN_RET_LOGE(ret == 0, SOFTBUS_ERR, AUTH_HICHAIN,
91         "hichain unRegDataChangeListener failed=%{public}d", ret);
92 
93     return SOFTBUS_OK;
94 }
95 
AuthDevice(int64_t authReqId, const char *authParams, const DeviceAuthCallback *cb)96 int32_t AuthDevice(int64_t authReqId, const char *authParams, const DeviceAuthCallback *cb)
97 {
98     AUTH_CHECK_AND_RETURN_RET_LOGE(authParams != NULL && cb != NULL, SOFTBUS_INVALID_PARAM,
99         AUTH_HICHAIN, "authParams or cb is null");
100     if (g_hichain == NULL) {
101         g_hichain = InitHichain();
102     }
103     AUTH_CHECK_AND_RETURN_RET_LOGE(g_hichain != NULL, SOFTBUS_ERR, AUTH_HICHAIN, "hichain not initialized");
104 
105     uint32_t authErrCode = 0;
106     for (int32_t i = 1; i < RETRY_TIMES; i++) {
107         int32_t ret = g_hichain->authDevice(ANY_OS_ACCOUNT, authReqId, authParams, cb);
108         if (ret == HC_SUCCESS) {
109             AUTH_LOGI(AUTH_HICHAIN, "hichain call authDevice success, times=%{public}d", i);
110             return SOFTBUS_OK;
111         }
112         (void)GetSoftbusHichainAuthErrorCode((uint32_t)ret, &authErrCode);
113         if (ret != HC_ERR_INVALID_PARAMS) {
114             AUTH_LOGE(AUTH_HICHAIN, "hichain call authDevice failed, err=%{public}d, authErrCode=%{public}d", ret,
115                 authErrCode);
116             return authErrCode;
117         }
118         AUTH_LOGW(AUTH_HICHAIN,
119             "hichain retry call authDevice, current retry times=%{public}d, err=%{public}d", i, ret);
120         (void)SoftBusSleepMs(RETRY_MILLSECONDS);
121     }
122     return authErrCode;
123 }
124 
ProcessAuthData(int64_t authSeq, const uint8_t *data, uint32_t len, DeviceAuthCallback *cb)125 int32_t ProcessAuthData(int64_t authSeq, const uint8_t *data, uint32_t len, DeviceAuthCallback *cb)
126 {
127     AUTH_CHECK_AND_RETURN_RET_LOGE(data != NULL && cb != NULL, SOFTBUS_INVALID_PARAM, AUTH_HICHAIN,
128         "data or cb is null");
129     if (g_hichain == NULL) {
130         g_hichain = InitHichain();
131     }
132     AUTH_CHECK_AND_RETURN_RET_LOGE(g_hichain != NULL, SOFTBUS_ERR, AUTH_HICHAIN, "hichain not initialized");
133 
134     int32_t ret = g_hichain->processData(authSeq, data, len, cb);
135     AUTH_CHECK_AND_RETURN_RET_LOGE(ret == 0, SOFTBUS_ERR, AUTH_HICHAIN,
136         "hichain processData failed. ret=%{public}d", ret);
137 
138     return SOFTBUS_OK;
139 }
140 
CheckDeviceInGroupByType(const char *udid, const char *uuid, HichainGroup groupType)141 bool CheckDeviceInGroupByType(const char *udid, const char *uuid, HichainGroup groupType)
142 {
143     (void)udid;
144     (void)uuid;
145     (void)groupType;
146     return false;
147 }
148 
DestroyDeviceAuth(void)149 void DestroyDeviceAuth(void)
150 {
151     DestroyDeviceAuthService();
152     g_hichain = NULL;
153     AUTH_LOGI(AUTH_HICHAIN, "hichain destroy succ");
154 }
155 
IsTrustedDeviceInAGroup(const DeviceGroupManager *gmInstance, int32_t accountId, const char *groupId, const char *deviceId)156 static bool IsTrustedDeviceInAGroup(const DeviceGroupManager *gmInstance, int32_t accountId,
157     const char *groupId, const char *deviceId)
158 {
159     uint32_t deviceNum = 0;
160     char *returnDevInfoVec = NULL;
161     if (gmInstance->getTrustedDevices(accountId, AUTH_APPID, groupId, &returnDevInfoVec, &deviceNum) != SOFTBUS_OK) {
162         gmInstance->destroyInfo(&returnDevInfoVec);
163         AUTH_LOGE(AUTH_HICHAIN, "GetTrustedDevices fail");
164         return false;
165     }
166     if (deviceNum == 0) {
167         gmInstance->destroyInfo(&returnDevInfoVec);
168         AUTH_LOGI(AUTH_HICHAIN, "GetTrustedDevices zero");
169         return false;
170     }
171     cJSON *devJson = cJSON_Parse(returnDevInfoVec);
172     if (devJson == NULL) {
173         gmInstance->destroyInfo(&returnDevInfoVec);
174         AUTH_LOGE(AUTH_HICHAIN, "parse json fail");
175         return false;
176     }
177     int32_t devArraySize = cJSON_GetArraySize(devJson);
178     for (int32_t j = 0; j < devArraySize; j++) {
179         cJSON *devItem = cJSON_GetArrayItem(devJson, j);
180         char authId[UDID_BUF_LEN] = {0};
181         if (!GetJsonObjectStringItem(devItem, AUTH_ID, authId, UDID_BUF_LEN)) {
182             AUTH_LOGE(AUTH_HICHAIN, "AUTH_ID not found");
183             continue;
184         }
185         uint8_t udidHash[SHA_256_HASH_LEN] = {0};
186         char hashStr[CUST_UDID_LEN + 1] = {0};
187         if (SoftBusGenerateStrHash((const unsigned char *)authId, strlen(authId), udidHash) != SOFTBUS_OK) {
188             continue;
189         }
190         if (ConvertBytesToHexString(hashStr, CUST_UDID_LEN + 1, udidHash,
191             CUST_UDID_LEN / HEXIFY_UNIT_LEN) != SOFTBUS_OK) {
192             continue;
193         }
194         if (strncmp(hashStr, deviceId, strlen(deviceId)) == 0) {
195             cJSON_Delete(devJson);
196             gmInstance->destroyInfo(&returnDevInfoVec);
197             return true;
198         }
199     }
200     cJSON_Delete(devJson);
201     gmInstance->destroyInfo(&returnDevInfoVec);
202     return false;
203 }
204 
HasTrustedRelationWithLocalDevice(const DeviceGroupManager *gmInstance, int32_t accountId, char *localUdid, const char *deviceId, bool isPointToPoint)205 static bool HasTrustedRelationWithLocalDevice(const DeviceGroupManager *gmInstance, int32_t accountId,
206     char *localUdid, const char *deviceId, bool isPointToPoint)
207 {
208     uint32_t groupNum = 0;
209     char *returnGroupVec = NULL;
210     if (gmInstance->getRelatedGroups(accountId, AUTH_APPID, localUdid, &returnGroupVec, &groupNum) != SOFTBUS_OK) {
211         AUTH_LOGE(AUTH_HICHAIN, "GetRelatedGroups fail, accountId=%{public}d", accountId);
212         gmInstance->destroyInfo(&returnGroupVec);
213         return false;
214     }
215     if (groupNum == 0) {
216         AUTH_LOGI(AUTH_HICHAIN, "GetRelatedGroups zero");
217         gmInstance->destroyInfo(&returnGroupVec);
218         return false;
219     }
220     cJSON *groupJson = cJSON_Parse(returnGroupVec);
221     if (groupJson == NULL) {
222         AUTH_LOGE(AUTH_HICHAIN, "parse json fail");
223         gmInstance->destroyInfo(&returnGroupVec);
224         return false;
225     }
226     int32_t groupArraySize = cJSON_GetArraySize(groupJson);
227     for (int32_t i = 0; i < groupArraySize; i++) {
228         cJSON *groupItem = cJSON_GetArrayItem(groupJson, i);
229         char groupId[UDID_BUF_LEN] = {0};
230         if (isPointToPoint) {
231             int groupType = 0;
232             if ((GetJsonObjectNumberItem(groupItem, GROUP_TYPE, &groupType) && groupType == SAME_ACCOUNT_GROUY_TYPE)) {
233                 AUTH_LOGD(AUTH_HICHAIN, "ignore same account group");
234                 continue;
235             }
236         }
237         if (!GetJsonObjectStringItem(groupItem, GROUP_ID, groupId, UDID_BUF_LEN)) {
238             AUTH_LOGE(AUTH_HICHAIN, "GROUP_ID not found");
239             continue;
240         }
241         if (IsTrustedDeviceInAGroup(gmInstance, accountId, groupId, deviceId)) {
242             cJSON_Delete(groupJson);
243             gmInstance->destroyInfo(&returnGroupVec);
244             return true;
245         }
246     }
247     cJSON_Delete(groupJson);
248     gmInstance->destroyInfo(&returnGroupVec);
249     return false;
250 }
251 
IsPotentialTrustedDevice(TrustedRelationIdType idType, const char *deviceId, bool isPrecise, bool isPointToPoint)252 bool IsPotentialTrustedDevice(TrustedRelationIdType idType, const char *deviceId, bool isPrecise, bool isPointToPoint)
253 {
254     (void)idType;
255     (void)isPrecise;
256     if (deviceId == NULL) {
257         AUTH_LOGE(AUTH_HICHAIN, "deviceId is null");
258         return false;
259     }
260     const DeviceGroupManager *gmInstance = GetGmInstance();
261     if (gmInstance == NULL) {
262         AUTH_LOGE(AUTH_HICHAIN, "hichain GetGmInstance failed");
263         return false;
264     }
265 
266     int32_t accountId = GetActiveOsAccountIds();
267     if (accountId <= 0) {
268         AUTH_LOGE(AUTH_HICHAIN, "accountId is invalid");
269         return false;
270     }
271 
272     char localUdid[UDID_BUF_LEN] = {0};
273     if (LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, localUdid, UDID_BUF_LEN) != SOFTBUS_OK) {
274         AUTH_LOGE(AUTH_HICHAIN, "get udid fail");
275         return false;
276     }
277     return HasTrustedRelationWithLocalDevice(gmInstance, accountId, localUdid, deviceId, isPointToPoint);
278 }
279 
HichainGetJoinedGroups(int32_t groupType)280 uint32_t HichainGetJoinedGroups(int32_t groupType)
281 {
282     uint32_t groupCnt = 0;
283     char *accountGroups = NULL;
284 
285     const DeviceGroupManager *gmInstance = GetGmInstance();
286     AUTH_CHECK_AND_RETURN_RET_LOGE(gmInstance != NULL, groupCnt, AUTH_HICHAIN, "hichain GetGmInstance failed");
287 
288     if (gmInstance->getJoinedGroups(0, AUTH_APPID, (GroupType)groupType, &accountGroups, &groupCnt) != 0) {
289         AUTH_LOGE(AUTH_HICHAIN, "hichain getJoinedGroups groupCnt fail");
290         groupCnt = 0;
291     }
292     if (accountGroups != NULL) {
293         SoftBusFree(accountGroups);
294     }
295     return groupCnt;
296 }
297 
IsSameAccountGroupDevice(void)298 bool IsSameAccountGroupDevice(void)
299 {
300     uint32_t groupNum = 0;
301     char *returnGroupVec = NULL;
302 
303     const DeviceGroupManager *gmInstance = GetGmInstance();
304     if (gmInstance == NULL) {
305         AUTH_LOGE(AUTH_HICHAIN, "hichain GetGmInstance failed");
306         return false;
307     }
308     int32_t accountId = GetActiveOsAccountIds();
309     if (accountId <= 0) {
310         AUTH_LOGE(AUTH_HICHAIN, "accountId is invalid");
311         return false;
312     }
313 
314     if (gmInstance->getJoinedGroups(accountId, AUTH_APPID, SAME_ACCOUNT_GROUY_TYPE, &returnGroupVec, &groupNum) !=
315         SOFTBUS_OK) {
316         AUTH_LOGE(AUTH_HICHAIN, "getJoinedGroups fail, accountId=%{public}d", accountId);
317         gmInstance->destroyInfo(&returnGroupVec);
318         return false;
319     }
320     if (groupNum == 0) {
321         AUTH_LOGE(AUTH_HICHAIN, "getJoinedGroups zero");
322         gmInstance->destroyInfo(&returnGroupVec);
323         return false;
324     } else {
325         AUTH_LOGI(AUTH_HICHAIN, "getJoinedGroups: %{public}d", groupNum);
326         gmInstance->destroyInfo(&returnGroupVec);
327         return true;
328     }
329 }
330 
CancelRequest(int64_t authReqId, const char *appId)331 void CancelRequest(int64_t authReqId, const char *appId)
332 {
333     AUTH_CHECK_AND_RETURN_LOGE(appId != NULL, AUTH_HICHAIN, "appId is null");
334     if (g_hichain == NULL) {
335         g_hichain = InitHichain();
336     }
337     AUTH_CHECK_AND_RETURN_LOGE(g_hichain != NULL, AUTH_HICHAIN, "hichain not initialized");
338     g_hichain->cancelRequest(authReqId, appId);
339 }