1 /*
2  * Copyright (c) 2022-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.h"
17 
18 #include <securec.h>
19 
20 #include "anonymizer.h"
21 #include "auth_common.h"
22 #include "auth_hichain_adapter.h"
23 #include "auth_log.h"
24 #include "auth_session_fsm.h"
25 #include "bus_center_manager.h"
26 #include "device_auth.h"
27 #include "lnn_event.h"
28 #include "lnn_net_builder.h"
29 #include "softbus_adapter_mem.h"
30 #include "softbus_def.h"
31 #include "softbus_json_utils.h"
32 
33 #define AUTH_APPID "softbus_auth"
34 #define GROUPID_BUF_LEN 65
35 #define KEY_LENGTH 16 /* Note: WinPc's special nearby only support 128 bits key */
36 #define ONTRANSMIT_MAX_DATA_BUFFER_LEN 5120 /* 5 × 1024 */
37 
38 #define HICHAIN_DAS_ERRCODE_MIN    0xF0000001
39 #define HICHAIN_DAS_ERRCODE_MAX    0xF00010FF
40 #define HICHAIN_COMMON_ERRCODE_MIN 0x0001
41 #define HICHAIN_COMMON_ERRCODE_MAX 0xFFFF
42 #define MASK_HIGH_4BIT             0xF000
43 #define MASK_LOW_8BIT              0x00FF
44 #define MASK_LOW_16BIT             0xFFFF
45 #define ERRCODE_OR_BIT             0x1000
46 #define ERRCODE_SHIFT_21BIT        21
47 #define ERRCODE_SHIFT_16BIT        16
48 #define ERRCODE_SHIFT_12BIT        12
49 #define ERRCODE_SHIFT_8BIT         8
50 #define SHORT_UDID_HASH_LEN        8
51 
52 typedef struct {
53     char groupId[GROUPID_BUF_LEN];
54     GroupType groupType;
55 } GroupInfo;
56 
57 static TrustDataChangeListener g_dataChangeListener;
58 
GenDeviceLevelParam(const char *udid, const char *uid, bool isClient)59 static char *GenDeviceLevelParam(const char *udid, const char *uid, bool isClient)
60 {
61     cJSON *msg = cJSON_CreateObject();
62     if (msg == NULL) {
63         AUTH_LOGE(AUTH_HICHAIN, "create json fail");
64         return NULL;
65     }
66     if (!AddStringToJsonObject(msg, FIELD_PEER_CONN_DEVICE_ID, udid) ||
67         !AddStringToJsonObject(msg, FIELD_SERVICE_PKG_NAME, AUTH_APPID) ||
68         !AddBoolToJsonObject(msg, FIELD_IS_DEVICE_LEVEL, true) ||
69         !AddBoolToJsonObject(msg, FIELD_IS_CLIENT, isClient) ||
70         !AddBoolToJsonObject(msg, FIELD_IS_UDID_HASH, false) ||
71         !AddNumberToJsonObject(msg, FIELD_KEY_LENGTH, KEY_LENGTH)) {
72         AUTH_LOGE(AUTH_HICHAIN, "add json object fail");
73         cJSON_Delete(msg);
74         return NULL;
75     }
76 #ifdef AUTH_ACCOUNT
77     AUTH_LOGI(AUTH_HICHAIN, "in account auth mode");
78     if (!AddStringToJsonObject(msg, FIELD_UID_HASH, uid)) {
79         AUTH_LOGE(AUTH_HICHAIN, "add uid into json fail");
80         cJSON_Delete(msg);
81         return NULL;
82     }
83 #endif
84     char *data = cJSON_PrintUnformatted(msg);
85     if (data == NULL) {
86         AUTH_LOGE(AUTH_HICHAIN, "cJSON_PrintUnformatted fail");
87     }
88     cJSON_Delete(msg);
89     return data;
90 }
91 
OnTransmit(int64_t authSeq, const uint8_t *data, uint32_t len)92 static bool OnTransmit(int64_t authSeq, const uint8_t *data, uint32_t len)
93 {
94     AUTH_CHECK_AND_RETURN_RET_LOGE(len <= ONTRANSMIT_MAX_DATA_BUFFER_LEN, false, AUTH_HICHAIN,
95         "data len is invalid, len=%{public}u", len);
96     AUTH_LOGI(AUTH_HICHAIN, "hichain OnTransmit: authSeq=%{public}" PRId64 ", len=%{public}u", authSeq, len);
97     if (AuthSessionPostAuthData(authSeq, data, len) != SOFTBUS_OK) {
98         AUTH_LOGE(AUTH_HICHAIN, "hichain OnTransmit fail: authSeq=%{public}" PRId64, authSeq);
99         return false;
100     }
101     return true;
102 }
103 
DfxRecordLnnExchangekeyEnd(int64_t authSeq, int32_t reason)104 static void DfxRecordLnnExchangekeyEnd(int64_t authSeq, int32_t reason)
105 {
106     LnnEventExtra extra = { 0 };
107     LnnEventExtraInit(&extra);
108     extra.authId = (int32_t)authSeq;
109     extra.errcode = reason;
110     extra.result = (reason == SOFTBUS_OK) ? EVENT_STAGE_RESULT_OK : EVENT_STAGE_RESULT_FAILED;
111     LNN_EVENT(EVENT_SCENE_JOIN_LNN, EVENT_STAGE_AUTH_EXCHANGE_CIPHER, extra);
112 }
113 
OnSessionKeyReturned(int64_t authSeq, const uint8_t *sessionKey, uint32_t sessionKeyLen)114 static void OnSessionKeyReturned(int64_t authSeq, const uint8_t *sessionKey, uint32_t sessionKeyLen)
115 {
116     AUTH_LOGI(AUTH_HICHAIN, "hichain OnSessionKeyReturned: authSeq=%{public}" PRId64 ", len=%{public}u", authSeq,
117         sessionKeyLen);
118     if (sessionKey == NULL || sessionKeyLen > SESSION_KEY_LENGTH) {
119         DfxRecordLnnExchangekeyEnd(authSeq, SOFTBUS_AUTH_GET_SESSION_KEY_FAIL);
120         AUTH_LOGW(AUTH_HICHAIN, "invalid sessionKey");
121         return;
122     }
123     DfxRecordLnnExchangekeyEnd(authSeq, SOFTBUS_OK);
124     (void)AuthSessionSaveSessionKey(authSeq, sessionKey, sessionKeyLen);
125 }
126 
DfxRecordLnnEndHichainEnd(int64_t authSeq, int32_t reason)127 static void DfxRecordLnnEndHichainEnd(int64_t authSeq, int32_t reason)
128 {
129     LnnEventExtra extra = { 0 };
130     LnnEventExtraInit(&extra);
131     extra.authId = (int32_t)authSeq;
132     extra.errcode = reason;
133     extra.result = (reason == SOFTBUS_OK) ? EVENT_STAGE_RESULT_OK : EVENT_STAGE_RESULT_FAILED;
134     LNN_EVENT(EVENT_SCENE_JOIN_LNN, EVENT_STAGE_AUTH_HICHAIN_END, extra);
135 }
136 
OnFinish(int64_t authSeq, int operationCode, const char *returnData)137 static void OnFinish(int64_t authSeq, int operationCode, const char *returnData)
138 {
139     (void)operationCode;
140     (void)returnData;
141     DfxRecordLnnEndHichainEnd(authSeq, SOFTBUS_OK);
142     AUTH_LOGI(AUTH_HICHAIN, "hichain OnFinish: authSeq=%{public}" PRId64, authSeq);
143     (void)AuthSessionHandleAuthFinish(authSeq);
144 }
145 
GetSoftbusHichainAuthErrorCode(uint32_t hichainErrCode, uint32_t *softbusErrCode)146 void GetSoftbusHichainAuthErrorCode(uint32_t hichainErrCode, uint32_t *softbusErrCode)
147 {
148     if (softbusErrCode == NULL) {
149         AUTH_LOGE(AUTH_HICHAIN, "softbusErrCode is null");
150         return;
151     }
152     if (hichainErrCode >= HICHAIN_DAS_ERRCODE_MIN && hichainErrCode <= HICHAIN_DAS_ERRCODE_MAX) {
153         *softbusErrCode = hichainErrCode & MASK_LOW_16BIT;
154         *softbusErrCode = -(((SOFTBUS_SUB_SYSTEM) << ERRCODE_SHIFT_21BIT) |
155             ((AUTH_SUB_MODULE_CODE) << ERRCODE_SHIFT_16BIT) | (*softbusErrCode | ERRCODE_OR_BIT));
156     } else if (hichainErrCode >= HICHAIN_COMMON_ERRCODE_MIN && hichainErrCode <= HICHAIN_COMMON_ERRCODE_MAX) {
157         uint32_t high4bit = 0;
158         uint32_t tempCode = 0;
159         high4bit = hichainErrCode & MASK_HIGH_4BIT;
160         high4bit = high4bit >> ERRCODE_SHIFT_12BIT;
161         tempCode = hichainErrCode & MASK_LOW_8BIT;
162         *softbusErrCode = -(((SOFTBUS_SUB_SYSTEM) << ERRCODE_SHIFT_21BIT) |
163             ((AUTH_SUB_MODULE_CODE) << ERRCODE_SHIFT_16BIT) | (tempCode | (high4bit << ERRCODE_SHIFT_8BIT)));
164     } else {
165         *softbusErrCode = hichainErrCode;
166         AUTH_LOGI(AUTH_HICHAIN, "unknow hichain errcode=%{public}d", hichainErrCode);
167     }
168 }
169 
CheckErrReturnValidity(const char *errorReturn)170 static int32_t CheckErrReturnValidity(const char *errorReturn)
171 {
172     cJSON *json = cJSON_Parse(errorReturn);
173     if (json == NULL || !cJSON_IsString(json)) {
174         AUTH_LOGE(AUTH_HICHAIN, "parse json fail");
175         cJSON_Delete(json);
176         return SOFTBUS_PARSE_JSON_ERR;
177     }
178     cJSON_Delete(json);
179     return SOFTBUS_OK;
180 }
181 
OnError(int64_t authSeq, int operationCode, int errCode, const char *errorReturn)182 static void OnError(int64_t authSeq, int operationCode, int errCode, const char *errorReturn)
183 {
184     (void)operationCode;
185     DfxRecordLnnEndHichainEnd(authSeq, errCode);
186     uint32_t authErrCode = 0;
187     (void)GetSoftbusHichainAuthErrorCode((uint32_t)errCode, &authErrCode);
188     AUTH_LOGE(AUTH_HICHAIN, "hichain OnError: authSeq=%{public}" PRId64 ", errCode=%{public}d authErrCode=%{public}d",
189         authSeq, errCode, authErrCode);
190     if (errorReturn != NULL && CheckErrReturnValidity(errorReturn) == SOFTBUS_OK) {
191         uint32_t errorReturnLen = strlen(errorReturn);
192         (void)AuthFailNotifyDeviceList(errCode, errorReturn, errorReturnLen);
193     }
194     (void)AuthSessionHandleAuthError(authSeq, authErrCode);
195 }
196 
OnRequest(int64_t authSeq, int operationCode, const char *reqParams)197 static char *OnRequest(int64_t authSeq, int operationCode, const char *reqParams)
198 {
199     (void)reqParams;
200     AUTH_LOGI(AUTH_HICHAIN, "hichain OnRequest: authSeq=%{public}" PRId64 ", operationCode=%{public}d", authSeq,
201         operationCode);
202     char udid[UDID_BUF_LEN] = {0};
203     if (AuthSessionGetUdid(authSeq, udid, sizeof(udid)) != SOFTBUS_OK) {
204         AUTH_LOGE(AUTH_HICHAIN, "get udid fail");
205         return NULL;
206     }
207     cJSON *msg = cJSON_CreateObject();
208     if (msg == NULL) {
209         return NULL;
210     }
211     char localUdid[UDID_BUF_LEN] = {0};
212     LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, localUdid, UDID_BUF_LEN);
213     if (!AddNumberToJsonObject(msg, FIELD_CONFIRMATION, REQUEST_ACCEPTED) ||
214         !AddStringToJsonObject(msg, FIELD_SERVICE_PKG_NAME, AUTH_APPID) ||
215         !AddStringToJsonObject(msg, FIELD_PEER_CONN_DEVICE_ID, udid) ||
216         !AddStringToJsonObject(msg, FIELD_DEVICE_ID, localUdid) ||
217         !AddBoolToJsonObject(msg, FIELD_IS_UDID_HASH, false)) {
218         AUTH_LOGE(AUTH_HICHAIN, "pack request msg fail");
219         cJSON_Delete(msg);
220         return NULL;
221     }
222     char *msgStr = cJSON_PrintUnformatted(msg);
223     if (msgStr == NULL) {
224         AUTH_LOGE(AUTH_HICHAIN, "cJSON_PrintUnformatted fail");
225         cJSON_Delete(msg);
226         return NULL;
227     }
228     cJSON_Delete(msg);
229     return msgStr;
230 }
231 
232 static DeviceAuthCallback g_hichainCallback = {
233     .onTransmit = OnTransmit,
234     .onSessionKeyReturned = OnSessionKeyReturned,
235     .onFinish = OnFinish,
236     .onError = OnError,
237     .onRequest = OnRequest
238 };
239 
GetUdidHash(const char *udid, char *udidHash)240 static int32_t GetUdidHash(const char *udid, char *udidHash)
241 {
242     if (udid == NULL || udidHash == NULL) {
243         AUTH_LOGE(AUTH_HICHAIN, "param error");
244         return SOFTBUS_INVALID_PARAM;
245     }
246     int32_t rc = SOFTBUS_OK;
247     uint8_t hash[UDID_HASH_LEN] = { 0 };
248     rc = SoftBusGenerateStrHash((uint8_t *)udid, strlen(udid), hash);
249     if (rc != SOFTBUS_OK) {
250         AUTH_LOGE(AUTH_HICHAIN, "generate udidhash fail");
251         return rc;
252     }
253     rc = ConvertBytesToHexString(udidHash, HB_SHORT_UDID_HASH_HEX_LEN + 1, hash, SHORT_UDID_HASH_LEN);
254     if (rc != SOFTBUS_OK) {
255         AUTH_LOGE(AUTH_HICHAIN, "convert bytes to string fail");
256         return rc;
257     }
258     return SOFTBUS_OK;
259 }
260 
DeletePcRestrictNode(const char *udid)261 static void DeletePcRestrictNode(const char *udid)
262 {
263     char peerUdidHash[HB_SHORT_UDID_HASH_HEX_LEN + 1] = { 0 };
264     uint32_t count = 0;
265 
266     if (GetUdidHash(udid, peerUdidHash) == SOFTBUS_OK && GetNodeFromPcRestrictMap(peerUdidHash, &count) == SOFTBUS_OK) {
267         DeleteNodeFromPcRestrictMap(peerUdidHash);
268         char *anonyUdid = NULL;
269         Anonymize(udid, &anonyUdid);
270         AUTH_LOGI(AUTH_HICHAIN, "delete restrict node success. udid=%{public}s", AnonymizeWrapper(anonyUdid));
271         AnonymizeFree(anonyUdid);
272     }
273 }
274 
ParseGroupInfo(const char *groupInfoStr, GroupInfo *groupInfo)275 static int32_t ParseGroupInfo(const char *groupInfoStr, GroupInfo *groupInfo)
276 {
277     cJSON *msg = cJSON_Parse(groupInfoStr);
278     if (msg == NULL) {
279         AUTH_LOGE(AUTH_HICHAIN, "parse json fail");
280         return SOFTBUS_PARSE_JSON_ERR;
281     }
282     if (!GetJsonObjectStringItem(msg, FIELD_GROUP_ID, groupInfo->groupId, GROUPID_BUF_LEN)) {
283         AUTH_LOGE(AUTH_HICHAIN, "get FIELD_GROUP_ID fail");
284         cJSON_Delete(msg);
285         return SOFTBUS_ERR;
286     }
287     int32_t groupType = 0;
288     if (!GetJsonObjectNumberItem(msg, FIELD_GROUP_TYPE, &groupType)) {
289         AUTH_LOGE(AUTH_HICHAIN, "get FIELD_GROUP_TYPE fail");
290         cJSON_Delete(msg);
291         return SOFTBUS_ERR;
292     }
293     groupInfo->groupType = (GroupType)groupType;
294     cJSON_Delete(msg);
295     return SOFTBUS_OK;
296 }
297 
OnGroupCreated(const char *groupInfo)298 static void OnGroupCreated(const char *groupInfo)
299 {
300     if (groupInfo == NULL) {
301         AUTH_LOGW(AUTH_HICHAIN, "invalid group info");
302         return;
303     }
304     GroupInfo info;
305     (void)memset_s(&info, sizeof(GroupInfo), 0, sizeof(GroupInfo));
306     if (ParseGroupInfo(groupInfo, &info) != SOFTBUS_OK) {
307         return;
308     }
309     AUTH_LOGI(AUTH_HICHAIN, "hichain OnGroupCreated, type=%{public}d", info.groupType);
310     if (g_dataChangeListener.onGroupCreated != NULL) {
311         g_dataChangeListener.onGroupCreated(info.groupId, (int32_t)info.groupType);
312     }
313 }
314 
OnDeviceBound(const char *udid, const char *groupInfo)315 static void OnDeviceBound(const char *udid, const char *groupInfo)
316 {
317     if (udid == NULL || groupInfo == NULL) {
318         AUTH_LOGW(AUTH_HICHAIN, "invalid udid");
319         return;
320     }
321     GroupInfo info;
322     (void)memset_s(&info, sizeof(GroupInfo), 0, sizeof(GroupInfo));
323     if (ParseGroupInfo(groupInfo, &info) != SOFTBUS_OK) {
324         return;
325     }
326     char *anonyUdid = NULL;
327     Anonymize(udid, &anonyUdid);
328     AUTH_LOGI(AUTH_HICHAIN, "hichain onDeviceBound, udid=%{public}s, type=%{public}d",
329         AnonymizeWrapper(anonyUdid), info.groupType);
330     AnonymizeFree(anonyUdid);
331     if (info.groupType == AUTH_IDENTICAL_ACCOUNT_GROUP) {
332         AUTH_LOGI(AUTH_HICHAIN, "ignore same account udid");
333         DeletePcRestrictNode(udid);
334         return;
335     }
336     char localUdid[UDID_BUF_LEN] = { 0 };
337     LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, localUdid, UDID_BUF_LEN);
338     if (strcmp(localUdid, udid) == 0) {
339         AUTH_LOGI(AUTH_HICHAIN, "ignore local udid");
340         return;
341     }
342     if (g_dataChangeListener.onDeviceBound != NULL) {
343         g_dataChangeListener.onDeviceBound(udid, groupInfo);
344     }
345 }
346 
OnGroupDeleted(const char *groupInfo)347 static void OnGroupDeleted(const char *groupInfo)
348 {
349     if (groupInfo == NULL) {
350         AUTH_LOGE(AUTH_HICHAIN, "invalid group info");
351         return;
352     }
353     GroupInfo info;
354     (void)memset_s(&info, sizeof(GroupInfo), 0, sizeof(GroupInfo));
355     if (ParseGroupInfo(groupInfo, &info) != SOFTBUS_OK) {
356         return;
357     }
358     AUTH_LOGI(AUTH_HICHAIN, "hichain OnGroupDeleted, type=%{public}d", info.groupType);
359     if (g_dataChangeListener.onGroupDeleted != NULL) {
360         g_dataChangeListener.onGroupDeleted(info.groupId, info.groupType);
361     }
362 }
363 
OnDeviceNotTrusted(const char *udid)364 static void OnDeviceNotTrusted(const char *udid)
365 {
366     if (udid == NULL) {
367         AUTH_LOGW(AUTH_HICHAIN, "hichain get invalid udid");
368         return;
369     }
370     char *anonyUdid = NULL;
371     Anonymize(udid, &anonyUdid);
372     AUTH_LOGI(AUTH_HICHAIN, "hichain OnDeviceNotTrusted, udid=%{public}s", AnonymizeWrapper(anonyUdid));
373     AnonymizeFree(anonyUdid);
374     if (g_dataChangeListener.onDeviceNotTrusted != NULL) {
375         g_dataChangeListener.onDeviceNotTrusted(udid);
376     }
377 }
378 
RegTrustDataChangeListener(const TrustDataChangeListener *listener)379 int32_t RegTrustDataChangeListener(const TrustDataChangeListener *listener)
380 {
381     if (listener == NULL) {
382         return SOFTBUS_INVALID_PARAM;
383     }
384     g_dataChangeListener = *listener;
385 
386     DataChangeListener hichainListener;
387     (void)memset_s(&hichainListener, sizeof(DataChangeListener), 0, sizeof(DataChangeListener));
388     hichainListener.onGroupCreated = OnGroupCreated;
389     hichainListener.onGroupDeleted = OnGroupDeleted;
390     hichainListener.onDeviceNotTrusted = OnDeviceNotTrusted;
391     hichainListener.onDeviceBound = OnDeviceBound;
392     if (RegChangeListener(AUTH_APPID, &hichainListener) != SOFTBUS_OK) {
393         AUTH_LOGE(AUTH_HICHAIN, "hichain regDataChangeListener fail");
394         return SOFTBUS_AUTH_REG_DATA_FAIL;
395     }
396     return SOFTBUS_OK;
397 }
398 
UnregTrustDataChangeListener(void)399 void UnregTrustDataChangeListener(void)
400 {
401     int32_t ret = UnregChangeListener(AUTH_APPID);
402     if (ret != SOFTBUS_OK) {
403         AUTH_LOGE(AUTH_HICHAIN, "hichain unRegDataChangeListener err=%{public}d", ret);
404     }
405     (void)memset_s(&g_dataChangeListener, sizeof(TrustDataChangeListener), 0, sizeof(TrustDataChangeListener));
406 }
407 
HichainStartAuth(int64_t authSeq, const char *udid, const char *uid)408 int32_t HichainStartAuth(int64_t authSeq, const char *udid, const char *uid)
409 {
410     if (udid == NULL || uid == NULL) {
411         AUTH_LOGE(AUTH_HICHAIN, "udid/uid is invalid");
412         return SOFTBUS_INVALID_PARAM;
413     }
414     char *authParams = GenDeviceLevelParam(udid, uid, true);
415     if (authParams == NULL) {
416         AUTH_LOGE(AUTH_HICHAIN, "generate auth param fail");
417         return SOFTBUS_CREATE_JSON_ERR;
418     }
419     int32_t ret = AuthDevice(authSeq, authParams, &g_hichainCallback);
420     if (ret == SOFTBUS_OK) {
421         AUTH_LOGI(AUTH_HICHAIN, "hichain call authDevice succ");
422         cJSON_free(authParams);
423         return SOFTBUS_OK;
424     }
425     AUTH_LOGE(AUTH_HICHAIN, "hichain call authDevice failed");
426     cJSON_free(authParams);
427     return ret;
428 }
429 
HichainProcessData(int64_t authSeq, const uint8_t *data, uint32_t len)430 int32_t HichainProcessData(int64_t authSeq, const uint8_t *data, uint32_t len)
431 {
432     if (data == NULL) {
433         AUTH_LOGE(AUTH_HICHAIN, "data is null");
434         return SOFTBUS_INVALID_PARAM;
435     }
436     int32_t ret = ProcessAuthData(authSeq, data, len, &g_hichainCallback);
437     if (ret != SOFTBUS_OK) {
438         AUTH_LOGE(AUTH_HICHAIN, "hichain processData err=%{public}d", ret);
439         return ret;
440     }
441     return SOFTBUS_OK;
442 }
443 
HichainDestroy(void)444 void HichainDestroy(void)
445 {
446     UnregTrustDataChangeListener();
447     DestroyDeviceAuth();
448     AUTH_LOGI(AUTH_HICHAIN, "hichain destroy succ");
449 }
450 
HichainCancelRequest(int64_t authReqId)451 void HichainCancelRequest(int64_t authReqId)
452 {
453     CancelRequest(authReqId, AUTH_APPID);
454 }
455