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