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