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_file_manager.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_file.h"
21 #include "adaptor_log.h"
22 #include "adaptor_memory.h"
23 #include "adaptor_time.h"
24 #include "file_manager_utils.h"
25 #include "idm_common.h"
26 
27 #define IDM_USER_INFO "/data/service/el1/public/userauth/userinfo"
28 #define PRE_APPLY_LEN 2048
29 #define VERSION 0
30 
31 #ifdef IAM_TEST_ENABLE
32 #define IAM_STATIC
33 #else
34 #define IAM_STATIC static
35 #endif
36 
StreamWriteEnrolledInfo(Buffer *parcel, LinkedList *enrolledList)37 IAM_STATIC ResultCode StreamWriteEnrolledInfo(Buffer *parcel, LinkedList *enrolledList)
38 {
39     if (!IsBufferValid(parcel) || enrolledList == NULL) {
40         LOG_ERROR("invalid params");
41         return RESULT_BAD_PARAM;
42     }
43     uint32_t size = enrolledList->getSize(enrolledList);
44     ResultCode ret = StreamWrite(parcel, &size, sizeof(uint32_t));
45     if (ret != RESULT_SUCCESS) {
46         LOG_ERROR("StreamWrite failed");
47         return ret;
48     }
49     LinkedListNode *temp = enrolledList->head;
50     for (uint32_t i = 0; i < size; ++i) {
51         if (temp == NULL) {
52             LOG_ERROR("listSize is invalid");
53             return RESULT_BAD_PARAM;
54         }
55         if (StreamWrite(parcel, temp->data, sizeof(EnrolledInfoHal)) != RESULT_SUCCESS) {
56             LOG_ERROR("enrolledInfo streamWrite failed");
57             return RESULT_GENERAL_ERROR;
58         }
59         temp = temp->next;
60     }
61     return RESULT_SUCCESS;
62 }
63 
StreamWriteCredentialList(Buffer *parcel, LinkedList *credentialList)64 IAM_STATIC ResultCode StreamWriteCredentialList(Buffer *parcel, LinkedList *credentialList)
65 {
66     if (!IsBufferValid(parcel) || credentialList == NULL) {
67         LOG_ERROR("invalid params");
68         return RESULT_BAD_PARAM;
69     }
70     uint32_t size = credentialList->getSize(credentialList);
71     ResultCode ret = StreamWrite(parcel, &size, sizeof(uint32_t));
72     if (ret != RESULT_SUCCESS) {
73         LOG_ERROR("StreamWrite failed");
74         return ret;
75     }
76     LinkedListNode *temp = credentialList->head;
77     for (uint32_t i = 0; i < size; ++i) {
78         if (temp == NULL) {
79             LOG_ERROR("listSize is invalid");
80             return RESULT_BAD_PARAM;
81         }
82         if (StreamWrite(parcel, temp->data, sizeof(CredentialInfoHal)) != RESULT_SUCCESS) {
83             LOG_ERROR("credentialInfo streamWrite failed");
84             return RESULT_GENERAL_ERROR;
85         }
86         temp = temp->next;
87     }
88     return RESULT_SUCCESS;
89 }
90 
StreamWriteUserInfo(Buffer *parcel, UserInfo *userInfo)91 IAM_STATIC ResultCode StreamWriteUserInfo(Buffer *parcel, UserInfo *userInfo)
92 {
93     if (!IsBufferValid(parcel) || userInfo == NULL) {
94         LOG_ERROR("invalid params");
95         return RESULT_BAD_PARAM;
96     }
97     ResultCode result;
98     result = StreamWrite(parcel, &userInfo->userId, sizeof(int32_t));
99     if (result != RESULT_SUCCESS) {
100         LOG_ERROR("userId streamWrite failed");
101         return result;
102     }
103     LOG_INFO("userInfo userId %{public}d", userInfo->userId);
104     result = StreamWrite(parcel, &userInfo->userType, sizeof(int32_t));
105     if (result != RESULT_SUCCESS) {
106         LOG_ERROR("userType streamWrite failed");
107         return result;
108     }
109     LOG_INFO("userInfo userType %{public}d", userInfo->userType);
110     result = StreamWrite(parcel, &userInfo->secUid, sizeof(uint64_t));
111     if (result != RESULT_SUCCESS) {
112         LOG_ERROR("secUid streamWrite failed");
113         return result;
114     }
115     result = StreamWriteCredentialList(parcel, userInfo->credentialInfoList);
116     if (result != RESULT_SUCCESS) {
117         LOG_ERROR("credentialInfoList streamWrite failed");
118         return result;
119     }
120     result = StreamWriteEnrolledInfo(parcel, userInfo->enrolledInfoList);
121     if (result != RESULT_SUCCESS) {
122         LOG_ERROR("enrolledInfoList streamWrite failed");
123         return result;
124     }
125     return RESULT_SUCCESS;
126 }
127 
WriteUserInfo(LinkedList *userInfoList, Buffer *parcel)128 IAM_STATIC ResultCode WriteUserInfo(LinkedList *userInfoList, Buffer *parcel)
129 {
130     LinkedListNode *temp = userInfoList->head;
131     uint32_t size = userInfoList->getSize(userInfoList);
132     for (uint32_t i = 0; i < size; ++i) {
133         if (temp == NULL || temp->data == NULL) {
134             LOG_ERROR("temp is null");
135             return RESULT_NEED_INIT;
136         }
137         if (StreamWriteUserInfo(parcel, (UserInfo *)temp->data) != RESULT_SUCCESS) {
138             LOG_ERROR("StreamWriteUserInfo failed");
139             return RESULT_GENERAL_ERROR;
140         }
141         temp = temp->next;
142     }
143     return RESULT_SUCCESS;
144 }
145 
UpdateFileInfo(LinkedList *userInfoList)146 ResultCode UpdateFileInfo(LinkedList *userInfoList)
147 {
148     LOG_INFO("start");
149     if (userInfoList == NULL) {
150         LOG_ERROR("userInfo list is null");
151         return RESULT_BAD_PARAM;
152     }
153     Buffer *parcel = CreateBufferBySize(PRE_APPLY_LEN);
154     if (parcel == NULL) {
155         LOG_ERROR("parcel is null");
156         return RESULT_BAD_PARAM;
157     }
158     uint32_t version = VERSION;
159     ResultCode ret = StreamWrite(parcel, &version, sizeof(uint32_t));
160     if (ret != RESULT_SUCCESS) {
161         LOG_ERROR("StreamWrite failed");
162         goto EXIT;
163     }
164 
165     uint32_t size = userInfoList->getSize(userInfoList);
166     ret = StreamWrite(parcel, &size, sizeof(uint32_t));
167     if (ret != RESULT_SUCCESS) {
168         LOG_ERROR("StreamWrite failed");
169         goto EXIT;
170     }
171 
172     ret = WriteUserInfo(userInfoList, parcel);
173     if (ret != RESULT_SUCCESS) {
174         LOG_ERROR("WriteUserInfo failed");
175         goto EXIT;
176     }
177 
178     FileOperator *fileOperator = GetFileOperator(DEFAULT_FILE_OPERATOR);
179     if (!IsFileOperatorValid(fileOperator)) {
180         LOG_ERROR("invalid file operation");
181         ret = RESULT_BAD_WRITE;
182         goto EXIT;
183     }
184 
185     // This is for example only. Should be implemented in trusted environment.
186     ret = (ResultCode)fileOperator->writeFile(IDM_USER_INFO, parcel->buf, parcel->contentSize);
187     if (ret != RESULT_SUCCESS) {
188         LOG_ERROR("write file failed, %{public}u", parcel->contentSize);
189     }
190 
191 EXIT:
192     DestoryBuffer(parcel);
193     return ret;
194 }
195 
StreamReadCredentialList(Buffer *parcel, uint32_t *index, LinkedList *credentialList)196 IAM_STATIC ResultCode StreamReadCredentialList(Buffer *parcel, uint32_t *index, LinkedList *credentialList)
197 {
198     if (!IsBufferValid(parcel) || credentialList == NULL) {
199         LOG_ERROR("invalid params");
200         return RESULT_BAD_PARAM;
201     }
202     uint32_t credentialNum;
203     ResultCode result = StreamRead(parcel, index, &credentialNum, sizeof(uint32_t));
204     if (result != RESULT_SUCCESS) {
205         LOG_ERROR("stream read failed");
206         return RESULT_BAD_READ;
207     }
208     if (credentialNum > MAX_CREDENTIAL) {
209         LOG_ERROR("Bad credential num");
210         return RESULT_BAD_READ;
211     }
212     for (uint32_t i = 0; i < credentialNum; ++i) {
213         CredentialInfoHal *credentialInfo = Malloc(sizeof(CredentialInfoHal));
214         if (credentialInfo == NULL) {
215             LOG_ERROR("credentialInfo malloc failed");
216             return RESULT_NO_MEMORY;
217         }
218         result = StreamRead(parcel, index, credentialInfo, sizeof(CredentialInfoHal));
219         if (result != RESULT_SUCCESS) {
220             LOG_ERROR("StreamRead failed");
221             Free(credentialInfo);
222             return result;
223         }
224         result = credentialList->insert(credentialList, credentialInfo);
225         if (result != RESULT_SUCCESS) {
226             LOG_ERROR("credentialList insert failed");
227             Free(credentialInfo);
228             return result;
229         }
230     }
231     return RESULT_SUCCESS;
232 }
233 
StreamReadEnrolledList(Buffer *parcel, uint32_t *index, LinkedList *enrolledList)234 IAM_STATIC ResultCode StreamReadEnrolledList(Buffer *parcel, uint32_t *index, LinkedList *enrolledList)
235 {
236     if (!IsBufferValid(parcel) || enrolledList == NULL) {
237         LOG_ERROR("invalid params");
238         return RESULT_BAD_PARAM;
239     }
240     uint32_t enrolledNum;
241     ResultCode result = StreamRead(parcel, index, &enrolledNum, sizeof(uint32_t));
242     if (result != RESULT_SUCCESS) {
243         LOG_ERROR("stream read failed");
244         return RESULT_BAD_READ;
245     }
246     if (enrolledNum > MAX_CREDENTIAL) {
247         LOG_ERROR("bad enrolled num");
248         return RESULT_BAD_READ;
249     }
250     for (uint32_t i = 0; i < enrolledNum; ++i) {
251         EnrolledInfoHal *enrolledInfo = Malloc(sizeof(EnrolledInfoHal));
252         if (enrolledInfo == NULL) {
253             LOG_ERROR("enrolledInfo malloc failed");
254             return RESULT_NO_MEMORY;
255         }
256         result = StreamRead(parcel, index, enrolledInfo, sizeof(EnrolledInfoHal));
257         if (result != RESULT_SUCCESS) {
258             LOG_ERROR("StreamRead failed");
259             Free(enrolledInfo);
260             return result;
261         }
262         result = enrolledList->insert(enrolledList, enrolledInfo);
263         if (result != RESULT_SUCCESS) {
264             LOG_ERROR("enrolledList insert failed");
265             Free(enrolledInfo);
266             return result;
267         }
268     }
269     return RESULT_SUCCESS;
270 }
271 
StreamReadUserInfo(Buffer *parcel, uint32_t *index, UserInfo *userInfo)272 IAM_STATIC ResultCode StreamReadUserInfo(Buffer *parcel, uint32_t *index, UserInfo *userInfo)
273 {
274     ResultCode result = StreamRead(parcel, index, &userInfo->userId, sizeof(int32_t));
275     if (result != RESULT_SUCCESS) {
276         LOG_ERROR("Read userId failed");
277         return RESULT_GENERAL_ERROR;
278     }
279     LOG_INFO("userInfo userId %{public}d", userInfo->userId);
280     result = StreamRead(parcel, index, &userInfo->userType, sizeof(int32_t));
281     if (result != RESULT_SUCCESS) {
282         LOG_ERROR("Read userType failed");
283         return RESULT_GENERAL_ERROR;
284     }
285     LOG_INFO("userInfo userType %{public}d", userInfo->userType);
286     result = StreamRead(parcel, index, &userInfo->secUid, sizeof(uint64_t));
287     if (result != RESULT_SUCCESS) {
288         LOG_ERROR("Read secUid failed");
289         return RESULT_GENERAL_ERROR;
290     }
291     result = StreamReadCredentialList(parcel, index, userInfo->credentialInfoList);
292     if (result != RESULT_SUCCESS) {
293         LOG_ERROR("Read credentialInfoList failed");
294         return RESULT_GENERAL_ERROR;
295     }
296     result = StreamReadEnrolledList(parcel, index, userInfo->enrolledInfoList);
297     if (result != RESULT_SUCCESS) {
298         LOG_ERROR("Read enrolledInfoList failed");
299         return RESULT_GENERAL_ERROR;
300     }
301     return RESULT_SUCCESS;
302 }
303 
ReadFileInfo(void)304 IAM_STATIC Buffer *ReadFileInfo(void)
305 {
306     FileOperator *fileOperator = GetFileOperator(DEFAULT_FILE_OPERATOR);
307     if (!IsFileOperatorValid(fileOperator)) {
308         LOG_ERROR("invalid file operation");
309         return NULL;
310     }
311     uint32_t fileSize;
312     int32_t ret = fileOperator->getFileLen(IDM_USER_INFO, &fileSize);
313     if (ret != RESULT_SUCCESS) {
314         LOG_ERROR("open file failed");
315         return NULL;
316     }
317     Buffer *parcel = CreateBufferBySize(fileSize);
318     if (parcel == NULL) {
319         LOG_ERROR("parcel create failed");
320         return NULL;
321     }
322     if (fileOperator->readFile(IDM_USER_INFO, parcel->buf, parcel->maxSize) != RESULT_SUCCESS) {
323         LOG_ERROR("read failed");
324         DestoryBuffer(parcel);
325         return NULL;
326     }
327     parcel->contentSize = fileSize;
328     return parcel;
329 }
330 
StreamReadFileInfo(Buffer *parcel, LinkedList *userInfoList)331 IAM_STATIC bool StreamReadFileInfo(Buffer *parcel, LinkedList *userInfoList)
332 {
333     uint32_t index = 0;
334     uint32_t userNum;
335     uint32_t version;
336     ResultCode result = StreamRead(parcel, &index, &version, sizeof(uint32_t));
337     if (result != RESULT_SUCCESS) {
338         LOG_ERROR("read version failed");
339         return false;
340     }
341     result = StreamRead(parcel, &index, &userNum, sizeof(uint32_t));
342     if (result != RESULT_SUCCESS) {
343         LOG_ERROR("read userNum failed");
344         return false;
345     }
346     if (userNum > MAX_USER) {
347         LOG_ERROR("bad user num");
348         return false;
349     }
350     for (uint32_t i = 0; i < userNum; ++i) {
351         UserInfo *userInfo = InitUserInfoNode();
352         if (userInfo == NULL) {
353             LOG_ERROR("userInfoNode init failed");
354             return false;
355         }
356         result = StreamReadUserInfo(parcel, &index, userInfo);
357         if (result != RESULT_SUCCESS) {
358             LOG_ERROR("StreamRead failed");
359             DestroyUserInfoNode(userInfo);
360             return false;
361         }
362         result = userInfoList->insert(userInfoList, userInfo);
363         if (result != RESULT_SUCCESS) {
364             LOG_ERROR("userInfoList insert failed");
365             DestroyUserInfoNode(userInfo);
366             return false;
367         }
368     }
369     return true;
370 }
371 
LoadFileInfo(void)372 LinkedList *LoadFileInfo(void)
373 {
374     LOG_INFO("start");
375     FileOperator *fileOperator = GetFileOperator(DEFAULT_FILE_OPERATOR);
376     if (!IsFileOperatorValid(fileOperator)) {
377         LOG_ERROR("invalid file operation");
378         return NULL;
379     }
380     if (!fileOperator->isFileExist(IDM_USER_INFO)) {
381         LOG_ERROR("file is not exist");
382         return CreateLinkedList(DestroyUserInfoNode);
383     }
384     Buffer *parcel = ReadFileInfo();
385     if (parcel == NULL) {
386         LOG_ERROR("read file info failed");
387         return NULL;
388     }
389 
390     LinkedList *userInfoList = CreateLinkedList(DestroyUserInfoNode);
391     if (userInfoList == NULL) {
392         LOG_ERROR("list create failed");
393         DestoryBuffer(parcel);
394         return NULL;
395     }
396     if (!StreamReadFileInfo(parcel, userInfoList)) {
397         LOG_ERROR("StreamReadFileInfo failed");
398         DestoryBuffer(parcel);
399         DestroyLinkedList(userInfoList);
400         return NULL;
401     }
402     DestoryBuffer(parcel);
403     return userInfoList;
404 }
405