• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "common_defs.h"
18 #include "device_auth_defines.h"
19 #include "group_auth_data_operation.h"
20 #include "hc_dev_info.h"
21 #include "hc_log.h"
22 #include "hc_types.h"
23 #include "json_utils.h"
24 #include "string_util.h"
25 
26 #define UID_HEX_STRING_LEN_MAX 64
27 #define UID_HEX_STRING_LEN_MIN 10
28 
29 static void OnAccountFinish(int64_t requestId, const CJson *authParam, const CJson *out,
30     const DeviceAuthCallback *callback);
31 static int32_t FillAccountAuthInfo(int32_t osAccountId, const TrustedGroupEntry *entry,
32     const TrustedDeviceEntry *localAuthInfo, CJson *paramsData);
33 static void GetAccountCandidateGroup(int32_t osAccountId, const CJson *param,
34     QueryGroupParams *queryParams, GroupEntryVec *vec);
35 static int32_t GetAuthParamsVecForServer(const CJson *dataFromClient, ParamsVecForAuth *authParamsVec);
36 static int32_t CombineAccountServerConfirms(const CJson *confirmationJson, CJson *dataFromClient);
37 
38 static AccountRelatedGroupAuth g_accountRelatedGroupAuth = {
39     .base.onFinish = OnAccountFinish,
40     .base.fillDeviceAuthInfo = FillAccountAuthInfo,
41     .base.getAuthParamsVecForServer = GetAuthParamsVecForServer,
42     .base.combineServerConfirmParams = CombineAccountServerConfirms,
43     .base.authType = ACCOUNT_RELATED_GROUP_AUTH_TYPE,
44     .getAccountCandidateGroup = GetAccountCandidateGroup,
45 };
46 
ReturnSessionKey(int64_t requestId,const CJson * authParam,const CJson * out,const DeviceAuthCallback * callback)47 static int32_t ReturnSessionKey(int64_t requestId, const CJson *authParam,
48     const CJson *out, const DeviceAuthCallback *callback)
49 {
50     int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH;
51     (void)GetIntFromJson(authParam, FIELD_KEY_LENGTH, &keyLen);
52     uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0);
53     if (sessionKey == NULL) {
54         LOGE("Failed to allocate memory for sessionKey!");
55         return HC_ERR_ALLOC_MEMORY;
56     }
57 
58     int32_t res = HC_SUCCESS;
59     do {
60         if (GetByteFromJson(out, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) {
61             LOGE("Failed to get sessionKey!");
62             res = HC_ERR_JSON_GET;
63             break;
64         }
65         if ((callback == NULL) || (callback->onSessionKeyReturned == NULL)) {
66             LOGE("The callback of onSessionKeyReturned is null!");
67             res = HC_ERR_INVALID_PARAMS;
68             break;
69         }
70         LOGI("Begin invoke onSessionKeyReturned.");
71         callback->onSessionKeyReturned(requestId, sessionKey, keyLen);
72         LOGI("End invoke onSessionKeyReturned, res = %d.", res);
73     } while (0);
74     (void)memset_s(sessionKey, keyLen, 0, keyLen);
75     HcFree(sessionKey);
76     sessionKey = NULL;
77     return res;
78 }
79 
GetSessionKeyForAccount(const CJson * sendToSelf,CJson * returnToSelf)80 static int32_t GetSessionKeyForAccount(const CJson *sendToSelf, CJson *returnToSelf)
81 {
82     int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH;
83     uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0);
84     if (sessionKey == NULL) {
85         LOGE("Failed to allocate memory for sessionKey!");
86         return HC_ERR_ALLOC_MEMORY;
87     }
88     int32_t res = HC_SUCCESS;
89     do {
90         if (GetByteFromJson(sendToSelf, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) {
91             LOGE("Failed to get sessionKey!");
92             res = HC_ERR_JSON_GET;
93             break;
94         }
95         if (AddByteToJson(returnToSelf, FIELD_SESSION_KEY, (const uint8_t *)sessionKey, keyLen) != HC_SUCCESS) {
96             LOGE("Failed to add sessionKey for onFinish!");
97             res = HC_ERR_JSON_FAIL;
98             break;
99         }
100     } while (0);
101     (void)memset_s(sessionKey, keyLen, 0, keyLen);
102     HcFree(sessionKey);
103     sessionKey = NULL;
104     return res;
105 }
106 
GetUserIdForAccount(const CJson * sendToSelf,CJson * returnToSelf)107 static int32_t GetUserIdForAccount(const CJson *sendToSelf, CJson *returnToSelf)
108 {
109     const char *peerUserId = GetStringFromJson(sendToSelf, FIELD_USER_ID);
110     if (peerUserId == NULL) {
111         LOGE("Failed to get peer uid!");
112         return HC_ERR_JSON_GET;
113     }
114     if (AddStringToJson(returnToSelf, FIELD_USER_ID, peerUserId) != HC_SUCCESS) {
115         LOGE("Failed to add peer uid!");
116         return HC_ERR_JSON_FAIL;
117     }
118     return HC_SUCCESS;
119 }
120 
IsPeerUidLenValid(uint32_t peerUserIdLen)121 static bool IsPeerUidLenValid(uint32_t peerUserIdLen)
122 {
123     if ((peerUserIdLen < UID_HEX_STRING_LEN_MIN) || (peerUserIdLen > UID_HEX_STRING_LEN_MAX)) {
124         LOGE("The input userId len is invalid, input userId in hex string len = %d", peerUserIdLen);
125         return false;
126     }
127     return true;
128 }
129 
IsUserIdEqual(const char * userIdInDb,const char * peerUserIdInDb)130 static bool IsUserIdEqual(const char *userIdInDb, const char *peerUserIdInDb)
131 {
132     char *peerUidToUpper = NULL;
133     if (ToUpperCase(peerUserIdInDb, &peerUidToUpper) != HC_SUCCESS) {
134         LOGE("Failed to convert the input userId to upper case!");
135         return false;
136     }
137     uint32_t userIdInDbLen = HcStrlen(userIdInDb);
138     uint32_t peerUserIdLen = HcStrlen(peerUserIdInDb);
139     if (!IsPeerUidLenValid(peerUserIdLen)) {
140         HcFree(peerUidToUpper);
141         peerUidToUpper = NULL;
142         return false;
143     }
144     uint32_t cmpLen = (userIdInDbLen > peerUserIdLen) ? peerUserIdLen : userIdInDbLen;
145     if (memcmp(userIdInDb, peerUidToUpper, cmpLen) == EOK) {
146         HcFree(peerUidToUpper);
147         peerUidToUpper = NULL;
148         return true;
149     }
150     HcFree(peerUidToUpper);
151     peerUidToUpper = NULL;
152     return false;
153 }
154 
IsPeerInAccountRelatedGroup(const TrustedGroupEntry * groupEntry,const char * peerUserId,GroupType type)155 static bool IsPeerInAccountRelatedGroup(const TrustedGroupEntry *groupEntry, const char *peerUserId, GroupType type)
156 {
157     const char *userIdInDb =
158         ((type == IDENTICAL_ACCOUNT_GROUP) ? StringGet(&(groupEntry->userId)) : StringGet(&(groupEntry->sharedUserId)));
159     if (userIdInDb == NULL) {
160         LOGD("Failed to get peer userId from db!");
161         return false;
162     }
163     if (IsUserIdEqual(userIdInDb, peerUserId)) {
164         LOGI("[Account auth]: The input peer-userId is in one account group, add account-group auth!");
165         return true;
166     }
167     return false;
168 }
169 
IsPeerInIdenticalGroup(int32_t osAccountId,const char * peerUserId)170 static bool IsPeerInIdenticalGroup(int32_t osAccountId, const char *peerUserId)
171 {
172     bool isGroupExist = false;
173     GroupEntryVec accountVec = CreateGroupEntryVec();
174     QueryGroupParams queryParams = InitQueryGroupParams();
175     queryParams.groupType = IDENTICAL_ACCOUNT_GROUP;
176     do {
177         if (QueryGroups(osAccountId, &queryParams, &accountVec) != HC_SUCCESS) {
178             LOGD("No identical-account group in db, no identical-account auth!");
179             break;
180         }
181         uint32_t index = 0;
182         TrustedGroupEntry **ptr = NULL;
183         while (index < accountVec.size(&accountVec)) {
184             ptr = accountVec.getp(&accountVec, index);
185             if ((ptr == NULL) || (*ptr == NULL)) {
186                 index++;
187                 continue;
188             }
189             if (IsPeerInAccountRelatedGroup(*ptr, peerUserId, IDENTICAL_ACCOUNT_GROUP)) {
190                 isGroupExist = true;
191                 break;
192             }
193             index++;
194         }
195     } while (0);
196     ClearGroupEntryVec(&accountVec);
197     return isGroupExist;
198 }
199 
GaGetAccountGroup(int32_t osAccountId,GroupType type,const char * peerUserId,QueryGroupParams * queryParams,GroupEntryVec * vec)200 static void GaGetAccountGroup(int32_t osAccountId, GroupType type, const char *peerUserId,
201     QueryGroupParams *queryParams, GroupEntryVec *vec)
202 {
203     LOGI("Try to get account group info, groupType: %d.", type);
204     queryParams->groupType = type;
205     if (QueryGroups(osAccountId, queryParams, vec) != HC_SUCCESS) {
206         LOGD("Database don't have local device's across-account group info!");
207         return;
208     }
209 
210     uint32_t index = 0;
211     TrustedGroupEntry **ptr = NULL;
212     while (index < vec->size(vec)) {
213         ptr = vec->getp(vec, index);
214         if ((ptr == NULL) || (*ptr == NULL)) {
215             index++;
216             continue;
217         }
218         if ((peerUserId == NULL) || IsPeerInAccountRelatedGroup(*ptr, peerUserId, type)) {
219             index++;
220             continue;
221         }
222         TrustedGroupEntry *tempEntry = NULL;
223         HC_VECTOR_POPELEMENT(vec, &tempEntry, index);
224         DestroyGroupEntry((TrustedGroupEntry *)tempEntry);
225     }
226     LOGI("The candidate account group size is: %u", vec->size(vec));
227 }
228 
GetAccountCandidateGroup(int32_t osAccountId,const CJson * param,QueryGroupParams * queryParams,GroupEntryVec * vec)229 static void GetAccountCandidateGroup(int32_t osAccountId, const CJson *param,
230     QueryGroupParams *queryParams, GroupEntryVec *vec)
231 {
232     /* Compare userId with local uid in DB. */
233     bool identicalFlag = false;
234     bool acrossAccountFlag = false;
235     const char *peerUserId = GetStringFromJson(param, FIELD_USER_ID);
236     if (peerUserId != NULL) {
237         acrossAccountFlag = true;
238         identicalFlag = IsPeerInIdenticalGroup(osAccountId, peerUserId);
239     } else {
240         LOGD("userId is null in authParam.");
241         identicalFlag = true;
242     }
243 
244     if (identicalFlag) {
245         GaGetAccountGroup(osAccountId, IDENTICAL_ACCOUNT_GROUP, peerUserId, queryParams, vec);
246     } else if (acrossAccountFlag) {
247         GaGetAccountGroup(osAccountId, ACROSS_ACCOUNT_AUTHORIZE_GROUP, peerUserId, queryParams, vec);
248     }
249 }
250 
FillAccountCredentialInfo(int32_t osAccountId,const char * peerUdid,const char * groupId,const TrustedDeviceEntry * localAuthInfo,CJson * paramsData)251 static int32_t FillAccountCredentialInfo(int32_t osAccountId, const char *peerUdid, const char *groupId,
252     const TrustedDeviceEntry *localAuthInfo, CJson *paramsData)
253 {
254     TrustedDeviceEntry *peerDevInfo = CreateDeviceEntry();
255     if (peerDevInfo == NULL) {
256         LOGE("Failed to alloc memory for peerDevInfo!");
257         return HC_ERR_ALLOC_MEMORY;
258     }
259     int32_t localDevType = DEVICE_TYPE_CONTROLLER;
260     int32_t authCredential = localAuthInfo->credential;
261     int32_t res = GaGetTrustedDeviceEntryById(osAccountId, peerUdid, true, groupId, peerDevInfo);
262     if ((res != HC_SUCCESS) || (peerDevInfo->source == SELF_CREATED)) {
263         LOGI("Peer device's query result = %d, pass local device info to account authenticator.", res);
264         localDevType = DEVICE_TYPE_ACCESSORY; /* Controller has peer device info, which is added by caller. */
265     }
266     if ((res == HC_SUCCESS) && (peerDevInfo->credential == SYMMETRIC_CRED) &&
267         (peerDevInfo->source == IMPORTED_FROM_CLOUD)) {
268         LOGI("Peer trusted device is imported by cloud, invoke sym account auth.");
269         authCredential = SYMMETRIC_CRED;
270     }
271     DestroyDeviceEntry(peerDevInfo);
272     if (AddIntToJson(paramsData, FIELD_LOCAL_DEVICE_TYPE, localDevType) != HC_SUCCESS) {
273         LOGE("Failed to add self device type to json!");
274         return HC_ERR_JSON_ADD;
275     }
276     if (AddIntToJson(paramsData, FIELD_CREDENTIAL_TYPE, authCredential) != HC_SUCCESS) {
277         LOGE("Failed to add self credential type to json!");
278         return HC_ERR_JSON_ADD;
279     }
280     return HC_SUCCESS;
281 }
282 
FillAccountAuthInfo(int32_t osAccountId,const TrustedGroupEntry * entry,const TrustedDeviceEntry * localAuthInfo,CJson * paramsData)283 static int32_t FillAccountAuthInfo(int32_t osAccountId, const TrustedGroupEntry *entry,
284     const TrustedDeviceEntry *localAuthInfo, CJson *paramsData)
285 {
286     const char *peerUdid = GetStringFromJson(paramsData, FIELD_PEER_CONN_DEVICE_ID);
287     if (peerUdid == NULL) {
288         LOGE("Failed to get peer udid in the input data for account auth!");
289         return HC_ERR_INVALID_PARAMS;
290     }
291     const char *selfUserId = StringGet(&entry->userId);
292     const char *groupId = StringGet(&entry->id);
293     const char *selfDeviceId = StringGet(&(localAuthInfo->udid));
294     const char *selfDevId = StringGet(&(localAuthInfo->authId));
295     if ((selfUserId == NULL) || (groupId == NULL) || (selfDeviceId == NULL) || (selfDevId == NULL)) {
296         LOGE("Failed to get self account info for client in account-related auth!");
297         return HC_ERR_JSON_GET;
298     }
299     if (AddStringToJson(paramsData, FIELD_SELF_USER_ID, selfUserId) != HC_SUCCESS) {
300         LOGE("Failed to add self userId for client in account-related auth!");
301         return HC_ERR_JSON_FAIL;
302     }
303     if (AddStringToJson(paramsData, FIELD_SELF_DEVICE_ID, selfDeviceId) != HC_SUCCESS) {
304         LOGE("Failed to add self deviceId for client in account-related auth!");
305         return HC_ERR_JSON_FAIL;
306     }
307     if (AddStringToJson(paramsData, FIELD_SELF_DEV_ID, selfDevId) != HC_SUCCESS) {
308         LOGE("Failed to add self devId for client in account-related auth!");
309         return HC_ERR_JSON_FAIL;
310     }
311     return FillAccountCredentialInfo(osAccountId, peerUdid, groupId, localAuthInfo, paramsData);
312 }
313 
IsDeviceImportedByCloud(int32_t osAccountId,const char * peerUdid,const char * groupId)314 static bool IsDeviceImportedByCloud(int32_t osAccountId,  const char *peerUdid, const char *groupId)
315 {
316     TrustedDeviceEntry *peerDeviceInfo = CreateDeviceEntry();
317     if (peerDeviceInfo == NULL) {
318         LOGE("Failed to alloc memory for peerDeviceInfo!");
319         return true;
320     }
321     if (GaGetTrustedDeviceEntryById(osAccountId, peerUdid, true, groupId, peerDeviceInfo) != HC_SUCCESS) {
322         LOGI("Peer trusted device is not in database.");
323         DestroyDeviceEntry(peerDeviceInfo);
324         return false;
325     }
326     uint8_t source = peerDeviceInfo->source;
327     DestroyDeviceEntry(peerDeviceInfo);
328     if (source == IMPORTED_FROM_CLOUD) {
329         LOGI("Peer trusted device is imported by cloud.");
330         return true;
331     }
332     return false;
333 }
334 
CombineAccountServerConfirms(const CJson * confirmationJson,CJson * dataFromClient)335 static int32_t CombineAccountServerConfirms(const CJson *confirmationJson, CJson *dataFromClient)
336 {
337     bool isClient = false;
338     if (AddBoolToJson(dataFromClient, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) {
339         LOGE("Failed to combine server param for isClient!");
340         return HC_ERR_JSON_FAIL;
341     }
342     const char *peerUdid = GetStringFromJson(confirmationJson, FIELD_PEER_CONN_DEVICE_ID);
343     if (peerUdid == NULL) {
344         LOGE("Failed to get peer udid from server confirm params!");
345         return HC_ERR_JSON_GET;
346     }
347     if (AddStringToJson(dataFromClient, FIELD_PEER_CONN_DEVICE_ID, peerUdid) != HC_SUCCESS) {
348         LOGE("Failed to combine server param for peerUdid!");
349         return HC_ERR_JSON_FAIL;
350     }
351     return HC_SUCCESS;
352 }
353 
QueryAuthGroupForServer(int32_t osAccountId,GroupEntryVec * accountVec,CJson * data)354 static int32_t QueryAuthGroupForServer(int32_t osAccountId, GroupEntryVec *accountVec, CJson *data)
355 {
356     const char *peerUserId = GetStringFromJson(data, FIELD_USER_ID);
357     if (peerUserId == NULL) {
358         LOGE("Failed to get peerUserId.");
359         return HC_ERR_JSON_GET;
360     }
361     int32_t authForm = AUTH_FORM_INVALID_TYPE;
362     if (GetIntFromJson(data, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) {
363         LOGE("Failed to get auth form for server!");
364         return HC_ERR_JSON_GET;
365     }
366     int32_t groupType = AuthFormToGroupType(authForm);
367     if (groupType == GROUP_TYPE_INVALID) {
368         LOGE("Invalid authForm, authForm = %d.", authForm);
369         return HC_ERR_INVALID_PARAMS;
370     }
371     QueryGroupParams queryParams = InitQueryGroupParams();
372     queryParams.groupType = groupType;
373     if (groupType == IDENTICAL_ACCOUNT_GROUP) {
374         queryParams.userId = peerUserId;
375     } else {
376         queryParams.sharedUserId = peerUserId;
377     }
378     int32_t res = QueryGroups(osAccountId, &queryParams, accountVec);
379     if (res != HC_SUCCESS) {
380         LOGE("Failed to query local device's account group info for server!");
381         return res;
382     }
383     if (accountVec->size(accountVec) == 0) {
384         LOGE("Database don't have local device's account group info for server!");
385         return HC_ERR_NO_CANDIDATE_GROUP;
386     }
387     return HC_SUCCESS;
388 }
389 
AddSelfUserId(const TrustedGroupEntry * groupEntry,CJson * dataFromClient)390 static int32_t AddSelfUserId(const TrustedGroupEntry *groupEntry, CJson *dataFromClient)
391 {
392     const char *selfUserId = StringGet(&groupEntry->userId);
393     if (selfUserId == NULL) {
394         LOGE("Failed to get local userId info from db!");
395         return HC_ERR_DB;
396     }
397     if (AddStringToJson(dataFromClient, FIELD_SELF_USER_ID, selfUserId) != HC_SUCCESS) {
398         LOGE("Failed to add self userId for server in account-related auth!");
399         return HC_ERR_JSON_FAIL;
400     }
401     return HC_SUCCESS;
402 }
403 
AddGroupIdForServer(const TrustedGroupEntry * groupEntry,CJson * dataFromClient)404 static int32_t AddGroupIdForServer(const TrustedGroupEntry *groupEntry, CJson *dataFromClient)
405 {
406     const char *groupId = StringGet(&groupEntry->id);
407     if (groupId == NULL) {
408         LOGE("Failed to get groupId info from db!");
409         return HC_ERR_DB;
410     }
411     if (AddStringToJson(dataFromClient, FIELD_GROUP_ID, groupId) != HC_SUCCESS) {
412         LOGE("Failed to add groupId for server in account-related auth!");
413         return HC_ERR_JSON_FAIL;
414     }
415     return HC_SUCCESS;
416 }
417 
AddSelfDevInfoForServer(int32_t osAccountId,const TrustedGroupEntry * groupEntry,CJson * dataFromClient)418 static int32_t AddSelfDevInfoForServer(int32_t osAccountId, const TrustedGroupEntry *groupEntry, CJson *dataFromClient)
419 {
420     TrustedDeviceEntry *localDevInfo = CreateDeviceEntry();
421     if (localDevInfo == NULL) {
422         LOGE("Failed to allocate memory for localDevInfo for server!");
423         return HC_ERR_ALLOC_MEMORY;
424     }
425     int32_t res;
426     do {
427         const char *groupId = StringGet(&groupEntry->id);
428         if (groupId == NULL) {
429             LOGE("Failed to get groupId for server!");
430             res = HC_ERR_NULL_PTR;
431             break;
432         }
433         res = GaGetLocalDeviceInfo(osAccountId, groupId, localDevInfo);
434         const char *selfDevId = StringGet(&(localDevInfo->authId));
435         const char *selfUdid = StringGet(&(localDevInfo->udid));
436         if ((res != HC_SUCCESS) || (selfDevId == NULL) || (selfUdid == NULL)) {
437             LOGE("Failed to get self id info from db!");
438             res = HC_ERR_DB;
439             break;
440         }
441         if (AddStringToJson(dataFromClient, FIELD_SELF_DEV_ID, selfDevId) != HC_SUCCESS) {
442             LOGE("Failed to add self devId for server in account-related auth!");
443             res = HC_ERR_JSON_ADD;
444             break;
445         }
446         if (AddStringToJson(dataFromClient, FIELD_SELF_DEVICE_ID, selfUdid) != HC_SUCCESS) {
447             LOGE("Failed to add self udid for server in account-related auth!");
448             res = HC_ERR_JSON_ADD;
449             break;
450         }
451         const char *peerUdid = GetStringFromJson(dataFromClient, FIELD_PEER_CONN_DEVICE_ID);
452         if (peerUdid == NULL) {
453             LOGE("Failed to get peer udid for server auth!");
454             res = HC_ERR_JSON_FAIL;
455             break;
456         }
457         res = FillAccountCredentialInfo(osAccountId, peerUdid, groupId, localDevInfo, dataFromClient);
458     } while (0);
459     DestroyDeviceEntry(localDevInfo);
460     return res;
461 }
462 
AddSelfAccountInfoForServer(CJson * dataFromClient)463 static int32_t AddSelfAccountInfoForServer(CJson *dataFromClient)
464 {
465     int32_t osAccountId = INVALID_OS_ACCOUNT;
466     if (GetIntFromJson(dataFromClient, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
467         LOGE("Failed to get osAccountId for server!");
468         return HC_ERR_JSON_GET;
469     }
470     GroupEntryVec accountVec = CreateGroupEntryVec();
471     int32_t res = QueryAuthGroupForServer(osAccountId, &accountVec, dataFromClient);
472     do {
473         if (res != HC_SUCCESS) {
474             LOGE("Failed to query account group info for server auth!");
475             break;
476         }
477         if (accountVec.size(&accountVec) == 0) {
478             LOGE("Database don't have local device's account group info for server!");
479             res = HC_ERR_NO_CANDIDATE_GROUP;
480             break;
481         }
482         TrustedGroupEntry *groupEntry = accountVec.get(&accountVec, 0);
483         if (groupEntry == NULL) {
484             LOGE("Local group info is null!");
485             res = HC_ERR_GROUP_NOT_EXIST;
486             break;
487         }
488         res = AddSelfUserId(groupEntry, dataFromClient);
489         if (res != HC_SUCCESS) {
490             break;
491         }
492         res = AddGroupIdForServer(groupEntry, dataFromClient);
493         if (res != HC_SUCCESS) {
494             break;
495         }
496         res = AddSelfDevInfoForServer(osAccountId, groupEntry, dataFromClient);
497     } while (0);
498     ClearGroupEntryVec(&accountVec);
499     return res;
500 }
501 
GetAuthParamsVecForServer(const CJson * dataFromClient,ParamsVecForAuth * authParamsVec)502 static int32_t GetAuthParamsVecForServer(const CJson *dataFromClient, ParamsVecForAuth *authParamsVec)
503 {
504     LOGI("Begin get account-related auth params for server.");
505     CJson *dupData = DuplicateJson(dataFromClient);
506     if (dupData == NULL) {
507         LOGE("Failed to create dupData for dataFromClient!");
508         return HC_ERR_JSON_FAIL;
509     }
510 
511     if (AddSelfAccountInfoForServer(dupData) != HC_SUCCESS) {
512         LOGE("Failed to add account info for server!");
513         FreeJson(dupData);
514         return HC_ERR_GROUP_NOT_EXIST;
515     }
516 
517     if (authParamsVec->pushBack(authParamsVec, (const void **)&dupData) == NULL) {
518         LOGE("Failed to push json data to vector in account-related auth!");
519         FreeJson(dupData);
520         return HC_ERR_ALLOC_MEMORY;
521     }
522     return HC_SUCCESS;
523 }
524 
AccountOnFinishToPeer(int64_t requestId,const CJson * out,const DeviceAuthCallback * callback)525 static int32_t AccountOnFinishToPeer(int64_t requestId, const CJson *out, const DeviceAuthCallback *callback)
526 {
527     int32_t res = HC_SUCCESS;
528     const CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER);
529     if (sendToPeer == NULL) {
530         LOGI("No need to transmit data to peer for account-related auth.");
531         return res;
532     }
533     char *sendToPeerStr = PackJsonToString(sendToPeer);
534     if (sendToPeerStr == NULL) {
535         LOGE("Failed to pack sendToPeerStr!");
536         return HC_ERR_ALLOC_MEMORY;
537     }
538     if ((callback != NULL) && (callback->onTransmit != NULL)) {
539         LOGD("Begin to transmit data to peer for auth in AccountOnFinishToPeer.");
540         if (!callback->onTransmit(requestId, (uint8_t *)sendToPeerStr, HcStrlen(sendToPeerStr) + 1)) {
541             LOGE("Failed to transmit data to peer!");
542             res = HC_ERR_TRANSMIT_FAIL;
543         }
544         LOGD("End to transmit data to peer for auth in AccountOnFinishToPeer.");
545     }
546     FreeJsonString(sendToPeerStr);
547     return res;
548 }
549 
PrepareTrustedDeviceInfo(const char * peerUdid,const char * groupId,const CJson * authParam,const CJson * out,TrustedDeviceEntry * devEntry)550 static int32_t PrepareTrustedDeviceInfo(const char *peerUdid, const char *groupId,
551     const CJson *authParam, const CJson *out, TrustedDeviceEntry *devEntry)
552 {
553     devEntry->source = SELF_CREATED;
554     const CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF);
555     if (sendToSelf == NULL) {
556         LOGE("Failed to get sendToSelf data for account!");
557         return HC_ERR_JSON_GET;
558     }
559     int32_t credentialType = INVALID_CRED;
560     if (GetIntFromJson(sendToSelf, FIELD_CREDENTIAL_TYPE, &credentialType) != HC_SUCCESS) {
561         LOGE("Failed to get credentialType from json sendToSelf!");
562         return HC_ERR_JSON_GET;
563     }
564     devEntry->credential = credentialType;
565     const char *peerAuthId = GetStringFromJson(sendToSelf, FIELD_DEV_ID);
566     if (peerAuthId == NULL) {
567         LOGE("Failed to get peer authId for account!");
568         return HC_ERR_JSON_GET;
569     }
570     const char *peerUserId = GetStringFromJson(sendToSelf, FIELD_USER_ID);
571     if (peerUserId == NULL) {
572         LOGE("Failed to get peer userId!");
573         return HC_ERR_JSON_GET;
574     }
575     if (!StringSetPointer(&(devEntry->userId), peerUserId) ||
576         !StringSetPointer(&(devEntry->udid), peerUdid) ||
577         !StringSetPointer(&(devEntry->authId), peerAuthId) ||
578         !StringSetPointer(&(devEntry->groupId), groupId) ||
579         !StringSetPointer(&(devEntry->serviceType), groupId)) {
580         LOGE("Failed to add device info when adding a trusted device!");
581         return HC_ERR_MEMORY_COPY;
582     }
583     return HC_SUCCESS;
584 }
585 
AddTrustedDeviceForAccount(const CJson * authParam,const CJson * out)586 static int32_t AddTrustedDeviceForAccount(const CJson *authParam, const CJson *out)
587 {
588     int32_t osAccountId = ANY_OS_ACCOUNT;
589     if (GetIntFromJson(authParam, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
590         LOGE("Failed to get osAccountId for account!");
591         return HC_ERR_JSON_GET;
592     }
593     const char *peerUdid = GetStringFromJson(authParam, FIELD_PEER_CONN_DEVICE_ID);
594     if (peerUdid == NULL) {
595         LOGE("Failed to get peer udid when adding peer trusted device!");
596         return HC_ERR_JSON_GET;
597     }
598     const char *groupId = GetStringFromJson(authParam, FIELD_GROUP_ID);
599     if (groupId == NULL) {
600         LOGE("Failed to get groupId when adding peer trusted device!");
601         return HC_ERR_JSON_GET;
602     }
603     if (IsDeviceImportedByCloud(osAccountId, peerUdid, groupId)) {
604         LOGD("Peer trusted device is imported by cloud, we don't update peer device's trusted relationship.");
605         return HC_SUCCESS;
606     }
607     TrustedDeviceEntry *devEntry = CreateDeviceEntry();
608     if (devEntry == NULL) {
609         LOGE("Failed to allocate device entry memory!");
610         return HC_ERR_ALLOC_MEMORY;
611     }
612     int32_t res;
613     do {
614         res = PrepareTrustedDeviceInfo(peerUdid, groupId, authParam, out, devEntry);
615         if (res != HC_SUCCESS) {
616             LOGE("Failed to prepare trust device params!");
617             break;
618         }
619         res = AddTrustedDevice(osAccountId, devEntry);
620         if (res != HC_SUCCESS) {
621             LOGE("Failed to add trusted devices for account to database!");
622             break;
623         }
624         res = SaveOsAccountDb(osAccountId);
625     } while (0);
626     DestroyDeviceEntry(devEntry);
627     return res;
628 }
629 
PrepareAccountDataToSelf(const CJson * sendToSelf,CJson * returnToSelf)630 static int32_t PrepareAccountDataToSelf(const CJson *sendToSelf, CJson *returnToSelf)
631 {
632     int32_t res = GetSessionKeyForAccount(sendToSelf, returnToSelf);
633     if (res != HC_SUCCESS) {
634         LOGE("Failed to get session key info for account auth!");
635         return res;
636     }
637     res = GetUserIdForAccount(sendToSelf, returnToSelf);
638     if (res != HC_SUCCESS) {
639         LOGE("Failed to get user id for account auth!");
640     }
641     return res;
642 }
643 
AccountOnFinishToSelf(int64_t requestId,const CJson * authParam,const CJson * out,const DeviceAuthCallback * callback)644 static int32_t AccountOnFinishToSelf(int64_t requestId, const CJson *authParam, const CJson *out,
645     const DeviceAuthCallback *callback)
646 {
647     const CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF);
648     if (sendToSelf == NULL) {
649         LOGE("No data to send to self for onFinish.");
650         return HC_ERR_LOST_DATA;
651     }
652 
653     CJson *returnToSelf = CreateJson();
654     if (returnToSelf == NULL) {
655         LOGE("Failed to create json for account-related auth in onFinish!");
656         return HC_ERR_ALLOC_MEMORY;
657     }
658     int32_t res = PrepareAccountDataToSelf(sendToSelf, returnToSelf);
659     if (res != HC_SUCCESS) {
660         LOGE("Failed to add account-related returnToSelf data!");
661         ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY);
662         FreeJson(returnToSelf);
663         return res;
664     }
665     char *returnStr = PackJsonToString(returnToSelf);
666     ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY);
667     FreeJson(returnToSelf);
668     if (returnStr == NULL) {
669         LOGE("Failed to pack return data to string!");
670         return HC_ERR_ALLOC_MEMORY;
671     }
672     do {
673         int32_t authForm = AUTH_FORM_INVALID_TYPE;
674         if (GetIntFromJson(authParam, FIELD_AUTH_FORM, &authForm) != HC_SUCCESS) {
675             LOGE("Failed to get auth type!");
676             res = HC_ERR_JSON_GET;
677             break;
678         }
679         if ((callback != NULL) && (callback->onFinish != NULL)) {
680             LOGD("Group auth call onFinish for account related auth.");
681             callback->onFinish(requestId, authForm, returnStr);
682         }
683     } while (0);
684     ClearAndFreeJsonString(returnStr);
685     return res;
686 }
687 
OnAccountFinish(int64_t requestId,const CJson * authParam,const CJson * out,const DeviceAuthCallback * callback)688 static void OnAccountFinish(int64_t requestId, const CJson *authParam, const CJson *out,
689     const DeviceAuthCallback *callback)
690 {
691     LOGI("Begin call onFinish for account-related auth.");
692     if (AccountOnFinishToPeer(requestId, out, callback) != HC_SUCCESS) {
693         LOGE("Failed to send data to peer when account-related auth finished!");
694         return;
695     }
696     if (ReturnSessionKey(requestId, authParam, out, callback) != HC_SUCCESS) {
697         LOGE("Failed to return session key for account-related auth!");
698         return;
699     }
700     if (AddTrustedDeviceForAccount(authParam, out) != HC_SUCCESS) {
701         LOGD("Failed to add peer trusted devices to database for account-related auth!");
702     }
703     if (AccountOnFinishToSelf(requestId, authParam, out, callback) != HC_SUCCESS) {
704         LOGE("Failed to send data to self when account-related auth finished!");
705         return;
706     }
707     LOGI("Call onFinish for account-related auth successfully.");
708 }
709 
GetAccountRelatedGroupAuth(void)710 BaseGroupAuth *GetAccountRelatedGroupAuth(void)
711 {
712     return (BaseGroupAuth *)&g_accountRelatedGroupAuth;
713 }