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