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 "context_manager.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_log.h"
21 #include "auth_level.h"
22 #include "coauth.h"
23 #include "idm_database.h"
24 #include "udid_manager.h"
25 
26 #ifdef IAM_TEST_ENABLE
27 #define IAM_STATIC
28 #else
29 #define IAM_STATIC static
30 #endif
31 
32 IAM_STATIC bool IsContextDuplicate(uint64_t contextId);
33 IAM_STATIC ResultCode CreateAndInsertSchedules(UserAuthContext *context, uint32_t authMode);
34 IAM_STATIC ResultCode CreateAuthSchedule(UserAuthContext *context, CoAuthSchedule **schedule);
35 IAM_STATIC ResultCode CreateIdentifySchedule(const UserAuthContext *context, CoAuthSchedule **schedule);
36 IAM_STATIC void DestroyContextNode(void *data);
37 IAM_STATIC ResultCode InsertScheduleToContext(CoAuthSchedule *schedule, UserAuthContext *context);
38 
39 // Stores information about the current user authentication schedule.
40 IAM_STATIC LinkedList *g_contextList = NULL;
41 
InitUserAuthContextList(void)42 ResultCode InitUserAuthContextList(void)
43 {
44     if (g_contextList != NULL) {
45         return RESULT_SUCCESS;
46     }
47     g_contextList = CreateLinkedList(DestroyContextNode);
48     if (g_contextList == NULL) {
49         return RESULT_GENERAL_ERROR;
50     }
51     return RESULT_SUCCESS;
52 }
53 
DestoryUserAuthContextList(void)54 void DestoryUserAuthContextList(void)
55 {
56     DestroyLinkedList(g_contextList);
57     g_contextList = NULL;
58 }
59 
InitAuthContext(AuthParamHal params)60 IAM_STATIC UserAuthContext *InitAuthContext(AuthParamHal params)
61 {
62     UserAuthContext *context = (UserAuthContext *)Malloc(sizeof(UserAuthContext));
63     if (context == NULL) {
64         LOG_ERROR("context malloc failed");
65         return NULL;
66     }
67     (void)memset_s(context, sizeof(UserAuthContext), 0, sizeof(UserAuthContext));
68     if (memcpy_s(context->challenge, CHALLENGE_LEN, params.challenge, CHALLENGE_LEN) != EOK) {
69         LOG_ERROR("failed to copy challenge");
70         Free(context);
71         return NULL;
72     }
73     context->contextId = params.contextId;
74     context->userId = params.userId;
75     context->authType = params.authType;
76     context->authTrustLevel = params.authTrustLevel;
77     context->collectorSensorHint = params.executorSensorHint;
78     context->scheduleList = CreateLinkedList(DestroyScheduleNode);
79     context->authIntent = params.authIntent;
80     context->isExpiredReturnSuccess = params.isExpiredReturnSuccess;
81 
82     if (memcpy_s(context->localUdid, sizeof(context->localUdid), params.localUdid,
83         sizeof(params.localUdid)) != EOK) {
84         LOG_ERROR("localUdid copy failed");
85         Free(context);
86         return NULL;
87     }
88 
89     if (memcpy_s(context->collectorUdid, sizeof(context->collectorUdid), params.collectorUdid,
90         sizeof(params.collectorUdid)) != EOK) {
91         LOG_ERROR("collectorUdid copy failed");
92         Free(context);
93         return NULL;
94     }
95 
96     if (context->scheduleList == NULL) {
97         LOG_ERROR("schedule list create failed");
98         Free(context);
99         return NULL;
100     }
101 
102     return context;
103 }
104 
SetContextExpiredTime(UserAuthContext * authContext)105 IAM_STATIC ResultCode SetContextExpiredTime(UserAuthContext *authContext)
106 {
107     if (authContext == NULL) {
108         LOG_ERROR("bad param");
109         return RESULT_BAD_PARAM;
110     }
111     PinExpiredInfo expiredInfo = {};
112     ResultCode result = GetPinExpiredInfo(authContext->userId, &expiredInfo);
113     if (result != RESULT_SUCCESS) {
114         LOG_ERROR("GetPinExpiredInfo failed");
115         return result;
116     }
117     if (expiredInfo.pinExpiredPeriod == NO_CHECK_PIN_EXPIRED_PERIOD) {
118         LOG_ERROR("pinExpiredPeriod is not set");
119         authContext->authExpiredSysTime = NO_CHECK_PIN_EXPIRED_PERIOD;
120         return RESULT_SUCCESS;
121     }
122     authContext->authExpiredSysTime = UINT64_MAX;
123     if (expiredInfo.pinEnrolledSysTime + expiredInfo.pinExpiredPeriod < UINT64_MAX) {
124         authContext->authExpiredSysTime = expiredInfo.pinEnrolledSysTime + expiredInfo.pinExpiredPeriod;
125     }
126     return RESULT_SUCCESS;
127 }
128 
GenerateAuthContext(AuthParamHal params,UserAuthContext ** context)129 ResultCode GenerateAuthContext(AuthParamHal params, UserAuthContext **context)
130 {
131     LOG_INFO("start");
132     if (context == NULL) {
133         LOG_ERROR("context is null");
134         return RESULT_BAD_PARAM;
135     }
136     if (g_contextList == NULL) {
137         LOG_ERROR("need init");
138         return RESULT_NEED_INIT;
139     }
140     if (IsContextDuplicate(params.contextId)) {
141         LOG_ERROR("contextId is duplicate");
142         return RESULT_DUPLICATE_CHECK_FAILED;
143     }
144     *context = InitAuthContext(params);
145     if (*context == NULL) {
146         LOG_ERROR("init context failed");
147         return RESULT_GENERAL_ERROR;
148     }
149     ResultCode ret = CreateAndInsertSchedules(*context, SCHEDULE_MODE_AUTH);
150     if (ret != RESULT_SUCCESS) {
151         LOG_ERROR("create schedule failed %{public}d", ret);
152         DestroyContextNode(*context);
153         *context = NULL;
154         return ret;
155     }
156     ret = SetContextExpiredTime(*context);
157     if (ret != RESULT_SUCCESS) {
158         LOG_ERROR("GetAuthExpiredSysTime failed");
159         DestroyContextNode(*context);
160         *context = NULL;
161         return ret;
162     }
163     ret = g_contextList->insert(g_contextList, *context);
164     if (ret != RESULT_SUCCESS) {
165         LOG_ERROR("create schedule failed");
166         DestroyContextNode(*context);
167         *context = NULL;
168         return RESULT_GENERAL_ERROR;
169     }
170     return RESULT_SUCCESS;
171 }
172 
CreateIdentifySchedule(const UserAuthContext * context,CoAuthSchedule ** schedule)173 IAM_STATIC ResultCode CreateIdentifySchedule(const UserAuthContext *context, CoAuthSchedule **schedule)
174 {
175     ScheduleParam scheduleParam = {};
176     scheduleParam.associateId.contextId = context->contextId;
177     scheduleParam.authType = context->authType;
178     scheduleParam.collectorSensorHint = context->collectorSensorHint;
179     scheduleParam.verifierSensorHint = context->collectorSensorHint;
180     scheduleParam.scheduleMode = SCHEDULE_MODE_IDENTIFY;
181     Uint8Array localUdid = { scheduleParam.localUdid, UDID_LEN };
182     bool getLocalUdidRet = GetLocalUdid(&localUdid);
183     Uint8Array collectorUdid = { scheduleParam.collectorUdid, UDID_LEN };
184     bool getCollectorUdidRet = GetLocalUdid(&collectorUdid);
185     if (!getLocalUdidRet || !getCollectorUdidRet) {
186         LOG_ERROR("get udid failed");
187         return RESULT_GENERAL_ERROR;
188     }
189     *schedule = GenerateSchedule(&scheduleParam);
190     if (*schedule == NULL) {
191         LOG_ERROR("GenerateSchedule failed");
192         return RESULT_GENERAL_ERROR;
193     }
194     return RESULT_SUCCESS;
195 }
196 
InitIdentifyContext(const IdentifyParam * params)197 IAM_STATIC UserAuthContext *InitIdentifyContext(const IdentifyParam *params)
198 {
199     UserAuthContext *context = (UserAuthContext *)Malloc(sizeof(UserAuthContext));
200     if (context == NULL) {
201         LOG_ERROR("context malloc failed");
202         return NULL;
203     }
204     (void)memset_s(context, sizeof(UserAuthContext), 0, sizeof(UserAuthContext));
205     if (memcpy_s(context->challenge, CHALLENGE_LEN, params->challenge, CHALLENGE_LEN) != EOK) {
206         LOG_ERROR("failed to copy challenge");
207         Free(context);
208         return NULL;
209     }
210     context->contextId = params->contextId;
211     context->authType = params->authType;
212     context->collectorSensorHint = params->executorSensorHint;
213     context->scheduleList = CreateLinkedList(DestroyScheduleNode);
214     if (context->scheduleList == NULL) {
215         LOG_ERROR("schedule list create failed");
216         Free(context);
217         return NULL;
218     }
219     return context;
220 }
221 
GenerateIdentifyContext(IdentifyParam params)222 UserAuthContext *GenerateIdentifyContext(IdentifyParam params)
223 {
224     LOG_INFO("start");
225     if (g_contextList == NULL) {
226         LOG_ERROR("need init");
227         return NULL;
228     }
229     if (IsContextDuplicate(params.contextId)) {
230         LOG_ERROR("contextId is duplicate");
231         return NULL;
232     }
233 
234     UserAuthContext *context = InitIdentifyContext(&params);
235     if (context == NULL) {
236         LOG_ERROR("init context failed");
237         return NULL;
238     }
239     ResultCode ret = CreateAndInsertSchedules(context, SCHEDULE_MODE_IDENTIFY);
240     if (ret != RESULT_SUCCESS) {
241         LOG_ERROR("create schedule failed");
242         DestroyContextNode(context);
243         return NULL;
244     }
245     ret = g_contextList->insert(g_contextList, context);
246     if (ret != RESULT_SUCCESS) {
247         LOG_ERROR("create schedule failed");
248         DestroyContextNode(context);
249         return NULL;
250     }
251     return context;
252 }
253 
GetContext(uint64_t contextId)254 UserAuthContext *GetContext(uint64_t contextId)
255 {
256     if (g_contextList == NULL) {
257         LOG_ERROR("context list is null");
258         return NULL;
259     }
260     uint32_t num = g_contextList->getSize(g_contextList);
261     LinkedListNode *tempNode = g_contextList->head;
262     UserAuthContext *contextRet = NULL;
263     for (uint32_t index = 0; index < num; index++) {
264         if (tempNode == NULL) {
265             LOG_ERROR("node is null");
266             return NULL;
267         }
268         contextRet = (UserAuthContext *)tempNode->data;
269         if (contextRet != NULL && contextRet->contextId == contextId) {
270             return contextRet;
271         }
272         tempNode = tempNode->next;
273     }
274     return NULL;
275 }
276 
InsertScheduleToContext(CoAuthSchedule * schedule,UserAuthContext * context)277 IAM_STATIC ResultCode InsertScheduleToContext(CoAuthSchedule *schedule, UserAuthContext *context)
278 {
279     LinkedList *scheduleList = context->scheduleList;
280     return scheduleList->insert(scheduleList, schedule);
281 }
282 
CreateAndInsertSchedules(UserAuthContext * context,uint32_t authMode)283 IAM_STATIC ResultCode CreateAndInsertSchedules(UserAuthContext *context, uint32_t authMode)
284 {
285     LOG_INFO("start");
286     CoAuthSchedule *schedule = NULL;
287     ResultCode result = RESULT_BAD_PARAM;
288     if (authMode == SCHEDULE_MODE_AUTH) {
289         result = CreateAuthSchedule(context, &schedule);
290     } else if (authMode == SCHEDULE_MODE_IDENTIFY) {
291         result = CreateIdentifySchedule(context, &schedule);
292     } else {
293         LOG_ERROR("authMode is invalid");
294         return result;
295     }
296 
297     if (result != RESULT_SUCCESS) {
298         LOG_INFO("create schedule fail %{public}d", result);
299         return result;
300     }
301 
302     if (AddCoAuthSchedule(schedule) != RESULT_SUCCESS) {
303         LOG_ERROR("AddCoAuthSchedule failed");
304         DestroyCoAuthSchedule(schedule);
305         return RESULT_UNKNOWN;
306     }
307 
308     if (InsertScheduleToContext(schedule, context) != RESULT_SUCCESS) {
309         RemoveCoAuthSchedule(schedule->scheduleId);
310         DestroyCoAuthSchedule(schedule);
311         LOG_ERROR("insert failed");
312         return RESULT_UNKNOWN;
313     }
314     return RESULT_SUCCESS;
315 }
316 
GetAuthCredentialList(const UserAuthContext * context)317 IAM_STATIC LinkedList *GetAuthCredentialList(const UserAuthContext *context)
318 {
319     CredentialCondition condition = {};
320     SetCredentialConditionAuthType(&condition, context->authType);
321     SetCredentialConditionUserId(&condition, context->userId);
322     if (context->collectorSensorHint != INVALID_SENSOR_HINT) {
323         uint32_t executorMatcher;
324         ResultCode ret = QueryCollecterMatcher(context->authType, context->collectorSensorHint, &executorMatcher);
325         if (ret != RESULT_SUCCESS) {
326             LOG_ERROR("query collect matcher failed");
327             return NULL;
328         }
329         SetCredentialConditionExecutorMatcher(&condition, executorMatcher);
330     }
331     return QueryCredentialLimit(&condition);
332 }
333 
CheckCredentialSize(LinkedList * credList)334 IAM_STATIC ResultCode CheckCredentialSize(LinkedList *credList)
335 {
336     uint32_t credNum = credList->getSize(credList);
337     if (credNum == 0) {
338         LOG_ERROR("credNum is 0");
339         return RESULT_NOT_ENROLLED;
340     }
341     if (credNum > MAX_CREDENTIAL) {
342         LOG_ERROR("credNum exceed limit");
343         return RESULT_EXCEED_LIMIT;
344     }
345     return RESULT_SUCCESS;
346 }
347 
QueryAuthTempletaInfo(UserAuthContext * context,Uint64Array * templateIds,uint32_t * sensorHint,uint32_t * matcher,uint32_t * acl)348 IAM_STATIC ResultCode QueryAuthTempletaInfo(UserAuthContext *context, Uint64Array *templateIds,
349     uint32_t *sensorHint, uint32_t *matcher, uint32_t *acl)
350 {
351     LinkedList *credList = GetAuthCredentialList(context);
352     if (credList == NULL) {
353         LOG_ERROR("query credential failed");
354         return RESULT_UNKNOWN;
355     }
356     ResultCode checkResult = CheckCredentialSize(credList);
357     if (checkResult != RESULT_SUCCESS) {
358         LOG_ERROR("CheckCredentialSize failed %{public}d", checkResult);
359         DestroyLinkedList(credList);
360         return checkResult;
361     }
362     templateIds->data = (uint64_t *)Malloc(sizeof(uint64_t) * credList->getSize(credList));
363     if (templateIds->data == NULL) {
364         LOG_ERROR("value malloc failed");
365         DestroyLinkedList(credList);
366         return RESULT_NO_MEMORY;
367     }
368     templateIds->len = 0;
369     LinkedListNode *temp = credList->head;
370     if (temp == NULL || temp->data == NULL) {
371         LOG_ERROR("link node is invalid");
372         goto FAIL;
373     }
374     CredentialInfoHal *credentialHal = (CredentialInfoHal *)temp->data;
375     *sensorHint = credentialHal->executorSensorHint;
376     *matcher = credentialHal->executorMatcher;
377     *acl = credentialHal->capabilityLevel;
378     while (temp != NULL) {
379         if (temp->data == NULL) {
380             LOG_ERROR("link node is invalid");
381             goto FAIL;
382         }
383         credentialHal = (CredentialInfoHal *)temp->data;
384         if (credentialHal->executorSensorHint == *sensorHint) {
385             templateIds->data[templateIds->len] = credentialHal->templateId;
386             ++(templateIds->len);
387         }
388         temp = temp->next;
389     }
390     DestroyLinkedList(credList);
391     return RESULT_SUCCESS;
392 
393 FAIL:
394     Free(templateIds->data);
395     templateIds->data = NULL;
396     DestroyLinkedList(credList);
397     return RESULT_UNKNOWN;
398 }
399 
CreateAuthSchedule(UserAuthContext * context,CoAuthSchedule ** schedule)400 IAM_STATIC ResultCode CreateAuthSchedule(UserAuthContext *context, CoAuthSchedule **schedule)
401 {
402     Uint64Array templateIds = {};
403     uint32_t verifierSensorHint;
404     uint32_t executorMatcher;
405     uint32_t acl;
406     ResultCode ret = QueryAuthTempletaInfo(context, &templateIds, &verifierSensorHint, &executorMatcher, &acl);
407     if (ret != RESULT_SUCCESS) {
408         LOG_ERROR("QueryAuthTempletaInfo failed %{public}d", ret);
409         return ret;
410     }
411     ScheduleParam scheduleParam = {};
412     scheduleParam.associateId.contextId = context->contextId;
413     scheduleParam.authType = context->authType;
414     scheduleParam.collectorSensorHint = context->collectorSensorHint;
415     scheduleParam.verifierSensorHint = verifierSensorHint;
416     scheduleParam.templateIds = &templateIds;
417     scheduleParam.executorMatcher = executorMatcher;
418     scheduleParam.scheduleMode = SCHEDULE_MODE_AUTH;
419     if (memcpy_s(scheduleParam.localUdid, sizeof(scheduleParam.localUdid), context->localUdid,
420         sizeof(context->localUdid)) != EOK) {
421         LOG_ERROR("localUdid copy failed");
422         return RESULT_GENERAL_ERROR;
423     }
424 
425     if (memcpy_s(scheduleParam.collectorUdid, sizeof(scheduleParam.collectorUdid), context->collectorUdid,
426         sizeof(context->collectorUdid)) != EOK) {
427         LOG_ERROR("collectorUdid copy failed");
428         return RESULT_GENERAL_ERROR;
429     }
430     *schedule = GenerateSchedule(&scheduleParam);
431     if (*schedule == NULL) {
432         LOG_ERROR("schedule is null");
433         Free(templateIds.data);
434         return RESULT_GENERAL_ERROR;
435     }
436     uint32_t scheduleAtl;
437     ret = QueryScheduleAtl(*schedule, acl, &scheduleAtl);
438     if (ret != RESULT_SUCCESS || context->authTrustLevel > scheduleAtl) {
439         Free(templateIds.data);
440         DestroyCoAuthSchedule(*schedule);
441         *schedule = NULL;
442         return ret;
443     }
444     Free(templateIds.data);
445     return RESULT_SUCCESS;
446 }
447 
IsContextDuplicate(uint64_t contextId)448 IAM_STATIC bool IsContextDuplicate(uint64_t contextId)
449 {
450     if (g_contextList == NULL) {
451         LOG_ERROR("context list is null");
452         return false;
453     }
454     LinkedListNode *tempNode = g_contextList->head;
455     while (tempNode != NULL) {
456         UserAuthContext *context = (UserAuthContext *)tempNode->data;
457         if (context == NULL) {
458             LOG_ERROR("context is null, please check");
459             tempNode = tempNode->next;
460             continue;
461         }
462         if (context->contextId == contextId) {
463             return true;
464         }
465         tempNode = tempNode->next;
466     }
467     return false;
468 }
469 
CopySchedules(UserAuthContext * context,LinkedList ** schedules)470 ResultCode CopySchedules(UserAuthContext *context, LinkedList **schedules)
471 {
472     if (context == NULL || context->scheduleList == NULL || schedules == NULL) {
473         LOG_ERROR("param is null");
474         return RESULT_BAD_PARAM;
475     }
476     LinkedList *scheduleList = context->scheduleList;
477     uint32_t scheduleNum = scheduleList->getSize(scheduleList);
478     if (scheduleNum > AUTH_MAX_SCHEDULING_NUM) {
479         LOG_ERROR("scheduleNum is invalid, scheduleNum is %{public}u", scheduleNum);
480         return RESULT_UNKNOWN;
481     }
482     *schedules = CreateLinkedList(DestroyScheduleNode);
483     if (*schedules == NULL) {
484         LOG_ERROR("schedules malloc failed");
485         return RESULT_NO_MEMORY;
486     }
487     if (scheduleNum == 0) {
488         LOG_INFO("scheduleNum is zero");
489         return RESULT_SUCCESS;
490     }
491 
492     LinkedListNode *temp = scheduleList->head;
493     while (temp != NULL) {
494         if (temp->data == NULL) {
495             LOG_ERROR("node data is wrong, please check");
496             goto ERROR;
497         }
498         CoAuthSchedule *schedule = CopyCoAuthSchedule((CoAuthSchedule *)temp->data);
499         if (schedule == NULL) {
500             LOG_ERROR("data is null");
501             goto ERROR;
502         }
503         if ((*schedules)->insert(*schedules, schedule) != RESULT_SUCCESS) {
504             LOG_ERROR("insert schedule failed");
505             DestroyCoAuthSchedule(schedule);
506             goto ERROR;
507         }
508         temp = temp->next;
509     }
510     return RESULT_SUCCESS;
511 
512 ERROR:
513     DestroyLinkedList(*schedules);
514     *schedules = NULL;
515     return RESULT_GENERAL_ERROR;
516 }
517 
MatchSchedule(const void * data,const void * condition)518 IAM_STATIC bool MatchSchedule(const void *data, const void *condition)
519 {
520     if (data == NULL || condition == NULL) {
521         LOG_ERROR("param is null");
522         return false;
523     }
524     const CoAuthSchedule *schedule = (const CoAuthSchedule *)data;
525     if (schedule->scheduleId == *(const uint64_t *)condition) {
526         return true;
527     }
528     return false;
529 }
530 
ScheduleOnceFinish(UserAuthContext * context,uint64_t scheduleId)531 ResultCode ScheduleOnceFinish(UserAuthContext *context, uint64_t scheduleId)
532 {
533     if (context == NULL || context->scheduleList == NULL) {
534         LOG_ERROR("param is null");
535         return RESULT_BAD_PARAM;
536     }
537     RemoveCoAuthSchedule(scheduleId);
538     return context->scheduleList->remove(context->scheduleList, &scheduleId, MatchSchedule, true);
539 }
540 
MatchContextSelf(const void * data,const void * condition)541 IAM_STATIC bool MatchContextSelf(const void *data, const void *condition)
542 {
543     return data == condition;
544 }
545 
DestroyContext(UserAuthContext * context)546 void DestroyContext(UserAuthContext *context)
547 {
548     if (context == NULL) {
549         LOG_ERROR("context is null");
550         return;
551     }
552     if (g_contextList == NULL) {
553         LOG_ERROR("context list is null");
554         return;
555     }
556     g_contextList->remove(g_contextList, context, MatchContextSelf, true);
557 }
558 
DestroyContextNode(void * data)559 IAM_STATIC void DestroyContextNode(void *data)
560 {
561     if (data == NULL) {
562         return;
563     }
564     LinkedList *schedules = ((UserAuthContext *)data)->scheduleList;
565     if (schedules == NULL) {
566         LOG_ERROR("schedules is null");
567         return;
568     }
569     LinkedListNode *tempNode = schedules->head;
570     while (tempNode != NULL) {
571         CoAuthSchedule *schedule = tempNode->data;
572         if (schedule == NULL) {
573             LOG_ERROR("schedule is null, please check");
574             tempNode = tempNode->next;
575             continue;
576         }
577         RemoveCoAuthSchedule(schedule->scheduleId);
578         tempNode = tempNode->next;
579     }
580     DestroyLinkedList(schedules);
581     Free(data);
582 }
583 
DestroyContextbyId(uint64_t contextId)584 ResultCode DestroyContextbyId(uint64_t contextId)
585 {
586     UserAuthContext *authContext = GetContext(contextId);
587     if (authContext == NULL) {
588         LOG_ERROR("get context failed");
589         return RESULT_NOT_FOUND;
590     }
591     DestroyContext(authContext);
592     return RESULT_SUCCESS;
593 }
594 
GetCoAuthScheduleFromContext(const UserAuthContext * context,uint64_t scheduleId)595 IAM_STATIC const CoAuthSchedule *GetCoAuthScheduleFromContext(const UserAuthContext *context, uint64_t scheduleId)
596 {
597     if (context->scheduleList == NULL) {
598         LOG_ERROR("get null scheduleList");
599         return NULL;
600     }
601 
602     LinkedListNode *tempNode = context->scheduleList->head;
603     while (tempNode != NULL) {
604         const CoAuthSchedule *schedule = tempNode->data;
605         if (schedule == NULL) {
606             LOG_ERROR("schedule is null, please check");
607             tempNode = tempNode->next;
608             continue;
609         }
610         if (schedule->scheduleId == scheduleId) {
611             return schedule;
612         }
613         tempNode = tempNode->next;
614     }
615 
616     LOG_ERROR("no schedule exist");
617     return NULL;
618 }
619 
CheckAndSetContextAtl(UserAuthContext * context,const CoAuthSchedule * schedule,ExecutorResultInfo * info)620 IAM_STATIC ResultCode CheckAndSetContextAtl(
621     UserAuthContext *context, const CoAuthSchedule *schedule, ExecutorResultInfo *info)
622 {
623     uint32_t atl = ATL0;
624     ResultCode ret = QueryScheduleAtl(schedule, info->capabilityLevel, &atl);
625     if (ret != RESULT_SUCCESS) {
626         LOG_ERROR("QueryScheduleAtl fail");
627         return ret;
628     }
629     if (atl < context->authTrustLevel) {
630         LOG_ERROR("atl %u not satisfied, context atl:%u", atl, context->authTrustLevel);
631         return RESULT_TRUST_LEVEL_NOT_SUPPORT;
632     }
633     LOG_INFO("context atl %{public}u:%{public}u", context->authTrustLevel, atl);
634     context->authTrustLevel = atl;
635     return RESULT_SUCCESS;
636 }
637 
CheckAndSetContextUserId(UserAuthContext * context,uint64_t credentialId,uint32_t authMode)638 IAM_STATIC ResultCode CheckAndSetContextUserId(UserAuthContext *context, uint64_t credentialId, uint32_t authMode)
639 {
640     int32_t userId = 0;
641     ResultCode ret = QueryCredentialUserId(credentialId, &userId);
642     if (ret != RESULT_SUCCESS) {
643         LOG_ERROR("query userId failed");
644         return ret;
645     }
646     if (authMode == SCHEDULE_MODE_IDENTIFY) {
647         context->userId = userId;
648     }
649     if (userId != context->userId) {
650         LOG_ERROR("userId is not matched");
651         return RESULT_GENERAL_ERROR;
652     }
653     return RESULT_SUCCESS;
654 }
655 
FillInContext(UserAuthContext * context,uint64_t * credentialId,ExecutorResultInfo * info,uint32_t authMode)656 ResultCode FillInContext(UserAuthContext *context, uint64_t *credentialId, ExecutorResultInfo *info,
657     uint32_t authMode)
658 {
659     if (context == NULL || credentialId == NULL  || info == NULL) {
660         LOG_ERROR("param is null");
661         return RESULT_BAD_PARAM;
662     }
663     const CoAuthSchedule *schedule = GetCoAuthScheduleFromContext(context, info->scheduleId);
664     if (schedule == NULL) {
665         LOG_ERROR("GetCoAuthScheduleFromContext failed");
666         return RESULT_GENERAL_ERROR;
667     }
668     ResultCode ret = CheckAndSetContextAtl(context, schedule, info);
669     if (ret != RESULT_SUCCESS) {
670         LOG_ERROR("CheckAndSetContextAtl failed");
671         return ret;
672     }
673     ret = RESULT_UNKNOWN;
674     uint32_t verifierSensorHint = GetScheduleVerifierSensorHint(schedule);
675     CredentialCondition condition = {};
676     SetCredentialConditionAuthType(&condition, context->authType);
677     SetCredentialConditionTemplateId(&condition, info->templateId);
678     SetCredentialConditionExecutorSensorHint(&condition, verifierSensorHint);
679     LinkedList *credList = QueryCredentialLimit(&condition);
680     if (credList == NULL || credList->getSize(credList) != 1) {
681         LOG_ERROR("query credential failed");
682         goto EXIT;
683     }
684     if (credList->head == NULL || credList->head->data == NULL) {
685         LOG_ERROR("list node is invalid");
686         goto EXIT;
687     }
688     CredentialInfoHal *credentialNode = (CredentialInfoHal *)credList->head->data;
689     ret = CheckAndSetContextUserId(context, credentialNode->credentialId, authMode);
690     if (ret != RESULT_SUCCESS) {
691         LOG_ERROR("CheckAndSetContextUserId failed");
692         goto EXIT;
693     }
694     *credentialId = credentialNode->credentialId;
695 EXIT:
696     DestroyLinkedList(credList);
697     return ret;
698 }
699