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 "idm_database.h"
17 
18 #include "inttypes.h"
19 #include "securec.h"
20 
21 #include "adaptor_algorithm.h"
22 #include "adaptor_log.h"
23 #include "adaptor_time.h"
24 #include "idm_file_manager.h"
25 #include "global_config_file_manager.h"
26 
27 #define MAX_DUPLICATE_CHECK 100
28 #define PRE_APPLY_NUM 5
29 #define MEM_GROWTH_FACTOR 2
30 #define MAX_CREDENTIAL_RETURN 5000
31 
32 #ifdef IAM_TEST_ENABLE
33 #define IAM_STATIC
34 #else
35 #define IAM_STATIC static
36 #endif
37 
38 // Caches IDM user information.
39 IAM_STATIC LinkedList *g_userInfoList = NULL;
40 
41 // Caches the current user to reduce the number of user list traversal times.
42 IAM_STATIC UserInfo *g_currentUser = NULL;
43 
44 // Caches global config info.
45 IAM_STATIC GlobalConfigInfo g_globalConfigArray[MAX_GLOBAL_CONFIG_NUM];
46 IAM_STATIC uint32_t g_globalConfigInfoNum = 0;
47 
48 typedef bool (*DuplicateCheckFunc)(LinkedList *collection, uint64_t value);
49 
50 IAM_STATIC UserInfo *QueryUserInfo(int32_t userId);
51 IAM_STATIC ResultCode GetAllEnrolledInfoFromUser(UserInfo *userInfo, EnrolledInfoHal **enrolledInfos, uint32_t *num);
52 IAM_STATIC ResultCode DeleteUser(int32_t userId);
53 IAM_STATIC CredentialInfoHal *QueryCredentialById(uint64_t credentialId, LinkedList *credentialList);
54 IAM_STATIC CredentialInfoHal *QueryCredentialByAuthType(uint32_t authType, LinkedList *credentialList);
55 IAM_STATIC bool MatchCredentialById(const void *data, const void *condition);
56 IAM_STATIC ResultCode GenerateDeduplicateUint64(LinkedList *collection, uint64_t *destValue, DuplicateCheckFunc func);
57 IAM_STATIC bool IsUserValid(UserInfo *user);
58 IAM_STATIC ResultCode GetInvalidUser(int32_t *invalidUserId, uint32_t maxUserCount, uint32_t *userCount,
59     bool *cachePinRemoved);
60 IAM_STATIC void RemoveCachePin(UserInfo *user, bool *isRemoved);
61 IAM_STATIC ResultCode ClearInvalidData(void);
62 
InitUserInfoList(void)63 ResultCode InitUserInfoList(void)
64 {
65     LOG_INFO("InitUserInfoList start");
66     if (g_userInfoList != NULL) {
67         DestroyUserInfoList();
68         g_userInfoList = NULL;
69     }
70     g_userInfoList = LoadFileInfo();
71     if (g_userInfoList == NULL) {
72         LOG_ERROR("load file info failed");
73         return RESULT_NEED_INIT;
74     }
75     ResultCode ret = ClearInvalidData();
76     if (ret != RESULT_SUCCESS) {
77         LOG_ERROR("clear invalid user failed");
78         DestroyUserInfoList();
79         return ret;
80     }
81     ret = LoadGlobalConfigInfo(g_globalConfigArray, MAX_GLOBAL_CONFIG_NUM, &g_globalConfigInfoNum);
82     if (ret != RESULT_SUCCESS) {
83         LOG_ERROR("load global config info failed");
84     }
85     LOG_INFO("InitUserInfoList end");
86     return RESULT_SUCCESS;
87 }
88 
DestroyUserInfoList(void)89 void DestroyUserInfoList(void)
90 {
91     DestroyLinkedList(g_userInfoList);
92     g_userInfoList = NULL;
93 }
94 
MatchUserInfo(const void *data, const void *condition)95 IAM_STATIC bool MatchUserInfo(const void *data, const void *condition)
96 {
97     if (data == NULL || condition == NULL) {
98         LOG_ERROR("please check invalid node");
99         return false;
100     }
101     const UserInfo *userInfo = (const UserInfo *)data;
102     int32_t userId = *(const int32_t *)condition;
103     if (userInfo->userId == userId) {
104         return true;
105     }
106     return false;
107 }
108 
IsUserInfoValid(UserInfo *userInfo)109 IAM_STATIC bool IsUserInfoValid(UserInfo *userInfo)
110 {
111     if (userInfo == NULL) {
112         LOG_ERROR("userInfo is null");
113         return false;
114     }
115     if (userInfo->credentialInfoList == NULL) {
116         LOG_ERROR("credentialInfoList is null");
117         return false;
118     }
119     if (userInfo->enrolledInfoList == NULL) {
120         LOG_ERROR("enrolledInfoList is null");
121         return false;
122     }
123     return true;
124 }
125 
GetSecureUid(int32_t userId, uint64_t *secUid)126 ResultCode GetSecureUid(int32_t userId, uint64_t *secUid)
127 {
128     if (secUid == NULL) {
129         LOG_ERROR("secUid is null");
130         return RESULT_BAD_PARAM;
131     }
132     UserInfo *user = QueryUserInfo(userId);
133     if (user == NULL) {
134         LOG_ERROR("can't find this user");
135         return RESULT_NOT_FOUND;
136     }
137     *secUid = user->secUid;
138     return RESULT_SUCCESS;
139 }
140 
GetEnrolledInfoAuthType(int32_t userId, uint32_t authType, EnrolledInfoHal *enrolledInfo)141 ResultCode GetEnrolledInfoAuthType(int32_t userId, uint32_t authType, EnrolledInfoHal *enrolledInfo)
142 {
143     if (enrolledInfo == NULL) {
144         LOG_ERROR("enrolledInfo is null");
145         return RESULT_BAD_PARAM;
146     }
147     UserInfo *user = QueryUserInfo(userId);
148     if (user == NULL) {
149         LOG_ERROR("can't find this user");
150         return RESULT_NOT_FOUND;
151     }
152     if (user->enrolledInfoList == NULL) {
153         LOG_ERROR("enrolledInfoList is null");
154         return RESULT_UNKNOWN;
155     }
156 
157     LinkedListNode *temp = user->enrolledInfoList->head;
158     while (temp != NULL) {
159         EnrolledInfoHal *nodeInfo = temp->data;
160         if (nodeInfo != NULL && nodeInfo->authType == authType) {
161             *enrolledInfo = *nodeInfo;
162             return RESULT_SUCCESS;
163         }
164         temp = temp->next;
165     }
166 
167     return RESULT_NOT_FOUND;
168 }
169 
GetEnrolledInfo(int32_t userId, EnrolledInfoHal **enrolledInfos, uint32_t *num)170 ResultCode GetEnrolledInfo(int32_t userId, EnrolledInfoHal **enrolledInfos, uint32_t *num)
171 {
172     if (enrolledInfos == NULL || num == NULL) {
173         LOG_ERROR("param is invalid");
174         return RESULT_BAD_PARAM;
175     }
176     UserInfo *user = QueryUserInfo(userId);
177     if (!IsUserInfoValid(user)) {
178         LOG_ERROR("can't find this user");
179         return RESULT_NOT_FOUND;
180     }
181     return GetAllEnrolledInfoFromUser(user, enrolledInfos, num);
182 }
183 
DeleteUserInfo(int32_t userId, LinkedList **creds)184 ResultCode DeleteUserInfo(int32_t userId, LinkedList **creds)
185 {
186     if (creds == NULL) {
187         LOG_ERROR("param is invalid");
188         return RESULT_BAD_PARAM;
189     }
190     UserInfo *user = QueryUserInfo(userId);
191     if (!IsUserInfoValid(user)) {
192         LOG_ERROR("can't find this user");
193         return RESULT_NOT_FOUND;
194     }
195     CredentialCondition condition = {};
196     SetCredentialConditionUserId(&condition, userId);
197     *creds = QueryCredentialLimit(&condition);
198     if (*creds == NULL) {
199         LOG_ERROR("query credential failed");
200         return RESULT_UNKNOWN;
201     }
202     g_currentUser = NULL;
203 
204     ResultCode ret = DeleteUser(userId);
205     if (ret != RESULT_SUCCESS) {
206         LOG_ERROR("deleteUser failed");
207         DestroyLinkedList(*creds);
208         *creds = NULL;
209         return ret;
210     }
211     ret = UpdateFileInfo(g_userInfoList);
212     if (ret != RESULT_SUCCESS) {
213         LOG_ERROR("update file info failed");
214         DestroyLinkedList(*creds);
215         *creds = NULL;
216         return ret;
217     }
218     return ret;
219 }
220 
QueryUserInfo(int32_t userId)221 IAM_STATIC UserInfo *QueryUserInfo(int32_t userId)
222 {
223     UserInfo *user = g_currentUser;
224     if (user != NULL && user->userId == userId) {
225         return user;
226     }
227     if (g_userInfoList == NULL) {
228         return NULL;
229     }
230     LinkedListNode *temp = g_userInfoList->head;
231     while (temp != NULL) {
232         user = (UserInfo *)temp->data;
233         if (user != NULL && user->userId == userId) {
234             break;
235         }
236         temp = temp->next;
237     }
238     if (temp == NULL) {
239         return NULL;
240     }
241     if (IsUserInfoValid(user)) {
242         g_currentUser = user;
243         return user;
244     }
245     return NULL;
246 }
247 
GetAllEnrolledInfoFromUser(UserInfo *userInfo, EnrolledInfoHal **enrolledInfos, uint32_t *num)248 IAM_STATIC ResultCode GetAllEnrolledInfoFromUser(UserInfo *userInfo, EnrolledInfoHal **enrolledInfos, uint32_t *num)
249 {
250     LinkedList *enrolledInfoList = userInfo->enrolledInfoList;
251     uint32_t size = enrolledInfoList->getSize(enrolledInfoList);
252     *enrolledInfos = Malloc(sizeof(EnrolledInfoHal) * size);
253     if (*enrolledInfos == NULL) {
254         LOG_ERROR("enrolledInfos malloc failed");
255         return RESULT_NO_MEMORY;
256     }
257     (void)memset_s(*enrolledInfos, sizeof(EnrolledInfoHal) * size, 0, sizeof(EnrolledInfoHal) * size);
258     LinkedListNode *temp = enrolledInfoList->head;
259     ResultCode result = RESULT_SUCCESS;
260     for (*num = 0; *num < size; (*num)++) {
261         if (temp == NULL) {
262             LOG_ERROR("temp node is null, something wrong");
263             result = RESULT_BAD_PARAM;
264             goto EXIT;
265         }
266         EnrolledInfoHal *tempInfo = (EnrolledInfoHal *)temp->data;
267         if (memcpy_s(*enrolledInfos + *num, sizeof(EnrolledInfoHal) * (size - *num),
268             tempInfo, sizeof(EnrolledInfoHal)) != EOK) {
269             LOG_ERROR("copy the %u information failed", *num);
270             result = RESULT_NO_MEMORY;
271             goto EXIT;
272         }
273         temp = temp->next;
274     }
275 
276 EXIT:
277     if (result != RESULT_SUCCESS) {
278         Free(*enrolledInfos);
279         *enrolledInfos = NULL;
280         *num = 0;
281     }
282     return result;
283 }
284 
IsSecureUidDuplicate(LinkedList *userInfoList, uint64_t secureUid)285 IAM_STATIC bool IsSecureUidDuplicate(LinkedList *userInfoList, uint64_t secureUid)
286 {
287     if (userInfoList == NULL) {
288         LOG_ERROR("the user list is empty, and the branch is abnormal");
289         return false;
290     }
291 
292     LinkedListNode *temp = userInfoList->head;
293     UserInfo *userInfo = NULL;
294     while (temp != NULL) {
295         userInfo = (UserInfo *)temp->data;
296         if (userInfo != NULL && userInfo->secUid == secureUid) {
297             return true;
298         }
299         temp = temp->next;
300     }
301 
302     return false;
303 }
304 
CreateUser(int32_t userId, int32_t userType)305 IAM_STATIC UserInfo *CreateUser(int32_t userId, int32_t userType)
306 {
307     UserInfo *user = InitUserInfoNode();
308     if (!IsUserInfoValid(user)) {
309         LOG_ERROR("user is invalid");
310         DestroyUserInfoNode(user);
311         return NULL;
312     }
313     user->userId = userId;
314     user->userType = userType;
315     ResultCode ret = GenerateDeduplicateUint64(g_userInfoList, &user->secUid, IsSecureUidDuplicate);
316     if (ret != RESULT_SUCCESS) {
317         LOG_ERROR("generate secureUid failed");
318         DestroyUserInfoNode(user);
319         return NULL;
320     }
321     return user;
322 }
323 
DeleteUser(int32_t userId)324 IAM_STATIC ResultCode DeleteUser(int32_t userId)
325 {
326     if (g_userInfoList == NULL) {
327         return RESULT_BAD_PARAM;
328     }
329     return g_userInfoList->remove(g_userInfoList, &userId, MatchUserInfo, true);
330 }
331 
IsCredentialIdDuplicate(LinkedList *userInfoList, uint64_t credentialId)332 IAM_STATIC bool IsCredentialIdDuplicate(LinkedList *userInfoList, uint64_t credentialId)
333 {
334     (void)userInfoList;
335     CredentialCondition condition = {};
336     SetCredentialConditionCredentialId(&condition, credentialId);
337     LinkedList *credList = QueryCredentialLimit(&condition);
338     if (credList == NULL) {
339         LOG_ERROR("query failed");
340         return true;
341     }
342     if (credList->getSize(credList) != 0) {
343         LOG_ERROR("duplicate credential id");
344         DestroyLinkedList(credList);
345         return true;
346     }
347     DestroyLinkedList(credList);
348     return false;
349 }
350 
IsEnrolledIdDuplicate(LinkedList *enrolledList, uint64_t enrolledId)351 IAM_STATIC bool IsEnrolledIdDuplicate(LinkedList *enrolledList, uint64_t enrolledId)
352 {
353     LinkedListNode *temp = enrolledList->head;
354     EnrolledInfoHal *enrolledInfo = NULL;
355     const static uint16_t num = 0xFFFF;
356     while (temp != NULL) {
357         enrolledInfo = (EnrolledInfoHal *)temp->data;
358         if ((enrolledInfo != NULL) && (enrolledInfo->enrolledId & num) == (enrolledId & num)) {
359             return true;
360         }
361         temp = temp->next;
362     }
363 
364     return false;
365 }
366 
GenerateDeduplicateUint64(LinkedList *collection, uint64_t *destValue, DuplicateCheckFunc func)367 IAM_STATIC ResultCode GenerateDeduplicateUint64(LinkedList *collection, uint64_t *destValue, DuplicateCheckFunc func)
368 {
369     if (collection == NULL || destValue == NULL || func == NULL) {
370         LOG_ERROR("param is null");
371         return RESULT_BAD_PARAM;
372     }
373 
374     for (uint32_t i = 0; i < MAX_DUPLICATE_CHECK; ++i) {
375         uint64_t tempRandom;
376         if (SecureRandom((uint8_t *)&tempRandom, sizeof(uint64_t)) != RESULT_SUCCESS) {
377             LOG_ERROR("get random failed");
378             return RESULT_GENERAL_ERROR;
379         }
380         if (!func(collection, tempRandom)) {
381             *destValue = tempRandom;
382             return RESULT_SUCCESS;
383         }
384     }
385 
386     LOG_ERROR("generate random failed");
387     return RESULT_GENERAL_ERROR;
388 }
389 
UpdateEnrolledId(LinkedList *enrolledList, uint32_t authType)390 IAM_STATIC ResultCode UpdateEnrolledId(LinkedList *enrolledList, uint32_t authType)
391 {
392     LinkedListNode *temp = enrolledList->head;
393     EnrolledInfoHal *enrolledInfo = NULL;
394     while (temp != NULL) {
395         EnrolledInfoHal *nodeData = (EnrolledInfoHal *)temp->data;
396         if (nodeData != NULL && nodeData->authType == authType) {
397             enrolledInfo = nodeData;
398             break;
399         }
400         temp = temp->next;
401     }
402 
403     if (enrolledInfo != NULL) {
404         return GenerateDeduplicateUint64(enrolledList, &enrolledInfo->enrolledId, IsEnrolledIdDuplicate);
405     }
406 
407     enrolledInfo = Malloc(sizeof(EnrolledInfoHal));
408     if (enrolledInfo == NULL) {
409         LOG_ERROR("enrolledInfo malloc failed");
410         return RESULT_NO_MEMORY;
411     }
412     enrolledInfo->authType = authType;
413     ResultCode ret = GenerateDeduplicateUint64(enrolledList, &enrolledInfo->enrolledId, IsEnrolledIdDuplicate);
414     if (ret != RESULT_SUCCESS) {
415         LOG_ERROR("generate enrolledId failed");
416         Free(enrolledInfo);
417         return ret;
418     }
419     ret = enrolledList->insert(enrolledList, enrolledInfo);
420     if (ret != RESULT_SUCCESS) {
421         LOG_ERROR("enrolledInfo insert failed");
422         Free(enrolledInfo);
423     }
424     return ret;
425 }
426 
427 // add for reliable pin updates
GetRealAuthTypeForEnrolledId(uint32_t authType)428 IAM_STATIC uint32_t GetRealAuthTypeForEnrolledId(uint32_t authType)
429 {
430     if (authType == DEFAULT_AUTH_TYPE) {
431         return PIN_AUTH;
432     }
433     return authType;
434 }
435 
AddCredentialToUser(UserInfo *user, CredentialInfoHal *credentialInfo)436 IAM_STATIC ResultCode AddCredentialToUser(UserInfo *user, CredentialInfoHal *credentialInfo)
437 {
438     if (g_userInfoList == NULL) {
439         LOG_ERROR("g_userInfoList is uninitialized");
440         return RESULT_NEED_INIT;
441     }
442     LinkedList *credentialList = user->credentialInfoList;
443     LinkedList *enrolledList = user->enrolledInfoList;
444     if (credentialList->getSize(credentialList) >= MAX_CREDENTIAL) {
445         LOG_ERROR("the number of credentials reaches the maximum");
446         return RESULT_EXCEED_LIMIT;
447     }
448 
449     ResultCode ret = UpdateEnrolledId(enrolledList, GetRealAuthTypeForEnrolledId(credentialInfo->authType));
450     if (ret != RESULT_SUCCESS) {
451         LOG_ERROR("update enrolledId failed");
452         return ret;
453     }
454     ret = GenerateDeduplicateUint64(g_userInfoList, &credentialInfo->credentialId, IsCredentialIdDuplicate);
455     if (ret != RESULT_SUCCESS) {
456         LOG_ERROR("GenerateDeduplicateUint64 failed");
457         return ret;
458     }
459     if (credentialInfo->authType == DEFAULT_AUTH_TYPE) {
460         bool isRemoved = false;
461         RemoveCachePin(user, &isRemoved);
462     }
463     CredentialInfoHal *credential = Malloc(sizeof(CredentialInfoHal));
464     if (credential == NULL) {
465         LOG_ERROR("credential malloc failed");
466         return RESULT_NO_MEMORY;
467     }
468     if (memcpy_s(credential, sizeof(CredentialInfoHal), credentialInfo, sizeof(CredentialInfoHal)) != EOK) {
469         LOG_ERROR("credential copy failed");
470         Free(credential);
471         return RESULT_BAD_COPY;
472     }
473     credential->enrolledSysTime = GetReeTime();
474     ret = credentialList->insert(credentialList, credential);
475     if (ret != RESULT_SUCCESS) {
476         LOG_ERROR("insert credential failed");
477         Free(credential);
478     }
479     return ret;
480 }
481 
AddUser(int32_t userId, CredentialInfoHal *credentialInfo, int32_t userType)482 IAM_STATIC ResultCode AddUser(int32_t userId, CredentialInfoHal *credentialInfo, int32_t userType)
483 {
484     if (g_userInfoList == NULL) {
485         LOG_ERROR("please init");
486         return RESULT_NEED_INIT;
487     }
488     if (g_userInfoList->getSize(g_userInfoList) >= MAX_USER) {
489         LOG_ERROR("the number of users reaches the maximum");
490         return RESULT_EXCEED_LIMIT;
491     }
492 
493     UserInfo *user = QueryUserInfo(userId);
494     if (user != NULL) {
495         LOG_ERROR("Please check pin");
496         return RESULT_BAD_PARAM;
497     }
498 
499     user = CreateUser(userId, userType);
500     if (user == NULL) {
501         LOG_ERROR("create user failed");
502         return RESULT_UNKNOWN;
503     }
504     LOG_INFO("user userType %{public}d", user->userType);
505     ResultCode ret = AddCredentialToUser(user, credentialInfo);
506     if (ret != RESULT_SUCCESS) {
507         LOG_ERROR("add credential to user failed");
508         goto FAIL;
509     }
510 
511     ret = g_userInfoList->insert(g_userInfoList, user);
512     if (ret != RESULT_SUCCESS) {
513         LOG_ERROR("insert failed");
514         goto FAIL;
515     }
516     return ret;
517 
518 FAIL:
519     DestroyUserInfoNode(user);
520     return ret;
521 }
522 
AddCredentialInfo(int32_t userId, CredentialInfoHal *credentialInfo, int32_t userType)523 ResultCode AddCredentialInfo(int32_t userId, CredentialInfoHal *credentialInfo, int32_t userType)
524 {
525     if ((credentialInfo == NULL) || (credentialInfo->authType == DEFAULT_AUTH_TYPE)) {
526         LOG_ERROR("credentialInfo is invalid");
527         return RESULT_BAD_PARAM;
528     }
529     UserInfo *user = QueryUserInfo(userId);
530     if (user == NULL && credentialInfo->authType == PIN_AUTH) {
531         ResultCode ret = AddUser(userId, credentialInfo, userType);
532         if (ret != RESULT_SUCCESS) {
533             LOG_ERROR("add user failed");
534             return ret;
535         }
536         ret = UpdateFileInfo(g_userInfoList);
537         if (ret != RESULT_SUCCESS) {
538             LOG_ERROR("updateFileInfo failed");
539         }
540         return ret;
541     }
542     if (user == NULL) {
543         LOG_ERROR("user is null");
544         return RESULT_BAD_PARAM;
545     }
546     if (credentialInfo->authType == PIN_AUTH) {
547         CredentialCondition condition = {};
548         SetCredentialConditionAuthType(&condition, PIN_AUTH);
549         SetCredentialConditionUserId(&condition, userId);
550         LinkedList *credList = QueryCredentialLimit(&condition);
551         if (credList == NULL) {
552             LOG_ERROR("query credential failed");
553             return RESULT_UNKNOWN;
554         }
555         if (credList->getSize(credList) != 0) {
556             LOG_INFO("cache pin");
557             // add for reliable pin updates
558             credentialInfo->authType = DEFAULT_AUTH_TYPE;
559         }
560         DestroyLinkedList(credList);
561     }
562     ResultCode ret = AddCredentialToUser(user, credentialInfo);
563     if (ret != RESULT_SUCCESS) {
564         LOG_ERROR("add credential to user failed");
565         return ret;
566     }
567     ret = UpdateFileInfo(g_userInfoList);
568     if (ret != RESULT_SUCCESS) {
569         LOG_ERROR("updateFileInfo failed");
570     }
571     return ret;
572 }
573 
MatchCredentialById(const void *data, const void *condition)574 IAM_STATIC bool MatchCredentialById(const void *data, const void *condition)
575 {
576     if (data == NULL || condition == NULL) {
577         return false;
578     }
579     const CredentialInfoHal *credentialInfo = (const CredentialInfoHal *)data;
580     uint64_t credentialId = *(const uint64_t *)condition;
581     if (credentialInfo->credentialId == credentialId) {
582         return true;
583     }
584     return false;
585 }
586 
MatchEnrolledInfoByType(const void *data, const void *condition)587 IAM_STATIC bool MatchEnrolledInfoByType(const void *data, const void *condition)
588 {
589     if (data == NULL || condition == NULL) {
590         return false;
591     }
592     const EnrolledInfoHal *enrolledInfo = (const EnrolledInfoHal *)data;
593     uint32_t authType = *(const uint32_t *)condition;
594     if (enrolledInfo->authType == authType) {
595         return true;
596     }
597     return false;
598 }
599 
RemoveCachePin(UserInfo *user, bool *isRemoved)600 IAM_STATIC void RemoveCachePin(UserInfo *user, bool *isRemoved)
601 {
602     LOG_INFO("RemoveCachePin start");
603     LinkedListNode *temp = user->credentialInfoList->head;
604     CredentialInfoHal *credentialInfoCache = NULL;
605     while (temp != NULL) {
606         CredentialInfoHal *nodeData = (CredentialInfoHal*)temp->data;
607         if (nodeData != NULL && nodeData->authType == DEFAULT_AUTH_TYPE) {
608             credentialInfoCache = nodeData;
609             break;
610         }
611         temp = temp->next;
612     }
613     if (credentialInfoCache == NULL) {
614         LOG_INFO("RemoveCachePin no cache pin");
615         *isRemoved = false;
616         return;
617     }
618     uint64_t credentialId = credentialInfoCache->credentialId;
619     ResultCode ret = (user->credentialInfoList)->remove(
620         user->credentialInfoList, &credentialId, MatchCredentialById, true);
621     if (ret != RESULT_SUCCESS) {
622         LOG_ERROR("remove credential failed");
623         *isRemoved = false;
624         return;
625     }
626     LOG_ERROR("remove credential success");
627     *isRemoved = true;
628 }
629 
ClearCachePin(int32_t userId)630 void ClearCachePin(int32_t userId)
631 {
632     LOG_INFO("ClearCachePin start");
633     UserInfo *user = QueryUserInfo(userId);
634     if (user == NULL) {
635         LOG_ERROR("can't find this user");
636         return;
637     }
638 
639     bool isRemoved = false;
640     RemoveCachePin(user, &isRemoved);
641     if (isRemoved && UpdateFileInfo(g_userInfoList) != RESULT_SUCCESS) {
642         LOG_ERROR("ClearCachePin save fail");
643         return;
644     }
645 }
646 
SwitchSubType(UserInfo *user)647 IAM_STATIC void SwitchSubType(UserInfo *user)
648 {
649     uint64_t tmpSubType = user->pinSubType;
650     user->pinSubType = user->cachePinSubType;
651     user->cachePinSubType = tmpSubType;
652 }
653 
654 // add for reliable pin updates
DeletePinCredentialInfo(UserInfo *user)655 IAM_STATIC ResultCode DeletePinCredentialInfo(UserInfo *user)
656 {
657     LOG_INFO("DeletePinCredentialInfo start");
658     LinkedListNode *temp = user->credentialInfoList->head;
659     CredentialInfoHal *credentialInfoOld = NULL;
660     CredentialInfoHal *credentialInfoCache = NULL;
661     while (temp != NULL) {
662         CredentialInfoHal *nodeData = (CredentialInfoHal*)temp->data;
663         if (nodeData != NULL && nodeData->authType == PIN_AUTH) {
664             credentialInfoOld = nodeData;
665         }
666         if (nodeData != NULL && nodeData->authType == DEFAULT_AUTH_TYPE) {
667             credentialInfoCache = nodeData;
668         }
669         temp = temp->next;
670     }
671     if (credentialInfoOld == NULL || credentialInfoCache == NULL) {
672         LOG_ERROR("no cache pin exist");
673         return RESULT_GENERAL_ERROR;
674     }
675     credentialInfoOld->authType = DEFAULT_AUTH_TYPE;
676     credentialInfoCache->authType = PIN_AUTH;
677     SwitchSubType(user);
678     ResultCode result = UpdateFileInfo(g_userInfoList);
679     if (result == RESULT_SUCCESS) {
680         LOG_INFO("switch cache pin success");
681         ClearCachePin(user->userId);
682         return result;
683     }
684     LOG_ERROR("switch cache pin fail");
685     credentialInfoOld->authType = PIN_AUTH;
686     credentialInfoCache->authType = DEFAULT_AUTH_TYPE;
687     SwitchSubType(user);
688     return RESULT_GENERAL_ERROR;
689 }
690 
DeleteCredentialInfo(int32_t userId, uint64_t credentialId, CredentialInfoHal *credentialInfo)691 ResultCode DeleteCredentialInfo(int32_t userId, uint64_t credentialId, CredentialInfoHal *credentialInfo)
692 {
693     if (credentialInfo == NULL) {
694         LOG_ERROR("param is invalid");
695         return RESULT_BAD_PARAM;
696     }
697 
698     UserInfo *user = QueryUserInfo(userId);
699     if (user == NULL) {
700         LOG_ERROR("can't find this user");
701         return RESULT_BAD_PARAM;
702     }
703 
704     LinkedList *credentialList = user->credentialInfoList;
705     CredentialInfoHal *credentialQuery = QueryCredentialById(credentialId, credentialList);
706     if (credentialQuery == NULL) {
707         LOG_ERROR("credentialQuery is null");
708         return RESULT_UNKNOWN;
709     }
710     if (memcpy_s(credentialInfo, sizeof(CredentialInfoHal), credentialQuery, sizeof(CredentialInfoHal)) != EOK) {
711         LOG_ERROR("copy failed");
712         return RESULT_BAD_COPY;
713     }
714     if (credentialInfo->authType == PIN_AUTH) {
715         return DeletePinCredentialInfo(user);
716     }
717     ResultCode ret = credentialList->remove(credentialList, &credentialId, MatchCredentialById, true);
718     if (ret != RESULT_SUCCESS) {
719         LOG_ERROR("remove credential failed");
720         return ret;
721     }
722     if (credentialInfo->authType == DEFAULT_AUTH_TYPE) {
723         return UpdateFileInfo(g_userInfoList);
724     }
725     credentialQuery = QueryCredentialByAuthType(credentialInfo->authType, credentialList);
726     if (credentialQuery != NULL) {
727         return UpdateFileInfo(g_userInfoList);
728     }
729 
730     LinkedList *enrolledInfoList = user->enrolledInfoList;
731     if (enrolledInfoList == NULL) {
732         LOG_ERROR("enrolledInfoList is null");
733         return RESULT_UNKNOWN;
734     }
735     ret = enrolledInfoList->remove(enrolledInfoList, &credentialInfo->authType, MatchEnrolledInfoByType, true);
736     if (ret != RESULT_SUCCESS) {
737         LOG_ERROR("remove enrolledInfo failed");
738         return ret;
739     }
740 
741     return UpdateFileInfo(g_userInfoList);
742 }
743 
QueryCredentialById(uint64_t credentialId, LinkedList *credentialList)744 IAM_STATIC CredentialInfoHal *QueryCredentialById(uint64_t credentialId, LinkedList *credentialList)
745 {
746     if (credentialList == NULL) {
747         return NULL;
748     }
749     LinkedListNode *temp = credentialList->head;
750     CredentialInfoHal *credentialInfo = NULL;
751     while (temp != NULL) {
752         CredentialInfoHal *nodeData = (CredentialInfoHal *)temp->data;
753         if (nodeData != NULL && nodeData->credentialId == credentialId) {
754             credentialInfo = nodeData;
755             break;
756         }
757         temp = temp->next;
758     }
759     return credentialInfo;
760 }
761 
QueryCredentialByAuthType(uint32_t authType, LinkedList *credentialList)762 IAM_STATIC CredentialInfoHal *QueryCredentialByAuthType(uint32_t authType, LinkedList *credentialList)
763 {
764     if (credentialList == NULL) {
765         return NULL;
766     }
767     LinkedListNode *temp = credentialList->head;
768     CredentialInfoHal *credentialInfo = NULL;
769     while (temp != NULL) {
770         CredentialInfoHal *nodeData = (CredentialInfoHal*)temp->data;
771         if (nodeData != NULL && nodeData->authType == authType) {
772             credentialInfo = nodeData;
773             break;
774         }
775         temp = temp->next;
776     }
777     return credentialInfo;
778 }
779 
780 // do not cotain cache pin credential
IsCredMatch(const CredentialCondition *limit, const CredentialInfoHal *credentialInfo)781 IAM_STATIC bool IsCredMatch(const CredentialCondition *limit, const CredentialInfoHal *credentialInfo)
782 {
783     if ((limit->conditionFactor & CREDENTIAL_CONDITION_CREDENTIAL_ID) != 0 &&
784         limit->credentialId != credentialInfo->credentialId) {
785         return false;
786     }
787     if (credentialInfo->authType == DEFAULT_AUTH_TYPE) {
788         if ((limit->conditionFactor & CREDENTIAL_CONDITION_NEED_CACHE_PIN) == 0) {
789             return false;
790         }
791     } else {
792         if ((limit->conditionFactor & CREDENTIAL_CONDITION_AUTH_TYPE) != 0 &&
793             limit->authType != credentialInfo->authType) {
794             return false;
795         }
796     }
797     if ((limit->conditionFactor & CREDENTIAL_CONDITION_TEMPLATE_ID) != 0 &&
798         limit->templateId != credentialInfo->templateId) {
799         return false;
800     }
801     if ((limit->conditionFactor & CREDENTIAL_CONDITION_SENSOR_HINT) != 0 &&
802         limit->executorSensorHint != INVALID_SENSOR_HINT &&
803         limit->executorSensorHint != credentialInfo->executorSensorHint) {
804         return false;
805     }
806     if ((limit->conditionFactor & CREDENTIAL_CONDITION_EXECUTOR_MATCHER) != 0 &&
807         limit->executorMatcher != credentialInfo->executorMatcher) {
808         return false;
809     }
810     return true;
811 }
812 
IsUserMatch(const CredentialCondition *limit, const UserInfo *user)813 IAM_STATIC bool IsUserMatch(const CredentialCondition *limit, const UserInfo *user)
814 {
815     if ((limit->conditionFactor & CREDENTIAL_CONDITION_USER_ID) != 0 && limit->userId != user->userId) {
816         return false;
817     }
818     return true;
819 }
820 
821 // do not cotain cache pin credential
TraverseCredentialList(const CredentialCondition *limit, const LinkedList *credentialList, LinkedList *credListGet)822 IAM_STATIC ResultCode TraverseCredentialList(const CredentialCondition *limit, const LinkedList *credentialList,
823     LinkedList *credListGet)
824 {
825     if (credentialList == NULL) {
826         LOG_ERROR("credentialList is null");
827         return RESULT_GENERAL_ERROR;
828     }
829     LinkedListNode *temp = credentialList->head;
830     while (temp != NULL) {
831         CredentialInfoHal *nodeData = (CredentialInfoHal*)temp->data;
832         if (nodeData == NULL) {
833             LOG_ERROR("nodeData is null");
834             return RESULT_UNKNOWN;
835         }
836         if (!IsCredMatch(limit, nodeData)) {
837             temp = temp->next;
838             continue;
839         }
840         CredentialInfoHal *copy = (CredentialInfoHal *)Malloc(sizeof(CredentialInfoHal));
841         if (copy == NULL) {
842             LOG_ERROR("copy malloc failed");
843             return RESULT_NO_MEMORY;
844         }
845         *copy = *nodeData;
846         ResultCode ret = credListGet->insert(credListGet, copy);
847         if (ret != RESULT_SUCCESS) {
848             LOG_ERROR("insert failed");
849             Free(copy);
850             return ret;
851         }
852         temp = temp->next;
853     }
854     return RESULT_SUCCESS;
855 }
856 
857 // do not cotain cache pin credential
QueryCredentialLimit(const CredentialCondition *limit)858 LinkedList *QueryCredentialLimit(const CredentialCondition *limit)
859 {
860     if (limit == NULL) {
861         LOG_ERROR("limit is null");
862         return NULL;
863     }
864     if (g_userInfoList == NULL) {
865         LOG_ERROR("g_userInfoList is null");
866         return NULL;
867     }
868     LinkedList *credList = CreateLinkedList(DestroyCredentialNode);
869     if (credList == NULL) {
870         LOG_ERROR("credList is null");
871         return NULL;
872     }
873     LinkedListNode *temp = g_userInfoList->head;
874     while (temp != NULL) {
875         UserInfo *user = (UserInfo *)temp->data;
876         if (user == NULL) {
877             LOG_ERROR("node data is null");
878             DestroyLinkedList(credList);
879             return NULL;
880         }
881         if (IsUserMatch(limit, user)) {
882             ResultCode ret = TraverseCredentialList(limit, user->credentialInfoList, credList);
883             if (ret != RESULT_SUCCESS) {
884                 LOG_ERROR("TraverseCredentialList failed");
885                 DestroyLinkedList(credList);
886                 return NULL;
887             }
888         }
889         temp = temp->next;
890     }
891     return credList;
892 }
893 
QueryCredentialUserId(uint64_t credentialId, int32_t *userId)894 ResultCode QueryCredentialUserId(uint64_t credentialId, int32_t *userId)
895 {
896     if (userId == NULL) {
897         LOG_ERROR("userId is null");
898         return RESULT_BAD_PARAM;
899     }
900     if (g_userInfoList == NULL) {
901         LOG_ERROR("g_userInfoList is null");
902         return RESULT_NEED_INIT;
903     }
904     LinkedList *credList = CreateLinkedList(DestroyCredentialNode);
905     if (credList == NULL) {
906         LOG_ERROR("credList is null");
907         return RESULT_NO_MEMORY;
908     }
909     LinkedListNode *temp = g_userInfoList->head;
910     CredentialCondition condition = {};
911     SetCredentialConditionCredentialId(&condition, credentialId);
912     while (temp != NULL) {
913         UserInfo *user = (UserInfo *)temp->data;
914         if (user == NULL) {
915             LOG_ERROR("user is null");
916             DestroyLinkedList(credList);
917             return RESULT_UNKNOWN;
918         }
919         ResultCode ret = TraverseCredentialList(&condition, user->credentialInfoList, credList);
920         if (ret != RESULT_SUCCESS) {
921             LOG_ERROR("TraverseCredentialList failed");
922             DestroyLinkedList(credList);
923             return RESULT_UNKNOWN;
924         }
925         if (credList->getSize(credList) != 0) {
926             DestroyLinkedList(credList);
927             *userId = user->userId;
928             return RESULT_SUCCESS;
929         }
930         temp = temp->next;
931     }
932     DestroyLinkedList(credList);
933     LOG_ERROR("can't find this credential");
934     return RESULT_NOT_FOUND;
935 }
936 
SetPinSubType(int32_t userId, uint64_t pinSubType)937 ResultCode SetPinSubType(int32_t userId, uint64_t pinSubType)
938 {
939     UserInfo *user = QueryUserInfo(userId);
940     if (user == NULL) {
941         LOG_ERROR("can't find this user");
942         return RESULT_NOT_FOUND;
943     }
944     user->pinSubType = pinSubType;
945     return RESULT_SUCCESS;
946 }
947 
GetPinSubType(int32_t userId, uint64_t *pinSubType)948 ResultCode GetPinSubType(int32_t userId, uint64_t *pinSubType)
949 {
950     if (pinSubType == NULL) {
951         LOG_ERROR("pinSubType is null");
952         return RESULT_BAD_PARAM;
953     }
954     UserInfo *user = QueryUserInfo(userId);
955     if (user == NULL) {
956         LOG_ERROR("can't find this user");
957         return RESULT_NOT_FOUND;
958     }
959     *pinSubType = user->pinSubType;
960     return RESULT_SUCCESS;
961 }
962 
SetCredentialConditionCredentialId(CredentialCondition *condition, uint64_t credentialId)963 void SetCredentialConditionCredentialId(CredentialCondition *condition, uint64_t credentialId)
964 {
965     if (condition == NULL) {
966         LOG_ERROR("condition is null");
967         return;
968     }
969     condition->credentialId = credentialId;
970     condition->conditionFactor |= CREDENTIAL_CONDITION_CREDENTIAL_ID;
971 }
972 
SetCredentialConditionTemplateId(CredentialCondition *condition, uint64_t templateId)973 void SetCredentialConditionTemplateId(CredentialCondition *condition, uint64_t templateId)
974 {
975     if (condition == NULL) {
976         LOG_ERROR("condition is null");
977         return;
978     }
979     condition->templateId = templateId;
980     condition->conditionFactor |= CREDENTIAL_CONDITION_TEMPLATE_ID;
981 }
982 
SetCredentialConditionAuthType(CredentialCondition *condition, uint32_t authType)983 void SetCredentialConditionAuthType(CredentialCondition *condition, uint32_t authType)
984 {
985     if (condition == NULL) {
986         LOG_ERROR("condition is null");
987         return;
988     }
989     condition->authType = authType;
990     condition->conditionFactor |= CREDENTIAL_CONDITION_AUTH_TYPE;
991 }
992 
SetCredentialConditionExecutorSensorHint(CredentialCondition *condition, uint32_t executorSensorHint)993 void SetCredentialConditionExecutorSensorHint(CredentialCondition *condition, uint32_t executorSensorHint)
994 {
995     if (condition == NULL) {
996         LOG_ERROR("condition is null");
997         return;
998     }
999     condition->executorSensorHint = executorSensorHint;
1000     condition->conditionFactor |= CREDENTIAL_CONDITION_SENSOR_HINT;
1001 }
1002 
SetCredentialConditionExecutorMatcher(CredentialCondition *condition, uint32_t executorMatcher)1003 void SetCredentialConditionExecutorMatcher(CredentialCondition *condition, uint32_t executorMatcher)
1004 {
1005     if (condition == NULL) {
1006         LOG_ERROR("condition is null");
1007         return;
1008     }
1009     condition->executorMatcher = executorMatcher;
1010     condition->conditionFactor |= CREDENTIAL_CONDITION_EXECUTOR_MATCHER;
1011 }
1012 
SetCredentialConditionUserId(CredentialCondition *condition, int32_t userId)1013 void SetCredentialConditionUserId(CredentialCondition *condition, int32_t userId)
1014 {
1015     if (condition == NULL) {
1016         LOG_ERROR("condition is null");
1017         return;
1018     }
1019     condition->userId = userId;
1020     condition->conditionFactor |= CREDENTIAL_CONDITION_USER_ID;
1021 }
1022 
SetCredentiaConditionNeedCachePin(CredentialCondition *condition)1023 void SetCredentiaConditionNeedCachePin(CredentialCondition *condition)
1024 {
1025     if (condition == NULL) {
1026         LOG_ERROR("condition is null");
1027         return;
1028     }
1029     condition->conditionFactor |= CREDENTIAL_CONDITION_NEED_CACHE_PIN;
1030 }
1031 
IsUserValid(UserInfo *user)1032 IAM_STATIC bool IsUserValid(UserInfo *user)
1033 {
1034     LinkedList *credentialInfoList = user->credentialInfoList;
1035     CredentialInfoHal *pinCredential = QueryCredentialByAuthType(PIN_AUTH, credentialInfoList);
1036     if (pinCredential == NULL) {
1037         LOG_INFO("user is invalid, userId: %{public}d", user->userId);
1038         return false;
1039     }
1040     return true;
1041 }
1042 
GetInvalidUser(int32_t *invalidUserId, uint32_t maxUserCount, uint32_t *userCount, bool *cachePinRemoved)1043 IAM_STATIC ResultCode GetInvalidUser(int32_t *invalidUserId, uint32_t maxUserCount, uint32_t *userCount,
1044     bool *cachePinRemoved)
1045 {
1046     LOG_INFO("get invalid user start");
1047     if (g_userInfoList == NULL) {
1048         LOG_ERROR("g_userInfoList is null");
1049         return RESULT_GENERAL_ERROR;
1050     }
1051 
1052     LinkedListIterator *iterator = g_userInfoList->createIterator(g_userInfoList);
1053     if (iterator == NULL) {
1054         LOG_ERROR("create iterator failed");
1055         return RESULT_NO_MEMORY;
1056     }
1057 
1058     UserInfo *user = NULL;
1059     *userCount = 0;
1060     while (iterator->hasNext(iterator)) {
1061         user = (UserInfo *)iterator->next(iterator);
1062         if (user == NULL) {
1063             LOG_ERROR("userinfo list node is null, please check");
1064             continue;
1065         }
1066 
1067         if (*userCount >= maxUserCount) {
1068             LOG_ERROR("too many users");
1069             break;
1070         }
1071 
1072         if (!IsUserValid(user)) {
1073             invalidUserId[*userCount] = user->userId;
1074             (*userCount)++;
1075             continue;
1076         }
1077 
1078         bool isRemoved = false;
1079         RemoveCachePin(user, &isRemoved);
1080         if (isRemoved) {
1081             *cachePinRemoved = true;
1082         }
1083     }
1084 
1085     g_userInfoList->destroyIterator(iterator);
1086     return RESULT_SUCCESS;
1087 }
1088 
ClearInvalidData(void)1089 IAM_STATIC ResultCode ClearInvalidData(void)
1090 {
1091     LOG_INFO("clear invalid user start");
1092     int32_t invalidUserId[MAX_USER] = {0};
1093     uint32_t userCount = 0;
1094     bool cachePinRemoved = false;
1095     if (GetInvalidUser(invalidUserId, MAX_USER, &userCount, &cachePinRemoved) != RESULT_SUCCESS) {
1096         LOG_ERROR("GetInvalidUser fail");
1097         return RESULT_GENERAL_ERROR;
1098     }
1099     ResultCode ret = RESULT_SUCCESS;
1100     for (uint32_t i = 0; i < userCount; ++i) {
1101         ret = DeleteUser(invalidUserId[i]);
1102         if (ret != RESULT_SUCCESS) {
1103             LOG_ERROR("delete invalid user fail, userId: %{public}d, ret: %{public}d", invalidUserId[i], ret);
1104             return ret;
1105         }
1106         LOG_INFO("delete invalid user success, userId: %{public}d, ret: %{public}d", invalidUserId[i], ret);
1107     }
1108 
1109     if ((userCount != 0) || cachePinRemoved) {
1110         ret = UpdateFileInfo(g_userInfoList);
1111         if (ret != RESULT_SUCCESS) {
1112             LOG_ERROR("UpdateFileInfo fail, ret: %{public}d", ret);
1113             return ret;
1114         }
1115     }
1116     return RESULT_SUCCESS;
1117 }
1118 
GetAllExtUserInfo(UserInfoResult *userInfos, uint32_t userInfoLen, uint32_t *userInfocount)1119 ResultCode GetAllExtUserInfo(UserInfoResult *userInfos, uint32_t userInfoLen, uint32_t *userInfocount)
1120 {
1121     LOG_INFO("get all user info start");
1122     if (userInfos == NULL || userInfocount == NULL || g_userInfoList == NULL) {
1123         LOG_ERROR("param is null");
1124         return RESULT_BAD_PARAM;
1125     }
1126 
1127     LinkedListIterator *iterator = g_userInfoList->createIterator(g_userInfoList);
1128     if (iterator == NULL) {
1129         LOG_ERROR("create iterator failed");
1130         return RESULT_NO_MEMORY;
1131     }
1132 
1133     UserInfo *user = NULL;
1134     EnrolledInfoHal *enrolledInfoHal = NULL;
1135     *userInfocount = 0;
1136     while (iterator->hasNext(iterator)) {
1137         user = (UserInfo *)iterator->next(iterator);
1138         if (user == NULL) {
1139             LOG_ERROR("userinfo list node is null, please check");
1140             continue;
1141         }
1142 
1143         if (*userInfocount >= userInfoLen) {
1144             LOG_ERROR("too many users");
1145             goto ERROR;
1146         }
1147 
1148         userInfos[*userInfocount].userId = user->userId;
1149         userInfos[*userInfocount].secUid = user->secUid;
1150         userInfos[*userInfocount].pinSubType = (uint32_t)user->pinSubType;
1151 
1152         ResultCode ret = GetAllEnrolledInfoFromUser(user, &enrolledInfoHal, &(userInfos[*userInfocount].enrollNum));
1153         if (ret != RESULT_SUCCESS) {
1154             LOG_ERROR("get enrolled info fail");
1155             goto ERROR;
1156         }
1157         if (userInfos[*userInfocount].enrollNum > MAX_ENROLL_OUTPUT) {
1158             LOG_ERROR("too many elements");
1159             free(enrolledInfoHal);
1160             goto ERROR;
1161         }
1162 
1163         for (uint32_t i = 0; i < userInfos[*userInfocount].enrollNum; i++) {
1164             userInfos[*userInfocount].enrolledInfo[i].authType = enrolledInfoHal[i].authType;
1165             userInfos[*userInfocount].enrolledInfo[i].enrolledId = enrolledInfoHal[i].enrolledId;
1166         }
1167 
1168         free(enrolledInfoHal);
1169         (*userInfocount)++;
1170     }
1171 
1172     g_userInfoList->destroyIterator(iterator);
1173     return RESULT_SUCCESS;
1174 
1175 ERROR:
1176     g_userInfoList->destroyIterator(iterator);
1177     return RESULT_GENERAL_ERROR;
1178 }
1179 
GetEnrolledState(int32_t userId, uint32_t authType, EnrolledStateHal *enrolledStateHal)1180 ResultCode GetEnrolledState(int32_t userId, uint32_t authType, EnrolledStateHal *enrolledStateHal)
1181 {
1182     LOG_INFO("get enrolled id info start, userId:%{public}d, authType:%{public}d", userId, authType);
1183 
1184     UserInfo *user = QueryUserInfo(userId);
1185     if (user == NULL) {
1186         LOG_ERROR("user is null");
1187         return RESULT_NOT_ENROLLED;
1188     }
1189     if (user->credentialInfoList == NULL) {
1190         LOG_ERROR("credentialInfoList is null");
1191         return RESULT_NOT_ENROLLED;
1192     }
1193 
1194     uint16_t credentialCount = 0;
1195     LinkedListNode *credentialInfoTemp = user->credentialInfoList->head;
1196     while (credentialInfoTemp != NULL) {
1197         CredentialInfoHal *nodeInfo = credentialInfoTemp->data;
1198         if (nodeInfo != NULL && nodeInfo->authType == authType) {
1199             ++credentialCount;
1200         }
1201         credentialInfoTemp = credentialInfoTemp->next;
1202     }
1203     if (credentialCount == 0) {
1204         LOG_ERROR("not enrolled");
1205         return RESULT_NOT_ENROLLED;
1206     }
1207     enrolledStateHal->credentialCount = credentialCount;
1208     if (user->enrolledInfoList == NULL) {
1209         LOG_ERROR("enrolledInfoList is null");
1210         return RESULT_NOT_ENROLLED;
1211     }
1212     LinkedListNode *enrolledInfoTemp = user->enrolledInfoList->head;
1213     while (enrolledInfoTemp != NULL) {
1214         EnrolledInfoHal *nodeInfo = enrolledInfoTemp->data;
1215         if (nodeInfo != NULL && nodeInfo->authType == authType) {
1216             enrolledStateHal->credentialDigest = nodeInfo->enrolledId;
1217             break;
1218         }
1219         enrolledInfoTemp = enrolledInfoTemp->next;
1220     }
1221     return RESULT_SUCCESS;
1222 }
1223 
UpdateGlobalConfigArray(GlobalConfigParamHal *param, uint32_t authType)1224 IAM_STATIC ResultCode UpdateGlobalConfigArray(GlobalConfigParamHal *param, uint32_t authType)
1225 {
1226     uint32_t infoIndex = 0;
1227     for (infoIndex = 0; infoIndex < g_globalConfigInfoNum; infoIndex++) {
1228         if (g_globalConfigArray[infoIndex].type == param->type &&
1229             g_globalConfigArray[infoIndex].authType == authType) {
1230             LOG_INFO("globalConfig is already exist, type:%{public}d, authType:%{public}u", param->type, authType);
1231             break;
1232         }
1233     }
1234     if (infoIndex >= MAX_GLOBAL_CONFIG_NUM) {
1235         LOG_ERROR("globalConfigArray is exceed limit");
1236         return RESULT_EXCEED_LIMIT;
1237     }
1238     memset_s(&g_globalConfigArray[infoIndex], sizeof(GlobalConfigInfo), 0, sizeof(GlobalConfigInfo));
1239 
1240     switch (param->type) {
1241         case PIN_EXPIRED_PERIOD:
1242             if (authType != PIN_AUTH) {
1243                 LOG_ERROR("bad authType:%{public}u for PIN_EXPIRED_PERIOD", authType);
1244                 return RESULT_BAD_PARAM;
1245             }
1246             g_globalConfigArray[infoIndex].value.pinExpiredPeriod = param->value.pinExpiredPeriod;
1247             break;
1248         case ENABLE_STATUS:
1249             g_globalConfigArray[infoIndex].value.enableStatus = param->value.enableStatus;
1250             break;
1251         default:
1252             LOG_ERROR("globalConfigType not support, type:%{public}d.", param->type);
1253             return RESULT_BAD_PARAM;
1254     }
1255     g_globalConfigArray[infoIndex].type = param->type;
1256     g_globalConfigArray[infoIndex].authType = authType;
1257     g_globalConfigArray[infoIndex].userIdNum = param->userIdNum;
1258     for (uint32_t i = 0; i < param->userIdNum; i++) {
1259         g_globalConfigArray[infoIndex].userIds[i] = param->userIds[i];
1260     }
1261     if (infoIndex == g_globalConfigInfoNum) {
1262         g_globalConfigInfoNum++;
1263     }
1264     return RESULT_SUCCESS;
1265 }
1266 
CheckAuthType(uint32_t authType)1267 IAM_STATIC bool CheckAuthType(uint32_t authType)
1268 {
1269     if (authType != PIN_AUTH && authType != FACE_AUTH && authType != FINGER_AUTH && authType != RECOVERY_KEY) {
1270         LOG_ERROR("bad authType %{public}u", authType);
1271         return false;
1272     }
1273     return true;
1274 }
1275 
SaveGlobalConfigParam(GlobalConfigParamHal *param)1276 ResultCode SaveGlobalConfigParam(GlobalConfigParamHal *param)
1277 {
1278     if (param == NULL || param->userIdNum > MAX_USER || param->authTypeNum > MAX_AUTH_TYPE_LEN ||
1279         param->authTypeNum == 0) {
1280         LOG_ERROR("bad param");
1281         return RESULT_BAD_PARAM;
1282     }
1283     for (uint32_t i = 0; i < param->authTypeNum; i++) {
1284         if (!CheckAuthType(param->authTypes[i])) {
1285             LOG_ERROR("bad authType %{public}u", param->authTypes[i]);
1286             return RESULT_BAD_PARAM;
1287         }
1288         ResultCode ret = UpdateGlobalConfigArray(param, param->authTypes[i]);
1289         if (ret != RESULT_SUCCESS) {
1290             return ret;
1291         }
1292     }
1293 
1294     return UpdateGlobalConfigFile(g_globalConfigArray, g_globalConfigInfoNum);
1295 }
1296 
QueryPinCredential(int32_t userId, CredentialInfoHal *pinCredential)1297 IAM_STATIC ResultCode QueryPinCredential(int32_t userId, CredentialInfoHal *pinCredential)
1298 {
1299     if (pinCredential == NULL) {
1300         LOG_ERROR("no need to get pin credential");
1301         return RESULT_BAD_PARAM;
1302     }
1303     CredentialCondition condition = {};
1304     SetCredentialConditionUserId(&condition, userId);
1305     SetCredentialConditionAuthType(&condition, PIN_AUTH);
1306     LinkedList *credList = QueryCredentialLimit(&condition);
1307     if (credList == NULL || credList->getSize(credList) == 0) {
1308         LOG_ERROR("pin credential is null");
1309         DestroyLinkedList(credList);
1310         return RESULT_NOT_ENROLLED;
1311     }
1312     if (credList->head == NULL || credList->head->data == NULL) {
1313         LOG_ERROR("pin credList node is invalid");
1314         DestroyLinkedList(credList);
1315         return RESULT_GENERAL_ERROR;
1316     }
1317     if (memcpy_s(pinCredential, sizeof(CredentialInfoHal), credList->head->data, sizeof(CredentialInfoHal)) != EOK) {
1318         LOG_ERROR("credential copy fail");
1319         DestroyLinkedList(credList);
1320         return RESULT_GENERAL_ERROR;
1321     }
1322     DestroyLinkedList(credList);
1323     return RESULT_SUCCESS;
1324 }
1325 
GetPinExpiredInfo(int32_t userId, PinExpiredInfo *expiredInfo)1326 ResultCode GetPinExpiredInfo(int32_t userId, PinExpiredInfo *expiredInfo)
1327 {
1328     if (expiredInfo == NULL) {
1329         LOG_ERROR("bad param");
1330         return RESULT_BAD_PARAM;
1331     }
1332     (void)memset_s(expiredInfo, sizeof(PinExpiredInfo), 0, sizeof(PinExpiredInfo));
1333     for (uint32_t i = 0; i < g_globalConfigInfoNum; i++) {
1334         if (g_globalConfigArray[i].type == PIN_EXPIRED_PERIOD) {
1335             expiredInfo->pinExpiredPeriod = g_globalConfigArray[i].value.pinExpiredPeriod;
1336             break;
1337         }
1338     }
1339     if (expiredInfo->pinExpiredPeriod <= 0) {
1340         expiredInfo->pinExpiredPeriod = NO_CHECK_PIN_EXPIRED_PERIOD;
1341         LOG_INFO("no need check pinExpiredPeriod");
1342         return RESULT_SUCCESS;
1343     }
1344     CredentialInfoHal pinCredential = {};
1345     if (QueryPinCredential(userId, &pinCredential) != RESULT_SUCCESS) {
1346         LOG_INFO("not enrolled pin");
1347         return RESULT_NOT_ENROLLED;
1348     }
1349     expiredInfo->pinEnrolledSysTime = pinCredential.enrolledSysTime;
1350     return RESULT_SUCCESS;
1351 }
1352 
GetEnableStatus(int32_t userId, uint32_t authType)1353 bool GetEnableStatus(int32_t userId, uint32_t authType)
1354 {
1355     for (uint32_t infoIndex = 0; infoIndex < g_globalConfigInfoNum; infoIndex++) {
1356         if (g_globalConfigArray[infoIndex].type != ENABLE_STATUS ||
1357             g_globalConfigArray[infoIndex].authType != authType) {
1358             continue;
1359         }
1360         LOG_INFO("enableStatus:%{public}d authType:%{public}u", g_globalConfigArray[infoIndex].value.enableStatus,
1361             authType);
1362         if (userId == INVALID_USER_ID || g_globalConfigArray[infoIndex].userIdNum == 0) {
1363             return g_globalConfigArray[infoIndex].value.enableStatus;
1364         }
1365         for (uint32_t i = 0; i < g_globalConfigArray[infoIndex].userIdNum; i++) {
1366             if (userId == g_globalConfigArray[infoIndex].userIds[i]) {
1367                 return g_globalConfigArray[infoIndex].value.enableStatus;
1368             }
1369         }
1370         LOG_INFO("enableStatus is not set for userId:%{public}d", userId);
1371         return (!g_globalConfigArray[infoIndex].value.enableStatus);
1372     }
1373     return true;
1374 }
1375