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