1 /*
2  * Copyright (C) 2022-2023 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 "account_related_group_auth.h"
17 #include "account_auth_plugin_proxy.h"
18 #include "common_defs.h"
19 #include "device_auth_defines.h"
20 #include "group_auth_data_operation.h"
21 #include "hc_dev_info.h"
22 #include "hc_log.h"
23 #include "hc_time.h"
24 #include "hc_types.h"
25 #include "json_utils.h"
26 #include "performance_dumper.h"
27 #include "string_util.h"
28 #include "alg_loader.h"
29 #include "hisysevent_adapter.h"
30 
31 #define UID_HEX_STRING_LEN_MAX 64
32 #define UID_HEX_STRING_LEN_MIN 10
33 #define MAX_SERVICE_PEER_DATA_LENGTH 2048
34 #define PLACE_HOLDER_LENGTH 4
35 #define COMMA_SEPARATOR ","
36 #define COLON_SEPARATOR ":"
37 #define JSON_KEY_FORMAT "\"%s\":"
38 
39 static void OnAccountFinish(int64_t requestId, const CJson *authParam, const CJson *out,
40     const DeviceAuthCallback *callback);
41 static int32_t FillAccountAuthInfo(int32_t osAccountId, const TrustedGroupEntry *entry,
42     const TrustedDeviceEntry *localAuthInfo, CJson *paramsData);
43 static void GetAccountCandidateGroup(int32_t osAccountId, const CJson *param,
44     QueryGroupParams *queryParams, GroupEntryVec *vec);
45 static int32_t GetAuthParamsVecForServer(const CJson *dataFromClient, ParamsVecForAuth *authParamsVec);
46 static int32_t CombineAccountServerConfirms(const CJson *confirmationJson, CJson *dataFromClient);
47 
48 static AccountRelatedGroupAuth g_accountRelatedGroupAuth = {
49     .base.onFinish = OnAccountFinish,
50     .base.fillDeviceAuthInfo = FillAccountAuthInfo,
51     .base.getAuthParamsVecForServer = GetAuthParamsVecForServer,
52     .base.combineServerConfirmParams = CombineAccountServerConfirms,
53     .base.authType = ACCOUNT_RELATED_GROUP_AUTH_TYPE,
54     .getAccountCandidateGroup = GetAccountCandidateGroup,
55 };
56 
ReturnSessionKey(int64_t requestId,const CJson * out,const DeviceAuthCallback * callback)57 static int32_t ReturnSessionKey(int64_t requestId, const CJson *out, const DeviceAuthCallback *callback)
58 {
59     const char *returnSessionKeyStr = GetStringFromJson(out, FIELD_SESSION_KEY);
60     if (returnSessionKeyStr == NULL) {
61         LOGE("Failed to get sessionKey!");
62         return HC_ERR_JSON_GET;
63     }
64     uint32_t keyLen = (HcStrlen(returnSessionKeyStr) / BYTE_TO_HEX_OPER_LENGTH);
65     uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0);
66     if (sessionKey == NULL) {
67         LOGE("Failed to allocate memory for sessionKey!");
68         return HC_ERR_ALLOC_MEMORY;
69     }
70 
71     int32_t res = HC_SUCCESS;
72     do {
73         if (GetByteFromJson(out, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) {
74             LOGE("Failed to get sessionKey!");
75             res = HC_ERR_JSON_GET;
76             break;
77         }
78         if ((callback == NULL) || (callback->onSessionKeyReturned == NULL)) {
79             LOGE("The callback of onSessionKeyReturned is null!");
80             res = HC_ERR_INVALID_PARAMS;
81             break;
82         }
83         LOGI("Begin invoke onSessionKeyReturned.");
84         UPDATE_PERFORM_DATA_BY_INPUT_INDEX(requestId, ON_SESSION_KEY_RETURN_TIME, HcGetCurTimeInMillis());
85         callback->onSessionKeyReturned(requestId, sessionKey, keyLen);
86         LOGI("End invoke onSessionKeyReturned, res = %d.", res);
87     } while (0);
88     (void)memset_s(sessionKey, keyLen, 0, keyLen);
89     HcFree(sessionKey);
90     sessionKey = NULL;
91     return res;
92 }
93 
GetSessionKeyForAccount(const CJson * sendToSelf,CJson * returnToSelf)94 static int32_t GetSessionKeyForAccount(const CJson *sendToSelf, CJson *returnToSelf)
95 {
96     int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH;
97     uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0);
98     if (sessionKey == NULL) {
99         LOGE("Failed to allocate memory for sessionKey!");
100         return HC_ERR_ALLOC_MEMORY;
101     }
102     int32_t res = HC_SUCCESS;
103     do {
104         if (GetByteFromJson(sendToSelf, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) {
105             LOGE("Failed to get sessionKey!");
106             res = HC_ERR_JSON_GET;
107             break;
108         }
109         if (AddByteToJson(returnToSelf, FIELD_SESSION_KEY, (const uint8_t *)sessionKey, keyLen) != HC_SUCCESS) {
110             LOGE("Failed to add sessionKey for onFinish!");
111             res = HC_ERR_JSON_FAIL;
112             break;
113         }
114     } while (0);
115     (void)memset_s(sessionKey, keyLen, 0, keyLen);
116     HcFree(sessionKey);
117     sessionKey = NULL;
118     return res;
119 }
120 
GetUserIdForAccount(const CJson * sendToSelf,CJson * returnToSelf)121 static int32_t GetUserIdForAccount(const CJson *sendToSelf, CJson *returnToSelf)
122 {
123     const char *peerUserId = GetStringFromJson(sendToSelf, FIELD_USER_ID);
124     if (peerUserId == NULL) {
125         LOGE("Failed to get peer uid!");
126         return HC_ERR_JSON_GET;
127     }
128     if (AddStringToJson(returnToSelf, FIELD_USER_ID, peerUserId) != HC_SUCCESS) {
129         LOGE("Failed to add peer uid!");
130         return HC_ERR_JSON_FAIL;
131     }
132     return HC_SUCCESS;
133 }
134 
IsPeerUidLenValid(uint32_t peerUserIdLen)135 static bool IsPeerUidLenValid(uint32_t peerUserIdLen)
136 {
137     if ((peerUserIdLen < UID_HEX_STRING_LEN_MIN) || (peerUserIdLen > UID_HEX_STRING_LEN_MAX)) {
138         LOGE("The input userId len is invalid, input userId in hex string len = %d", peerUserIdLen);
139         return false;
140     }
141     return true;
142 }
143 
IsUserIdEqual(const char * userIdInDb,const char * peerUserIdInDb)144 static bool IsUserIdEqual(const char *userIdInDb, const char *peerUserIdInDb)
145 {
146     char *peerUidToUpper = NULL;
147     if (ToUpperCase(peerUserIdInDb, &peerUidToUpper) != HC_SUCCESS) {
148         LOGE("Failed to convert the input userId to upper case!");
149         return false;
150     }
151     uint32_t userIdInDbLen = HcStrlen(userIdInDb);
152     uint32_t peerUserIdLen = HcStrlen(peerUserIdInDb);
153     if (!IsPeerUidLenValid(peerUserIdLen)) {
154         HcFree(peerUidToUpper);
155         peerUidToUpper = NULL;
156         return false;
157     }
158     uint32_t cmpLen = (userIdInDbLen > peerUserIdLen) ? peerUserIdLen : userIdInDbLen;
159     if (memcmp(userIdInDb, peerUidToUpper, cmpLen) == EOK) {
160         HcFree(peerUidToUpper);
161         peerUidToUpper = NULL;
162         return true;
163     }
164     HcFree(peerUidToUpper);
165     peerUidToUpper = NULL;
166     return false;
167 }
168 
IsPeerInAccountRelatedGroup(const TrustedGroupEntry * groupEntry,const char * peerUserId,GroupType type)169 static bool IsPeerInAccountRelatedGroup(const TrustedGroupEntry *groupEntry, const char *peerUserId, GroupType type)
170 {
171     const char *userIdInDb =
172         ((type == IDENTICAL_ACCOUNT_GROUP) ? StringGet(&(groupEntry->userId)) : StringGet(&(groupEntry->sharedUserId)));
173     if (userIdInDb == NULL) {
174         LOGD("Failed to get peer userId from db!");
175         return false;
176     }
177     if (IsUserIdEqual(userIdInDb, peerUserId)) {
178         LOGI("[Account auth]: The input peer-userId is in one account group, add account-group auth!");
179         return true;
180     }
181     return false;
182 }
183 
IsPeerInIdenticalGroup(int32_t osAccountId,const char * peerUserId)184 static bool IsPeerInIdenticalGroup(int32_t osAccountId, const char *peerUserId)
185 {
186     bool isGroupExist = false;
187     GroupEntryVec accountVec = CreateGroupEntryVec();
188     QueryGroupParams queryParams = InitQueryGroupParams();
189     queryParams.groupType = IDENTICAL_ACCOUNT_GROUP;
190     do {
191         if (QueryGroups(osAccountId, &queryParams, &accountVec) != HC_SUCCESS) {
192             LOGD("No identical-account group in db, no identical-account auth!");
193             break;
194         }
195         uint32_t index = 0;
196         TrustedGroupEntry **ptr = NULL;
197         while (index < accountVec.size(&accountVec)) {
198             ptr = accountVec.getp(&accountVec, index);
199             if ((ptr == NULL) || (*ptr == NULL)) {
200                 index++;
201                 continue;
202             }
203             if (IsPeerInAccountRelatedGroup(*ptr, peerUserId, IDENTICAL_ACCOUNT_GROUP)) {
204                 isGroupExist = true;
205                 break;
206             }
207             index++;
208         }
209     } while (0);
210     ClearGroupEntryVec(&accountVec);
211     return isGroupExist;
212 }
213 
GaGetAccountGroup(int32_t osAccountId,GroupType type,const char * peerUserId,QueryGroupParams * queryParams,GroupEntryVec * vec)214 static void GaGetAccountGroup(int32_t osAccountId, GroupType type, const char *peerUserId,
215     QueryGroupParams *queryParams, GroupEntryVec *vec)
216 {
217     LOGI("Try to get account group info, groupType: %d.", type);
218     queryParams->groupType = type;
219     if (QueryGroups(osAccountId, queryParams, vec) != HC_SUCCESS) {
220         LOGD("Database don't have local device's across-account group info!");
221         return;
222     }
223 
224     uint32_t index = 0;
225     TrustedGroupEntry **ptr = NULL;
226     while (index < vec->size(vec)) {
227         ptr = vec->getp(vec, index);
228         if ((ptr == NULL) || (*ptr == NULL)) {
229             index++;
230             continue;
231         }
232         if ((peerUserId == NULL) || IsPeerInAccountRelatedGroup(*ptr, peerUserId, type)) {
233             index++;
234             continue;
235         }
236         TrustedGroupEntry *tempEntry = NULL;
237         const char *groupId = StringGet(&tempEntry->id);
238         if (groupId != NULL) {
239             PRINT_SENSITIVE_DATA("GroupId", groupId);
240         }
241         HC_VECTOR_POPELEMENT(vec, &tempEntry, index);
242         DestroyGroupEntry((TrustedGroupEntry *)tempEntry);
243     }
244     LOGI("The candidate account group size is: %u", vec->size(vec));
245 }
246 
GetAccountCandidateGroup(int32_t osAccountId,const CJson * param,QueryGroupParams * queryParams,GroupEntryVec * vec)247 static void GetAccountCandidateGroup(int32_t osAccountId, const CJson *param,
248     QueryGroupParams *queryParams, GroupEntryVec *vec)
249 {
250     /* Compare userId with local uid in DB. */
251     bool identicalFlag = false;
252     bool acrossAccountFlag = false;
253     const char *peerUserId = GetStringFromJson(param, FIELD_USER_ID);
254     if (peerUserId != NULL) {
255         acrossAccountFlag = true;
256         identicalFlag = IsPeerInIdenticalGroup(osAccountId, peerUserId);
257     } else {
258         LOGD("userId is null in authParam.");
259         identicalFlag = true;
260     }
261 
262     if (identicalFlag) {
263         GaGetAccountGroup(osAccountId, IDENTICAL_ACCOUNT_GROUP, peerUserId, queryParams, vec);
264     } else if (acrossAccountFlag) {
265         GaGetAccountGroup(osAccountId, ACROSS_ACCOUNT_AUTHORIZE_GROUP, peerUserId, queryParams, vec);
266     }
267 }
268 
FillAccountCredentialInfo(int32_t osAccountId,const char * peerUdid,const char * groupId,const TrustedDeviceEntry * localAuthInfo,CJson * paramsData)269 static int32_t FillAccountCredentialInfo(int32_t osAccountId, const char *peerUdid, const char *groupId,
270     const TrustedDeviceEntry *localAuthInfo, CJson *paramsData)
271 {
272     TrustedDeviceEntry *peerDevInfo = CreateDeviceEntry();
273     if (peerDevInfo == NULL) {
274         LOGE("Failed to alloc memory for peerDevInfo!");
275         return HC_ERR_ALLOC_MEMORY;
276     }
277     int32_t localDevType = DEVICE_TYPE_CONTROLLER;
278     int32_t authCredential = localAuthInfo->credential;
279     int32_t res = GaGetTrustedDeviceEntryById(osAccountId, peerUdid, true, groupId, peerDevInfo);
280     if ((res != HC_SUCCESS) || (peerDevInfo->source == SELF_CREATED)) {
281         LOGI("Peer device's query result = %d, pass local device info to account authenticator.", res);
282         localDevType = DEVICE_TYPE_ACCESSORY; /* Controller has peer device info, which is added by caller. */
283     }
284     if ((res == HC_SUCCESS) && (peerDevInfo->source == IMPORTED_FROM_CLOUD)) {
285         LOGI("Peer trusted device is imported by cloud, invoke sym account auth.");
286         authCredential = peerDevInfo->credential;
287     }
288     DestroyDeviceEntry(peerDevInfo);
289     if (AddIntToJson(paramsData, FIELD_LOCAL_DEVICE_TYPE, localDevType) != HC_SUCCESS) {
290         LOGE("Failed to add self device type to json!");
291         return HC_ERR_JSON_ADD;
292     }
293     if (AddIntToJson(paramsData, FIELD_CREDENTIAL_TYPE, authCredential) != HC_SUCCESS) {
294         LOGE("Failed to add self credential type to json!");
295         return HC_ERR_JSON_ADD;
296     }
297     return HC_SUCCESS;
298 }
299 
FillAccountAuthInfo(int32_t osAccountId,const TrustedGroupEntry * entry,const TrustedDeviceEntry * localAuthInfo,CJson * paramsData)300 static int32_t FillAccountAuthInfo(int32_t osAccountId, const TrustedGroupEntry *entry,
301     const TrustedDeviceEntry *localAuthInfo, CJson *paramsData)
302 {
303     const char *peerUdid = GetStringFromJson(paramsData, FIELD_PEER_CONN_DEVICE_ID);
304     if (peerUdid == NULL) {
305         LOGE("Failed to get peer udid in the input data for account auth!");
306         return HC_ERR_INVALID_PARAMS;
307     }
308     const char *selfUserId = StringGet(&entry->userId);
309     const char *groupId = StringGet(&entry->id);
310     const char *selfDeviceId = StringGet(&(localAuthInfo->udid));
311     const char *selfDevId = StringGet(&(localAuthInfo->authId));
312     if ((selfUserId == NULL) || (groupId == NULL) || (selfDeviceId == NULL) || (selfDevId == NULL)) {
313         LOGE("Failed to get self account info for client in account-related auth!");
314         return HC_ERR_JSON_GET;
315     }
316     if (AddStringToJson(paramsData, FIELD_SELF_USER_ID, selfUserId) != HC_SUCCESS) {
317         LOGE("Failed to add self userId for client in account-related auth!");
318         return HC_ERR_JSON_FAIL;
319     }
320     if (AddStringToJson(paramsData, FIELD_SELF_DEVICE_ID, selfDeviceId) != HC_SUCCESS) {
321         LOGE("Failed to add self deviceId for client in account-related auth!");
322         return HC_ERR_JSON_FAIL;
323     }
324     if (AddStringToJson(paramsData, FIELD_SELF_DEV_ID, selfDevId) != HC_SUCCESS) {
325         LOGE("Failed to add self devId for client in account-related auth!");
326         return HC_ERR_JSON_FAIL;
327     }
328     return FillAccountCredentialInfo(osAccountId, peerUdid, groupId, localAuthInfo, paramsData);
329 }
330 
IsDeviceImportedByCloud(int32_t osAccountId,const char * peerUdid,const char * groupId)331 static bool IsDeviceImportedByCloud(int32_t osAccountId,  const char *peerUdid, const char *groupId)
332 {
333     TrustedDeviceEntry *peerDeviceInfo = CreateDeviceEntry();
334     if (peerDeviceInfo == NULL) {
335         LOGE("Failed to alloc memory for peerDeviceInfo!");
336         return true;
337     }
338     if (GaGetTrustedDeviceEntryById(osAccountId, peerUdid, true, groupId, peerDeviceInfo) != HC_SUCCESS) {
339         LOGI("Peer trusted device is not in database.");
340         DestroyDeviceEntry(peerDeviceInfo);
341         return false;
342     }
343     uint8_t source = peerDeviceInfo->source;
344     DestroyDeviceEntry(peerDeviceInfo);
345     if (source == IMPORTED_FROM_CLOUD) {
346         LOGI("Peer trusted device is imported by cloud.");
347         return true;
348     }
349     return false;
350 }
351 
CombineAccountServerConfirms(const CJson * confirmationJson,CJson * dataFromClient)352 static int32_t CombineAccountServerConfirms(const CJson *confirmationJson, CJson *dataFromClient)
353 {
354     bool isClient = false;
355     if (AddBoolToJson(dataFromClient, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) {
356         LOGE("Failed to combine server param for isClient!");
357         return HC_ERR_JSON_FAIL;
358     }
359     const char *peerUdid = GetStringFromJson(confirmationJson, FIELD_PEER_CONN_DEVICE_ID);
360     if (peerUdid == NULL) {
361         LOGE("Failed to get peer udid from server confirm params!");
362         return HC_ERR_JSON_GET;
363     }
364     if (AddStringToJson(dataFromClient, FIELD_PEER_CONN_DEVICE_ID, peerUdid) != HC_SUCCESS) {
365         LOGE("Failed to combine server param for peerUdid!");
366         return HC_ERR_JSON_FAIL;
367     }
368     return HC_SUCCESS;
369 }
370 
QueryAuthGroupForServer(int32_t osAccountId,GroupEntryVec * accountVec,CJson * data)371 static int32_t QueryAuthGroupForServer(int32_t osAccountId, GroupEntryVec *accountVec, CJson *data)
372 {
373     const char *peerUserId = GetStringFromJson(data, FIELD_USER_ID);
374     if (peerUserId == NULL) {
375         LOGE("Failed to get peerUserId.");
376         return HC_ERR_JSON_GET;
377     }
378     int32_t authForm = AUTH_FORM_INVALID_TYPE;
379     if (GetIntFromJson(data, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) {
380         LOGE("Failed to get auth form for server!");
381         return HC_ERR_JSON_GET;
382     }
383     int32_t groupType = AuthFormToGroupType(authForm);
384     if (groupType == GROUP_TYPE_INVALID) {
385         LOGE("Invalid authForm, authForm = %d.", authForm);
386         return HC_ERR_INVALID_PARAMS;
387     }
388     QueryGroupParams queryParams = InitQueryGroupParams();
389     queryParams.groupType = (uint32_t)groupType;
390     if (queryParams.groupType == IDENTICAL_ACCOUNT_GROUP) {
391         queryParams.userId = peerUserId;
392     } else {
393         queryParams.sharedUserId = peerUserId;
394     }
395     int32_t res = QueryGroups(osAccountId, &queryParams, accountVec);
396     if (res != HC_SUCCESS) {
397         LOGE("Failed to query local device's account group info for server!");
398         return res;
399     }
400     if (accountVec->size(accountVec) == 0) {
401         LOGE("Database don't have local device's account group info for server!");
402         return HC_ERR_NO_CANDIDATE_GROUP;
403     }
404     return HC_SUCCESS;
405 }
406 
GetValueFromJsonStr(char * jsonStr,const char * key)407 static char *GetValueFromJsonStr(char *jsonStr, const char *key)
408 {
409     if (HcStrlen(jsonStr) > MAX_SERVICE_PEER_DATA_LENGTH) {
410         LOGE("Invalid peer data length!");
411         return NULL;
412     }
413     uint32_t keyLen = HcStrlen(key);
414     char *keyStr = (char *)HcMalloc(keyLen + PLACE_HOLDER_LENGTH, 0);
415     if (keyStr == NULL) {
416         LOGE("Failed to alloc memory for keyStr!");
417         return NULL;
418     }
419     if (sprintf_s(keyStr, keyLen + PLACE_HOLDER_LENGTH, JSON_KEY_FORMAT, key) <= 0) {
420         LOGE("Failed to convert key to string!");
421         HcFree(keyStr);
422         return NULL;
423     }
424     char *nextPtr = NULL;
425     char *value = NULL;
426     char *subVal = strtok_s(jsonStr, COMMA_SEPARATOR, &nextPtr);
427     while (subVal != NULL) {
428         if (strstr(subVal, keyStr) != NULL) {
429             value = strstr(subVal, COLON_SEPARATOR);
430             if (value != NULL) {
431                 value++;
432             }
433             break;
434         }
435         subVal = strtok_s(NULL, COMMA_SEPARATOR, &nextPtr);
436     }
437     HcFree(keyStr);
438     return value;
439 }
440 
GetPeerUserIdFromReceivedData(const CJson * data,char ** peerUserId)441 static int32_t GetPeerUserIdFromReceivedData(const CJson *data, char **peerUserId)
442 {
443     const char *peerData = GetStringFromJson(data, FIELD_PLUGIN_EXT_DATA);
444     if (peerData == NULL) {
445         LOGE("Failed to get peerData from data!");
446         return HC_ERR_JSON_GET;
447     }
448     char *copyPeerData = NULL;
449     int32_t res = DeepCopyString(peerData, &copyPeerData);
450     if (res != HC_SUCCESS) {
451         LOGE("Failed to deep copy peerData!");
452         return res;
453     }
454     char *userId = GetValueFromJsonStr(copyPeerData, FIELD_USER_ID);
455     if (userId == NULL) {
456         LOGE("Failed to get userId from peer data!");
457         HcFree(copyPeerData);
458         return HC_ERR_JSON_GET;
459     }
460     uint8_t userIdHash[SHA256_LEN] = { 0 };
461     Uint8Buff hashBuff = { userIdHash, sizeof(userIdHash) };
462     Uint8Buff hashMsgBuff = { (uint8_t *)userId, HcStrlen(userId) };
463     res = GetLoaderInstance()->sha256(&hashMsgBuff, &hashBuff);
464     HcFree(copyPeerData);
465     if (res != HC_SUCCESS) {
466         LOGE("Failed to get hash for userId!");
467         return res;
468     }
469     uint32_t hexLen = hashBuff.length * BYTE_TO_HEX_OPER_LENGTH + 1;
470     *peerUserId = (char *)HcMalloc(hexLen, 0);
471     if (*peerUserId == NULL) {
472         LOGE("Failed to alloc memory for peer userId!");
473         return HC_ERR_ALLOC_MEMORY;
474     }
475     res = ByteToHexString(hashBuff.val, hashBuff.length, *peerUserId, hexLen);
476     if (res != HC_SUCCESS) {
477         LOGE("Failed to convert hash to hex string!");
478         HcFree(*peerUserId);
479         *peerUserId = NULL;
480         return res;
481     }
482     return HC_SUCCESS;
483 }
484 
QueryGroupForAccountPlugin(int32_t osAccountId,GroupEntryVec * accountVec,CJson * data)485 static int32_t QueryGroupForAccountPlugin(int32_t osAccountId, GroupEntryVec *accountVec, CJson *data)
486 {
487     char *peerUserId = NULL;
488     int32_t res = GetPeerUserIdFromReceivedData(data, &peerUserId);
489     if (res != HC_SUCCESS) {
490         return res;
491     }
492     do {
493         int32_t authForm = AUTH_FORM_INVALID_TYPE;
494         if (GetIntFromJson(data, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) {
495             LOGE("Failed to get auth form for server!");
496             res = HC_ERR_JSON_GET;
497             break;
498         }
499         int32_t groupType = AuthFormToGroupType(authForm);
500         if (groupType == GROUP_TYPE_INVALID) {
501             LOGE("Invalid authForm: %d.", authForm);
502             res = HC_ERR_INVALID_PARAMS;
503             break;
504         }
505         QueryGroupParams queryParams = InitQueryGroupParams();
506         queryParams.groupType = (uint32_t)groupType;
507         if (queryParams.groupType == IDENTICAL_ACCOUNT_GROUP) {
508             queryParams.userId = peerUserId;
509         } else {
510             queryParams.sharedUserId = peerUserId;
511         }
512         res = QueryGroups(osAccountId, &queryParams, accountVec);
513     } while (0);
514     HcFree(peerUserId);
515     return res;
516 }
517 
AddSelfUserId(const TrustedGroupEntry * groupEntry,CJson * dataFromClient)518 static int32_t AddSelfUserId(const TrustedGroupEntry *groupEntry, CJson *dataFromClient)
519 {
520     const char *selfUserId = StringGet(&groupEntry->userId);
521     if (selfUserId == NULL) {
522         LOGE("Failed to get local userId info from db!");
523         return HC_ERR_DB;
524     }
525     if (AddStringToJson(dataFromClient, FIELD_SELF_USER_ID, selfUserId) != HC_SUCCESS) {
526         LOGE("Failed to add self userId for server in account-related auth!");
527         return HC_ERR_JSON_FAIL;
528     }
529     return HC_SUCCESS;
530 }
531 
AddGroupIdForServer(const TrustedGroupEntry * groupEntry,CJson * dataFromClient)532 static int32_t AddGroupIdForServer(const TrustedGroupEntry *groupEntry, CJson *dataFromClient)
533 {
534     const char *groupId = StringGet(&groupEntry->id);
535     if (groupId == NULL) {
536         LOGE("Failed to get groupId info from db!");
537         return HC_ERR_DB;
538     }
539     if (AddStringToJson(dataFromClient, FIELD_GROUP_ID, groupId) != HC_SUCCESS) {
540         LOGE("Failed to add groupId for server in account-related auth!");
541         return HC_ERR_JSON_FAIL;
542     }
543     return HC_SUCCESS;
544 }
545 
AddSelfDevInfoForServer(int32_t osAccountId,const TrustedGroupEntry * groupEntry,CJson * dataFromClient)546 static int32_t AddSelfDevInfoForServer(int32_t osAccountId, const TrustedGroupEntry *groupEntry, CJson *dataFromClient)
547 {
548     TrustedDeviceEntry *localDevInfo = CreateDeviceEntry();
549     if (localDevInfo == NULL) {
550         LOGE("Failed to allocate memory for localDevInfo for server!");
551         return HC_ERR_ALLOC_MEMORY;
552     }
553     int32_t res;
554     do {
555         const char *groupId = StringGet(&groupEntry->id);
556         if (groupId == NULL) {
557             LOGE("Failed to get groupId for server!");
558             res = HC_ERR_NULL_PTR;
559             break;
560         }
561         res = GaGetLocalDeviceInfo(osAccountId, groupId, localDevInfo);
562         const char *selfDevId = StringGet(&(localDevInfo->authId));
563         const char *selfUdid = StringGet(&(localDevInfo->udid));
564         if ((res != HC_SUCCESS) || (selfDevId == NULL) || (selfUdid == NULL)) {
565             LOGE("Failed to get self id info from db!");
566             res = HC_ERR_DB;
567             break;
568         }
569         if (AddStringToJson(dataFromClient, FIELD_SELF_DEV_ID, selfDevId) != HC_SUCCESS) {
570             LOGE("Failed to add self devId for server in account-related auth!");
571             res = HC_ERR_JSON_ADD;
572             break;
573         }
574         if (AddStringToJson(dataFromClient, FIELD_SELF_DEVICE_ID, selfUdid) != HC_SUCCESS) {
575             LOGE("Failed to add self udid for server in account-related auth!");
576             res = HC_ERR_JSON_ADD;
577             break;
578         }
579         const char *peerUdid = GetStringFromJson(dataFromClient, FIELD_PEER_CONN_DEVICE_ID);
580         if (peerUdid == NULL) {
581             LOGE("Failed to get peer udid for server auth!");
582             res = HC_ERR_JSON_FAIL;
583             break;
584         }
585         res = FillAccountCredentialInfo(osAccountId, peerUdid, groupId, localDevInfo, dataFromClient);
586     } while (0);
587     DestroyDeviceEntry(localDevInfo);
588     return res;
589 }
590 
AddServerParamsForAccountPlugin(CJson * dataFromClient)591 static int32_t AddServerParamsForAccountPlugin(CJson *dataFromClient)
592 {
593     int32_t osAccountId = INVALID_OS_ACCOUNT;
594     if (GetIntFromJson(dataFromClient, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
595         LOGE("Failed to get osAccountId!");
596         return HC_ERR_JSON_GET;
597     }
598     GroupEntryVec accountVec = CreateGroupEntryVec();
599     int32_t res = QueryGroupForAccountPlugin(osAccountId, &accountVec, dataFromClient);
600     if (res != HC_SUCCESS) {
601         LOGE("Failed to query group!");
602         ClearGroupEntryVec(&accountVec);
603         return res;
604     }
605     if (accountVec.size(&accountVec) == 0) {
606         // if group not found by peer userId, no need to add groupId to params, return success.
607         LOGE("Group size is 0!");
608         ClearGroupEntryVec(&accountVec);
609         return HC_SUCCESS;
610     }
611     TrustedGroupEntry *groupEntry = accountVec.get(&accountVec, 0);
612     if (groupEntry == NULL) {
613         LOGE("Group entry is null!");
614         ClearGroupEntryVec(&accountVec);
615         return HC_ERR_GROUP_NOT_EXIST;
616     }
617     res = AddGroupIdForServer(groupEntry, dataFromClient);
618     ClearGroupEntryVec(&accountVec);
619     return res;
620 }
621 
AddSelfAccountInfoForServer(CJson * dataFromClient)622 static int32_t AddSelfAccountInfoForServer(CJson *dataFromClient)
623 {
624     int32_t osAccountId = INVALID_OS_ACCOUNT;
625     if (GetIntFromJson(dataFromClient, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
626         LOGE("Failed to get osAccountId for server!");
627         return HC_ERR_JSON_GET;
628     }
629     GroupEntryVec accountVec = CreateGroupEntryVec();
630     int32_t res = QueryAuthGroupForServer(osAccountId, &accountVec, dataFromClient);
631     do {
632         if (res != HC_SUCCESS) {
633             LOGE("Failed to query account group info for server auth!");
634             break;
635         }
636         if (accountVec.size(&accountVec) == 0) {
637             LOGE("Database don't have local device's account group info for server!");
638             res = HC_ERR_NO_CANDIDATE_GROUP;
639             break;
640         }
641         TrustedGroupEntry *groupEntry = accountVec.get(&accountVec, 0);
642         if (groupEntry == NULL) {
643             LOGE("Local group info is null!");
644             res = HC_ERR_GROUP_NOT_EXIST;
645             break;
646         }
647         res = AddSelfUserId(groupEntry, dataFromClient);
648         if (res != HC_SUCCESS) {
649             break;
650         }
651         res = AddGroupIdForServer(groupEntry, dataFromClient);
652         if (res != HC_SUCCESS) {
653             break;
654         }
655         res = AddSelfDevInfoForServer(osAccountId, groupEntry, dataFromClient);
656     } while (0);
657     ClearGroupEntryVec(&accountVec);
658     return res;
659 }
660 
GetAuthParamsVecForServer(const CJson * dataFromClient,ParamsVecForAuth * authParamsVec)661 static int32_t GetAuthParamsVecForServer(const CJson *dataFromClient, ParamsVecForAuth *authParamsVec)
662 {
663     LOGI("Begin get account-related auth params for server.");
664     CJson *dupData = DuplicateJson(dataFromClient);
665     if (dupData == NULL) {
666         LOGE("Failed to create dupData for dataFromClient!");
667         return HC_ERR_JSON_FAIL;
668     }
669 
670     int32_t res;
671     if (HasAccountAuthPlugin() == HC_SUCCESS) {
672         res = AddServerParamsForAccountPlugin(dupData);
673     } else {
674         res = AddSelfAccountInfoForServer(dupData);
675     }
676     if (res != HC_SUCCESS) {
677         LOGE("Failed to add account server params!");
678         FreeJson(dupData);
679         return res;
680     }
681 
682     if (authParamsVec->pushBack(authParamsVec, (const void **)&dupData) == NULL) {
683         LOGE("Failed to push json data to vector in account-related auth!");
684         FreeJson(dupData);
685         return HC_ERR_ALLOC_MEMORY;
686     }
687     return HC_SUCCESS;
688 }
689 
AccountOnFinishToPeer(int64_t requestId,const CJson * out,const DeviceAuthCallback * callback)690 static int32_t AccountOnFinishToPeer(int64_t requestId, const CJson *out, const DeviceAuthCallback *callback)
691 {
692     int32_t res = HC_SUCCESS;
693     CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER);
694     if (sendToPeer == NULL) {
695         LOGI("No need to transmit data to peer for account-related auth.");
696         return res;
697     }
698     if (AddBoolToJson(sendToPeer, FIELD_IS_DEVICE_LEVEL, false) != HC_SUCCESS) {
699         LOGE("Failed to add device level flag!");
700         return HC_ERR_JSON_ADD;
701     }
702     char *sendToPeerStr = PackJsonToString(sendToPeer);
703     if (sendToPeerStr == NULL) {
704         LOGE("Failed to pack sendToPeerStr!");
705         return HC_ERR_ALLOC_MEMORY;
706     }
707     if ((callback != NULL) && (callback->onTransmit != NULL)) {
708         LOGD("Begin to transmit data to peer for auth in AccountOnFinishToPeer.");
709         UPDATE_PERFORM_DATA_BY_SELF_INDEX(requestId, HcGetCurTimeInMillis());
710         if (!callback->onTransmit(requestId, (uint8_t *)sendToPeerStr, HcStrlen(sendToPeerStr) + 1)) {
711             LOGE("Failed to transmit data to peer!");
712             res = HC_ERR_TRANSMIT_FAIL;
713         }
714         LOGD("End to transmit data to peer for auth in AccountOnFinishToPeer.");
715     }
716     FreeJsonString(sendToPeerStr);
717     return res;
718 }
719 
PrepareTrustedDeviceInfo(const char * peerUdid,const char * groupId,const CJson * out,TrustedDeviceEntry * devEntry)720 static int32_t PrepareTrustedDeviceInfo(const char *peerUdid, const char *groupId,
721     const CJson *out, TrustedDeviceEntry *devEntry)
722 {
723     devEntry->source = SELF_CREATED;
724     const CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF);
725     if (sendToSelf == NULL) {
726         LOGE("Failed to get sendToSelf data for account!");
727         return HC_ERR_JSON_GET;
728     }
729     int32_t credentialType = INVALID_CRED;
730     if (GetIntFromJson(sendToSelf, FIELD_CREDENTIAL_TYPE, &credentialType) != HC_SUCCESS) {
731         LOGE("Failed to get credentialType from json sendToSelf!");
732         return HC_ERR_JSON_GET;
733     }
734     devEntry->credential = credentialType;
735     const char *peerAuthId = GetStringFromJson(sendToSelf, FIELD_DEV_ID);
736     if (peerAuthId == NULL) {
737         LOGE("Failed to get peer authId for account!");
738         return HC_ERR_JSON_GET;
739     }
740     const char *peerUserId = GetStringFromJson(sendToSelf, FIELD_USER_ID);
741     if (peerUserId == NULL) {
742         LOGE("Failed to get peer userId!");
743         return HC_ERR_JSON_GET;
744     }
745     if (!StringSetPointer(&(devEntry->userId), peerUserId) ||
746         !StringSetPointer(&(devEntry->udid), peerUdid) ||
747         !StringSetPointer(&(devEntry->authId), peerAuthId) ||
748         !StringSetPointer(&(devEntry->groupId), groupId) ||
749         !StringSetPointer(&(devEntry->serviceType), groupId)) {
750         LOGE("Failed to add device info when adding a trusted device!");
751         return HC_ERR_MEMORY_COPY;
752     }
753     return HC_SUCCESS;
754 }
755 
AddTrustedDeviceForAccount(const CJson * authParam,const CJson * out)756 static int32_t AddTrustedDeviceForAccount(const CJson *authParam, const CJson *out)
757 {
758     int32_t osAccountId = ANY_OS_ACCOUNT;
759     if (GetIntFromJson(authParam, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
760         LOGE("Failed to get osAccountId for account!");
761         return HC_ERR_JSON_GET;
762     }
763     const char *peerUdid = GetStringFromJson(authParam, FIELD_PEER_CONN_DEVICE_ID);
764     if (peerUdid == NULL) {
765         LOGE("Failed to get peer udid when adding peer trusted device!");
766         return HC_ERR_JSON_GET;
767     }
768     const char *groupId = GetStringFromJson(authParam, FIELD_GROUP_ID);
769     if (groupId == NULL) {
770         LOGE("Failed to get groupId when adding peer trusted device!");
771         return HC_ERR_JSON_GET;
772     }
773     if (IsDeviceImportedByCloud(osAccountId, peerUdid, groupId)) {
774         LOGD("Peer trusted device is imported by cloud, we don't update peer device's trusted relationship.");
775         return HC_SUCCESS;
776     }
777     TrustedDeviceEntry *devEntry = CreateDeviceEntry();
778     if (devEntry == NULL) {
779         LOGE("Failed to allocate device entry memory!");
780         return HC_ERR_ALLOC_MEMORY;
781     }
782     int32_t res;
783     do {
784         res = PrepareTrustedDeviceInfo(peerUdid, groupId, out, devEntry);
785         if (res != HC_SUCCESS) {
786             LOGE("Failed to prepare trust device params!");
787             break;
788         }
789         res = AddTrustedDevice(osAccountId, devEntry);
790         if (res != HC_SUCCESS) {
791             LOGE("Failed to add trusted devices for account to database!");
792             break;
793         }
794         res = SaveOsAccountDb(osAccountId);
795     } while (0);
796     DestroyDeviceEntry(devEntry);
797     return res;
798 }
799 
PrepareAccountDataToSelf(const CJson * sendToSelf,CJson * returnToSelf)800 static int32_t PrepareAccountDataToSelf(const CJson *sendToSelf, CJson *returnToSelf)
801 {
802     int32_t res = GetSessionKeyForAccount(sendToSelf, returnToSelf);
803     if (res != HC_SUCCESS) {
804         LOGE("Failed to get session key info for account auth!");
805         return res;
806     }
807     res = GetUserIdForAccount(sendToSelf, returnToSelf);
808     if (res != HC_SUCCESS) {
809         LOGE("Failed to get user id for account auth!");
810     }
811     return res;
812 }
813 
ReportV1RelatedAuthCallEvent(int64_t requestId,const CJson * authParam)814 static void ReportV1RelatedAuthCallEvent(int64_t requestId, const CJson *authParam)
815 {
816 #ifdef DEV_AUTH_HIVIEW_ENABLE
817     DevAuthCallEvent eventData;
818     eventData.appId = SOFTBUS_APP_ID;
819     eventData.funcName = AUTH_DEV_EVENT;
820     eventData.osAccountId = DEFAULT_OS_ACCOUNT;
821     (void)GetIntFromJson(authParam, FIELD_OS_ACCOUNT_ID, &eventData.osAccountId);
822     eventData.callResult = DEFAULT_CALL_RESULT;
823     eventData.processCode = PROCESS_AUTH_V1;
824     eventData.credType = DEFAULT_CRED_TYPE;
825     eventData.groupType = IDENTICAL_ACCOUNT_GROUP;
826     eventData.executionTime = GET_TOTAL_CONSUME_TIME_BY_REQ_ID(requestId);
827     eventData.extInfo = DEFAULT_EXT_INFO;
828     DEV_AUTH_REPORT_CALL_EVENT(eventData);
829     return;
830 #endif
831     (void)requestId;
832     (void)authParam;
833     return;
834 }
835 
AccountOnFinishToSelf(int64_t requestId,const CJson * authParam,const CJson * out,const DeviceAuthCallback * callback)836 static int32_t AccountOnFinishToSelf(int64_t requestId, const CJson *authParam, const CJson *out,
837     const DeviceAuthCallback *callback)
838 {
839     const CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF);
840     if (sendToSelf == NULL) {
841         LOGE("No data to send to self for onFinish.");
842         return HC_ERR_LOST_DATA;
843     }
844 
845     CJson *returnToSelf = CreateJson();
846     if (returnToSelf == NULL) {
847         LOGE("Failed to create json for account-related auth in onFinish!");
848         return HC_ERR_ALLOC_MEMORY;
849     }
850     int32_t res = PrepareAccountDataToSelf(sendToSelf, returnToSelf);
851     if (res != HC_SUCCESS) {
852         LOGE("Failed to add account-related returnToSelf data!");
853         ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY);
854         FreeJson(returnToSelf);
855         return res;
856     }
857     char *returnStr = PackJsonToString(returnToSelf);
858     ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY);
859     FreeJson(returnToSelf);
860     if (returnStr == NULL) {
861         LOGE("Failed to pack return data to string!");
862         return HC_ERR_ALLOC_MEMORY;
863     }
864     do {
865         int32_t authForm = AUTH_FORM_INVALID_TYPE;
866         if (GetIntFromJson(authParam, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) {
867             LOGE("Failed to get auth type!");
868             res = HC_ERR_JSON_GET;
869             break;
870         }
871         if ((callback != NULL) && (callback->onFinish != NULL)) {
872             LOGD("Group auth call onFinish for account related auth.");
873             UPDATE_PERFORM_DATA_BY_INPUT_INDEX(requestId, ON_FINISH_TIME, HcGetCurTimeInMillis());
874             callback->onFinish(requestId, authForm, returnStr);
875         }
876     } while (0);
877     ClearAndFreeJsonString(returnStr);
878     ReportV1RelatedAuthCallEvent(requestId, authParam);
879     return res;
880 }
881 
OnAccountFinish(int64_t requestId,const CJson * authParam,const CJson * out,const DeviceAuthCallback * callback)882 static void OnAccountFinish(int64_t requestId, const CJson *authParam, const CJson *out,
883     const DeviceAuthCallback *callback)
884 {
885     LOGI("Begin call onFinish for account-related auth.");
886     if (AccountOnFinishToPeer(requestId, out, callback) != HC_SUCCESS) {
887         LOGE("Failed to send data to peer when account-related auth finished!");
888         return;
889     }
890     if (ReturnSessionKey(requestId, out, callback) != HC_SUCCESS) {
891         LOGE("Failed to return session key for account-related auth!");
892         return;
893     }
894     if (AddTrustedDeviceForAccount(authParam, out) != HC_SUCCESS) {
895         LOGD("Failed to add peer trusted devices to database for account-related auth!");
896     }
897     if (AccountOnFinishToSelf(requestId, authParam, out, callback) != HC_SUCCESS) {
898         LOGE("Failed to send data to self when account-related auth finished!");
899         return;
900     }
901     LOGI("Call onFinish for account-related auth successfully.");
902 }
903 
GetAccountRelatedGroupAuth(void)904 BaseGroupAuth *GetAccountRelatedGroupAuth(void)
905 {
906     return (BaseGroupAuth *)&g_accountRelatedGroupAuth;
907 }