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 "user_idm_funcs.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_log.h"
21 #include "adaptor_memory.h"
22 #include "adaptor_time.h"
23 #include "coauth.h"
24 #include "enroll_specification_check.h"
25 #include "executor_message.h"
26 #include "idm_database.h"
27 #include "udid_manager.h"
28 
29 #ifdef IAM_TEST_ENABLE
30 #define IAM_STATIC
31 #else
32 #define IAM_STATIC static
33 #endif
34 
SetScheduleParam(const PermissionCheckParam *param, ScheduleParam *scheduleParam)35 IAM_STATIC ResultCode SetScheduleParam(const PermissionCheckParam *param, ScheduleParam *scheduleParam)
36 {
37     scheduleParam->associateId.userId = param->userId;
38     scheduleParam->authType = param->authType;
39     scheduleParam->userType = param->userType;
40     scheduleParam->scheduleMode = SCHEDULE_MODE_ENROLL;
41     scheduleParam->collectorSensorHint = param->executorSensorHint;
42 
43     Uint8Array localUdid = { scheduleParam->localUdid, UDID_LEN };
44     bool getLocalUdidRet = GetLocalUdid(&localUdid);
45     Uint8Array collectorUdid = { scheduleParam->collectorUdid, UDID_LEN };
46     bool getCollectorUdidRet = GetLocalUdid(&collectorUdid);
47     if (!getLocalUdidRet || !getCollectorUdidRet) {
48         LOG_ERROR("get udid failed");
49         return RESULT_GENERAL_ERROR;
50     }
51     return RESULT_SUCCESS;
52 }
53 
GenerateIdmSchedule(const PermissionCheckParam *param)54 IAM_STATIC CoAuthSchedule *GenerateIdmSchedule(const PermissionCheckParam *param)
55 {
56     ScheduleParam scheduleParam = {};
57     if (SetScheduleParam(param, &scheduleParam) != RESULT_SUCCESS) {
58         LOG_ERROR("SetScheduleParam failed");
59         return NULL;
60     }
61 
62     if (scheduleParam.collectorSensorHint != INVALID_SENSOR_HINT) {
63         ResultCode ret = QueryCollecterMatcher(scheduleParam.authType, scheduleParam.collectorSensorHint,
64             &scheduleParam.executorMatcher);
65         if (ret != RESULT_SUCCESS) {
66             LOG_ERROR("QueryCollecterMatcher failed");
67             return NULL;
68         }
69     }
70 
71     LinkedList *credList = NULL;
72     if (QueryCredentialFunc(param->userId, param->authType, &credList) != RESULT_SUCCESS) {
73         LOG_ERROR("query credential failed");
74         return NULL;
75     }
76     uint64_t templateIdsBuffer[MAX_CREDENTIAL_OUTPUT];
77     uint32_t len = 0;
78     LinkedListNode *temp = credList->head;
79     while (temp != NULL) {
80         if (temp->data == NULL) {
81             LOG_ERROR("list node is invalid");
82             DestroyLinkedList(credList);
83             return NULL;
84         }
85         CredentialInfoHal *credentialHal = (CredentialInfoHal *)(temp->data);
86         if (len >= MAX_CREDENTIAL_OUTPUT) {
87             LOG_ERROR("len out of bound");
88             DestroyLinkedList(credList);
89             return NULL;
90         }
91         templateIdsBuffer[len] = credentialHal->templateId;
92         ++len;
93         temp = temp->next;
94     }
95 
96     Uint64Array templateIds = { templateIdsBuffer, len };
97     scheduleParam.templateIds = &templateIds;
98 
99     DestroyLinkedList(credList);
100     return GenerateSchedule(&scheduleParam);
101 }
102 
GenerateCoAuthSchedule(PermissionCheckParam *param, bool isUpdate, uint64_t *scheduleId)103 IAM_STATIC ResultCode GenerateCoAuthSchedule(PermissionCheckParam *param, bool isUpdate, uint64_t *scheduleId)
104 {
105     CoAuthSchedule *enrollSchedule = GenerateIdmSchedule(param);
106     if (enrollSchedule == NULL) {
107         LOG_ERROR("enrollSchedule malloc failed");
108         return RESULT_NO_MEMORY;
109     }
110     ResultCode ret = AddCoAuthSchedule(enrollSchedule);
111     if (ret != RESULT_SUCCESS) {
112         LOG_ERROR("add coauth schedule failed");
113         goto EXIT;
114     }
115     ret = AssociateCoauthSchedule(enrollSchedule->scheduleId, param->authType, isUpdate);
116     if (ret != RESULT_SUCCESS) {
117         LOG_ERROR("idm associate coauth schedule failed");
118         RemoveCoAuthSchedule(enrollSchedule->scheduleId);
119         goto EXIT;
120     }
121     *scheduleId = enrollSchedule->scheduleId;
122 
123 EXIT:
124     DestroyCoAuthSchedule(enrollSchedule);
125     return ret;
126 }
127 
CheckEnrollPermission(PermissionCheckParam param, uint64_t *scheduleId)128 ResultCode CheckEnrollPermission(PermissionCheckParam param, uint64_t *scheduleId)
129 {
130     if (scheduleId == NULL) {
131         LOG_ERROR("scheduleId is null");
132         return RESULT_BAD_PARAM;
133     }
134     if (!GetEnableStatus(param.userId, param.authType)) {
135         LOG_ERROR("authType is not support %{public}d", param.authType);
136         return RESULT_TYPE_NOT_SUPPORT;
137     }
138     ResultCode ret = IsValidUserType(param.userType);
139     if (ret != RESULT_SUCCESS) {
140         LOG_ERROR("userType is invalid");
141         return ret;
142     }
143     ret = CheckSessionValid(param.userId);
144     if (ret != RESULT_SUCCESS) {
145         LOG_ERROR("session is invalid");
146         return ret;
147     }
148     UserAuthTokenHal *authToken = (UserAuthTokenHal *)param.token;
149     ret = CheckSpecification(param.userId, param.authType);
150     if (ret != RESULT_SUCCESS) {
151         LOG_ERROR("check specification failed, authType is %{public}u, ret is %{public}d", param.authType, ret);
152         return ret;
153     }
154     if (param.authType != PIN_AUTH) {
155         ret = CheckIdmOperationToken(param.userId, authToken);
156         if (ret != RESULT_SUCCESS) {
157             LOG_ERROR("a valid token is required");
158             return RESULT_VERIFY_TOKEN_FAIL;
159         }
160     }
161 
162     return GenerateCoAuthSchedule(&param, false, scheduleId);
163 }
164 
CheckUpdatePermission(PermissionCheckParam param, uint64_t *scheduleId)165 ResultCode CheckUpdatePermission(PermissionCheckParam param, uint64_t *scheduleId)
166 {
167     if (scheduleId == NULL || param.authType != PIN_AUTH) {
168         LOG_ERROR("param is invalid");
169         return RESULT_BAD_PARAM;
170     }
171     if (!GetEnableStatus(param.userId, param.authType)) {
172         LOG_ERROR("authType is not support %{public}d", param.authType);
173         return RESULT_TYPE_NOT_SUPPORT;
174     }
175     ResultCode ret = CheckSessionValid(param.userId);
176     if (ret != RESULT_SUCCESS) {
177         LOG_ERROR("session is invalid");
178         return ret;
179     }
180     ret = CheckSpecification(param.userId, param.authType);
181     if (ret != RESULT_EXCEED_LIMIT) {
182         LOG_ERROR("no pin or exception, authType is %{public}u, ret is %{public}d", param.authType, ret);
183         return ret;
184     }
185     UserAuthTokenHal *authToken = (UserAuthTokenHal *)param.token;
186     ret = CheckIdmOperationToken(param.userId, authToken);
187     if (ret != RESULT_SUCCESS) {
188         LOG_ERROR("a valid token is required");
189         return RESULT_VERIFY_TOKEN_FAIL;
190     }
191 
192     return GenerateCoAuthSchedule(&param, true, scheduleId);
193 }
194 
GetInfoFromResult(CredentialInfoHal *credentialInfo, const ExecutorResultInfo *result, const CoAuthSchedule *schedule)195 IAM_STATIC void GetInfoFromResult(CredentialInfoHal *credentialInfo, const ExecutorResultInfo *result,
196     const CoAuthSchedule *schedule)
197 {
198     credentialInfo->authType = schedule->authType;
199     credentialInfo->templateId = result->templateId;
200     credentialInfo->capabilityLevel = result->capabilityLevel;
201     credentialInfo->executorSensorHint = GetScheduleVerifierSensorHint(schedule);
202     credentialInfo->executorMatcher = schedule->executors[0].executorMatcher;
203 }
204 
GetCredentialInfoFromSchedule(const ExecutorResultInfo *executorInfo, CredentialInfoHal *credentialInfo, const CoAuthSchedule *schedule)205 IAM_STATIC ResultCode GetCredentialInfoFromSchedule(const ExecutorResultInfo *executorInfo,
206     CredentialInfoHal *credentialInfo, const CoAuthSchedule *schedule)
207 {
208     uint64_t currentScheduleId;
209     uint32_t scheduleAuthType;
210     ResultCode ret = GetEnrollScheduleInfo(&currentScheduleId, &scheduleAuthType);
211     if (ret != RESULT_SUCCESS || executorInfo->scheduleId != currentScheduleId) {
212         LOG_ERROR("schedule is mismatch");
213         return RESULT_GENERAL_ERROR;
214     }
215     ret = CheckSessionTimeout();
216     if (ret != RESULT_SUCCESS) {
217         LOG_ERROR("idm session is time out");
218         return ret;
219     }
220     GetInfoFromResult(credentialInfo, executorInfo, schedule);
221     return RESULT_SUCCESS;
222 }
223 
GetEnrollTokenDataPlain(const CredentialInfoHal *credentialInfo, TokenDataPlain *dataPlain)224 IAM_STATIC ResultCode GetEnrollTokenDataPlain(const CredentialInfoHal *credentialInfo, TokenDataPlain *dataPlain)
225 {
226     ResultCode ret = GetChallenge(dataPlain->challenge, CHALLENGE_LEN);
227     if (ret != RESULT_SUCCESS) {
228         LOG_ERROR("get challenge fail");
229         return ret;
230     }
231 
232     dataPlain->time = GetSystemTime();
233     dataPlain->authTrustLevel = ATL3;
234     dataPlain->authType = credentialInfo->authType;
235     dataPlain->authMode = SCHEDULE_MODE_ENROLL;
236     return RESULT_SUCCESS;
237 }
238 
GetEnrollTokenDataToEncrypt(const CredentialInfoHal *credentialInfo, int32_t userId, TokenDataToEncrypt *data)239 IAM_STATIC ResultCode GetEnrollTokenDataToEncrypt(const CredentialInfoHal *credentialInfo, int32_t userId,
240     TokenDataToEncrypt *data)
241 {
242     data->userId = userId;
243     uint64_t secureUid;
244     ResultCode ret = GetSecureUid(userId, &secureUid);
245     if (ret != RESULT_SUCCESS) {
246         LOG_ERROR("get secure uid failed");
247         return ret;
248     }
249     data->secureUid = secureUid;
250     EnrolledInfoHal enrolledInfo = {};
251     ret = GetEnrolledInfoAuthType(userId, credentialInfo->authType, &enrolledInfo);
252     if (ret != RESULT_SUCCESS) {
253         LOG_ERROR("get enrolled info failed");
254         return ret;
255     }
256     data->enrolledId = enrolledInfo.enrolledId;
257     data->credentialId = credentialInfo->credentialId;
258     return RESULT_SUCCESS;
259 }
260 
GetAuthTokenForPinEnroll(const CredentialInfoHal *credentialInfo, int32_t userId)261 IAM_STATIC Buffer *GetAuthTokenForPinEnroll(const CredentialInfoHal *credentialInfo, int32_t userId)
262 {
263     UserAuthTokenPlain tokenPlain = {};
264     ResultCode ret = GetEnrollTokenDataPlain(credentialInfo, &(tokenPlain.tokenDataPlain));
265     if (ret != RESULT_SUCCESS) {
266         LOG_ERROR("GetEnrollTokenDataPlain fail");
267         return NULL;
268     }
269     ret = GetEnrollTokenDataToEncrypt(credentialInfo, userId, &(tokenPlain.tokenDataToEncrypt));
270     if (ret != RESULT_SUCCESS) {
271         LOG_ERROR("GetEnrollTokenDataToEncrypt fail");
272         return NULL;
273     }
274 
275     UserAuthTokenHal authTokenHal = {};
276     ret = UserAuthTokenSign(&tokenPlain, &authTokenHal);
277     if (ret != RESULT_SUCCESS) {
278         LOG_ERROR("generate pin enroll authToken fail");
279         return NULL;
280     }
281     Buffer *authToken = CreateBufferByData((uint8_t *)(&authTokenHal), sizeof(UserAuthTokenHal));
282     if (!IsBufferValid(authToken)) {
283         LOG_ERROR("create authToken buffer fail");
284         return NULL;
285     }
286 
287     return authToken;
288 }
289 
ProcessAddPinCredential(int32_t userId, const CredentialInfoHal *credentialInfo, const ExecutorResultInfo *executorResultInfo, Buffer **rootSecret, Buffer **authToken)290 IAM_STATIC ResultCode ProcessAddPinCredential(int32_t userId, const CredentialInfoHal *credentialInfo,
291     const ExecutorResultInfo *executorResultInfo, Buffer **rootSecret, Buffer **authToken)
292 {
293     ResultCode ret = SetPinSubType(userId, executorResultInfo->authSubType);
294     if (ret != RESULT_SUCCESS) {
295         LOG_ERROR("set pin sub type failed");
296         return ret;
297     }
298     *rootSecret = CopyBuffer(executorResultInfo->rootSecret);
299     if ((*rootSecret) == NULL) {
300         LOG_ERROR("copy rootSecret fail");
301         return RESULT_NO_MEMORY;
302     }
303     *authToken = GetAuthTokenForPinEnroll(credentialInfo, userId);
304     if (!IsBufferValid(*authToken)) {
305         LOG_ERROR("authToken is invalid");
306         DestoryBuffer(*rootSecret);
307         *rootSecret = NULL;
308         return RESULT_NO_MEMORY;
309     }
310 
311     return RESULT_SUCCESS;
312 }
313 
AddCredentialFunc( int32_t userId, const Buffer *scheduleResult, uint64_t *credentialId, Buffer **rootSecret, Buffer **authToken)314 ResultCode AddCredentialFunc(
315     int32_t userId, const Buffer *scheduleResult, uint64_t *credentialId, Buffer **rootSecret, Buffer **authToken)
316 {
317     if (!IsBufferValid(scheduleResult) || credentialId == NULL || rootSecret == NULL || authToken == NULL) {
318         LOG_ERROR("param is null");
319         return RESULT_BAD_PARAM;
320     }
321     int32_t sessionUserId;
322     ResultCode ret = GetUserId(&sessionUserId);
323     if (ret != RESULT_SUCCESS || sessionUserId != userId) {
324         LOG_ERROR("userId mismatch");
325         return RESULT_UNKNOWN;
326     }
327     ExecutorResultInfo *executorResultInfo = CreateExecutorResultInfo(scheduleResult);
328     if (executorResultInfo == NULL) {
329         LOG_ERROR("executorResultInfo is null");
330         return RESULT_UNKNOWN;
331     }
332     const CoAuthSchedule *schedule = GetCoAuthSchedule(executorResultInfo->scheduleId);
333     if (schedule == NULL) {
334         LOG_ERROR("schedule is null");
335         ret = RESULT_GENERAL_ERROR;
336         goto EXIT;
337     }
338     CredentialInfoHal credentialInfo;
339     ret = GetCredentialInfoFromSchedule(executorResultInfo, &credentialInfo, schedule);
340     if (ret != RESULT_SUCCESS) {
341         LOG_ERROR("failed to get credential info result");
342         goto EXIT;
343     }
344     ret = AddCredentialInfo(userId, &credentialInfo, schedule->userType);
345     if (ret != RESULT_SUCCESS) {
346         LOG_ERROR("add credential failed");
347         goto EXIT;
348     }
349     *credentialId = credentialInfo.credentialId;
350     if (credentialInfo.authType != PIN_AUTH) {
351         goto EXIT;
352     }
353     ret = ProcessAddPinCredential(userId, &credentialInfo, executorResultInfo, rootSecret, authToken);
354     if (ret != RESULT_SUCCESS) {
355         LOG_ERROR("ProcessAddPinCredential fail");
356         goto EXIT;
357     }
358 
359 EXIT:
360     DestroyExecutorResultInfo(executorResultInfo);
361     return ret;
362 }
363 
DeleteCredentialFunc(CredentialDeleteParam param, CredentialInfoHal *credentialInfo)364 ResultCode DeleteCredentialFunc(CredentialDeleteParam param, CredentialInfoHal *credentialInfo)
365 {
366     if (credentialInfo == NULL) {
367         LOG_ERROR("param is null");
368         return RESULT_BAD_PARAM;
369     }
370     UserAuthTokenHal token;
371     if (memcpy_s(&token, sizeof(UserAuthTokenHal), param.token, AUTH_TOKEN_LEN) != EOK) {
372         LOG_ERROR("token copy failed");
373         return RESULT_BAD_COPY;
374     }
375     ResultCode ret = CheckIdmOperationToken(param.userId, &token);
376     if (ret != RESULT_SUCCESS) {
377         LOG_ERROR("token is invalid");
378         return RESULT_VERIFY_TOKEN_FAIL;
379     }
380 
381     ret = DeleteCredentialInfo(param.userId, param.credentialId, credentialInfo);
382     if (ret != RESULT_SUCCESS) {
383         LOG_ERROR("delete database info failed");
384         return RESULT_BAD_SIGN;
385     }
386     return ret;
387 }
388 
QueryCredentialFunc(int32_t userId, uint32_t authType, LinkedList **creds)389 ResultCode QueryCredentialFunc(int32_t userId, uint32_t authType, LinkedList **creds)
390 {
391     if (creds == NULL) {
392         LOG_ERROR("creds is null");
393         return RESULT_BAD_PARAM;
394     }
395     CredentialCondition condition = {};
396     SetCredentialConditionUserId(&condition, userId);
397     if (authType != DEFAULT_AUTH_TYPE) {
398         SetCredentialConditionAuthType(&condition, authType);
399     }
400     *creds = QueryCredentialLimit(&condition);
401     if (*creds == NULL) {
402         LOG_ERROR("query credential failed");
403         return RESULT_UNKNOWN;
404     }
405     LOG_INFO("query credential success");
406     return RESULT_SUCCESS;
407 }
408 
GetUserInfoFunc(int32_t userId, uint64_t *secureUid, uint64_t *pinSubType, EnrolledInfoHal **enrolledInfoArray, uint32_t *enrolledNum)409 ResultCode GetUserInfoFunc(int32_t userId, uint64_t *secureUid, uint64_t *pinSubType,
410     EnrolledInfoHal **enrolledInfoArray, uint32_t *enrolledNum)
411 {
412     if (secureUid == NULL || pinSubType == NULL || enrolledInfoArray == NULL || enrolledNum == NULL) {
413         LOG_ERROR("param is null");
414         return RESULT_BAD_PARAM;
415     }
416     ResultCode ret = GetSecureUid(userId, secureUid);
417     if (ret != RESULT_SUCCESS) {
418         LOG_ERROR("get secureUid failed");
419         return ret;
420     }
421     ret = GetPinSubType(userId, pinSubType);
422     if (ret != RESULT_SUCCESS) {
423         LOG_ERROR("get pinSubType failed");
424         return ret;
425     }
426     return GetEnrolledInfo(userId, enrolledInfoArray, enrolledNum);
427 }
428 
GetDeletedCredential(int32_t userId, CredentialInfoHal *deletedCredential)429 IAM_STATIC ResultCode GetDeletedCredential(int32_t userId, CredentialInfoHal *deletedCredential)
430 {
431     CredentialCondition condition = {};
432     SetCredentialConditionAuthType(&condition, PIN_AUTH);
433     SetCredentialConditionUserId(&condition, userId);
434     LinkedList *credList = QueryCredentialLimit(&condition);
435     if (credList == NULL || credList->head == NULL || credList->head->data == NULL) {
436         LOG_ERROR("query credential failed");
437         DestroyLinkedList(credList);
438         return RESULT_UNKNOWN;
439     }
440     if (credList->getSize(credList) != MAX_NUMBER_OF_PIN_PER_USER) {
441         LOG_ERROR("pin num is invalid");
442         DestroyLinkedList(credList);
443         return RESULT_UNKNOWN;
444     }
445     *deletedCredential = *((CredentialInfoHal *)credList->head->data);
446     DestroyLinkedList(credList);
447     return RESULT_SUCCESS;
448 }
449 
CheckResultValid(uint64_t scheduleId, int32_t userId)450 IAM_STATIC ResultCode CheckResultValid(uint64_t scheduleId, int32_t userId)
451 {
452     uint64_t currentScheduleId;
453     uint32_t scheduleAuthType;
454     ResultCode ret = GetEnrollScheduleInfo(&currentScheduleId, &scheduleAuthType);
455     if (ret != RESULT_SUCCESS || scheduleId != currentScheduleId) {
456         LOG_ERROR("schedule is mismatch");
457         return RESULT_GENERAL_ERROR;
458     }
459     ret = CheckSessionTimeout();
460     if (ret != RESULT_SUCCESS) {
461         LOG_ERROR("idm session is time out");
462         return ret;
463     }
464     int32_t userIdGet;
465     ret = GetUserId(&userIdGet);
466     if (ret != RESULT_SUCCESS || userId != userIdGet) {
467         LOG_ERROR("check userId failed");
468         return RESULT_REACH_LIMIT;
469     }
470     if (scheduleAuthType != PIN_AUTH) {
471         LOG_ERROR("only pin is allowed to be updated");
472         return RESULT_UNKNOWN;
473     }
474     return RESULT_SUCCESS;
475 }
476 
GetUpdateCredentialOutput(int32_t userId, const Buffer *rootSecret, const CredentialInfoHal *credentialInfo, UpdateCredentialOutput *output)477 IAM_STATIC ResultCode GetUpdateCredentialOutput(int32_t userId, const Buffer *rootSecret,
478     const CredentialInfoHal *credentialInfo, UpdateCredentialOutput *output)
479 {
480     if (credentialInfo->authType != PIN_AUTH && credentialInfo->authType != DEFAULT_AUTH_TYPE) {
481         LOG_ERROR("bad authType");
482         return RESULT_GENERAL_ERROR;
483     }
484     CredentialInfoHal credInfo = (*credentialInfo);
485     credInfo.authType = PIN_AUTH;
486 
487     output->credentialId = credInfo.credentialId;
488     output->rootSecret = CopyBuffer(rootSecret);
489     if (!IsBufferValid(output->rootSecret)) {
490         LOG_ERROR("copy rootSecret fail");
491         goto ERROR;
492     }
493     output->oldRootSecret = GetCacheRootSecret(userId);
494     if (!IsBufferValid(output->oldRootSecret)) {
495         LOG_ERROR("GetCacheRootSecret fail");
496         goto ERROR;
497     }
498     output->authToken = GetAuthTokenForPinEnroll(&credInfo, userId);
499     if (!IsBufferValid(output->authToken)) {
500         LOG_ERROR("authToken is invalid");
501         goto ERROR;
502     }
503     return RESULT_SUCCESS;
504 
505 ERROR:
506     DestoryBuffer(output->rootSecret);
507     output->rootSecret = NULL;
508     DestoryBuffer(output->oldRootSecret);
509     output->oldRootSecret = NULL;
510     DestoryBuffer(output->authToken);
511     output->authToken = NULL;
512     return RESULT_NO_MEMORY;
513 }
514 
UpdateCredentialFunc(int32_t userId, const Buffer *scheduleResult, UpdateCredentialOutput *output)515 ResultCode UpdateCredentialFunc(int32_t userId, const Buffer *scheduleResult, UpdateCredentialOutput *output)
516 {
517     if (!IsBufferValid(scheduleResult) || output == NULL) {
518         LOG_ERROR("param is invalid");
519         return RESULT_BAD_PARAM;
520     }
521     ExecutorResultInfo *executorResultInfo = CreateExecutorResultInfo(scheduleResult);
522     if (executorResultInfo == NULL) {
523         LOG_ERROR("executorResultInfo is null");
524         return RESULT_UNKNOWN;
525     }
526     ResultCode ret = CheckResultValid(executorResultInfo->scheduleId, userId);
527     if (ret != RESULT_SUCCESS) {
528         LOG_ERROR("check result failed");
529         goto EXIT;
530     }
531     ret = GetDeletedCredential(userId, &(output->deletedCredential));
532     if (ret != RESULT_SUCCESS) {
533         LOG_ERROR("get old credential failed");
534         goto EXIT;
535     }
536     const CoAuthSchedule *schedule = GetCoAuthSchedule(executorResultInfo->scheduleId);
537     if (schedule == NULL) {
538         LOG_ERROR("schedule is null");
539         ret = RESULT_UNKNOWN;
540         goto EXIT;
541     }
542     CredentialInfoHal credentialInfo;
543     GetInfoFromResult(&credentialInfo, executorResultInfo, schedule);
544     ret = AddCredentialInfo(userId, &credentialInfo, schedule->userType);
545     if (ret != RESULT_SUCCESS) {
546         LOG_ERROR("failed to add credential");
547         goto EXIT;
548     }
549     ret = GetUpdateCredentialOutput(userId, executorResultInfo->rootSecret, &credentialInfo, output);
550     if (ret != RESULT_SUCCESS) {
551         LOG_ERROR("GetUpdateCredentialOutputRootSecret fail");
552         goto EXIT;
553     }
554 
555 EXIT:
556     DestroyExecutorResultInfo(executorResultInfo);
557     return ret;
558 }
559 
QueryAllExtUserInfoFunc(UserInfoResult *userInfos, uint32_t userInfolen, uint32_t *userInfoCount)560 ResultCode QueryAllExtUserInfoFunc(UserInfoResult *userInfos, uint32_t userInfolen, uint32_t *userInfoCount)
561 {
562     ResultCode ret = GetAllExtUserInfo(userInfos, userInfolen, userInfoCount);
563     if (ret != RESULT_SUCCESS) {
564         LOG_ERROR("GetAllExtUserInfo failed");
565         return RESULT_BAD_PARAM;
566     }
567 
568     return RESULT_SUCCESS;
569 }
570