• 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/service/el1/public/userauth/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 = CreateBufferBySize(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         result = credentialList->insert(credentialList, credentialInfo);
279         if (result != RESULT_SUCCESS) {
280             LOG_ERROR("credentialList insert failed");
281             Free(credentialInfo);
282             return result;
283         }
284     }
285     return RESULT_SUCCESS;
286 }
287 
StreamReadEnrolledList(Buffer * parcel,uint32_t * index,LinkedList * enrolledList)288 static ResultCode StreamReadEnrolledList(Buffer *parcel, uint32_t *index, LinkedList *enrolledList)
289 {
290     if (!IsBufferValid(parcel) || enrolledList == NULL) {
291         LOG_ERROR("invalid params");
292         return RESULT_BAD_PARAM;
293     }
294     uint32_t enrolledNum;
295     ResultCode result = StreamRead(parcel, index, &enrolledNum, sizeof(uint32_t));
296     if (result != RESULT_SUCCESS) {
297         LOG_ERROR("stream read failed");
298         return RESULT_BAD_READ;
299     }
300     if (enrolledNum > MAX_CREDENTIAL) {
301         LOG_ERROR("bad enrolled num");
302         return RESULT_BAD_READ;
303     }
304     for (uint32_t i = 0; i < enrolledNum; ++i) {
305         EnrolledInfoHal *enrolledInfo = Malloc(sizeof(EnrolledInfoHal));
306         if (enrolledInfo == NULL) {
307             LOG_ERROR("enrolledInfo malloc failed");
308             return RESULT_NO_MEMORY;
309         }
310         result = StreamRead(parcel, index, enrolledInfo, sizeof(EnrolledInfoHal));
311         if (result != RESULT_SUCCESS) {
312             LOG_ERROR("StreamRead failed");
313             Free(enrolledInfo);
314             return result;
315         }
316         result = enrolledList->insert(enrolledList, enrolledInfo);
317         if (result != RESULT_SUCCESS) {
318             LOG_ERROR("enrolledList insert failed");
319             Free(enrolledInfo);
320             return result;
321         }
322     }
323     return RESULT_SUCCESS;
324 }
325 
StreamReadUserInfo(Buffer * parcel,uint32_t * index,UserInfo * userInfo)326 static ResultCode StreamReadUserInfo(Buffer *parcel, uint32_t *index, UserInfo *userInfo)
327 {
328     ResultCode result = StreamRead(parcel, index, &userInfo->userId, sizeof(int32_t));
329     if (result != RESULT_SUCCESS) {
330         LOG_ERROR("Read userId failed");
331         return RESULT_GENERAL_ERROR;
332     }
333     result = StreamRead(parcel, index, &userInfo->secUid, sizeof(uint64_t));
334     if (result != RESULT_SUCCESS) {
335         LOG_ERROR("Read secUid failed");
336         return RESULT_GENERAL_ERROR;
337     }
338     result = StreamReadCredentialList(parcel, index, userInfo->credentialInfoList);
339     if (result != RESULT_SUCCESS) {
340         LOG_ERROR("Read credentialInfoList failed");
341         return RESULT_GENERAL_ERROR;
342     }
343     result = StreamReadEnrolledList(parcel, index, userInfo->enrolledInfoList);
344     if (result != RESULT_SUCCESS) {
345         LOG_ERROR("Read enrolledInfoList failed");
346         return RESULT_GENERAL_ERROR;
347     }
348     return RESULT_SUCCESS;
349 }
350 
ReadFileInfo()351 static Buffer *ReadFileInfo()
352 {
353     FileOperator *fileOperator = GetFileOperator(DEFAULT_FILE_OPERATOR);
354     if (!IsFileOperatorValid(fileOperator)) {
355         LOG_ERROR("invalid file operation");
356         return NULL;
357     }
358     uint32_t fileSize;
359     int32_t ret = fileOperator->getFileLen(IDM_USER_INFO, &fileSize);
360     if (ret != RESULT_SUCCESS) {
361         LOG_ERROR("open file failed");
362         return NULL;
363     }
364     Buffer *parcel = CreateBufferBySize(fileSize);
365     if (parcel == NULL) {
366         LOG_ERROR("parcel create failed");
367         return NULL;
368     }
369     if (fileOperator->readFile(IDM_USER_INFO, parcel->buf, parcel->maxSize) != RESULT_SUCCESS) {
370         LOG_ERROR("read failed");
371         DestoryBuffer(parcel);
372         return NULL;
373     }
374     parcel->contentSize = fileSize;
375     return parcel;
376 }
377 
StreamReadFileInfo(Buffer * parcel,LinkedList * userInfoList)378 static bool StreamReadFileInfo(Buffer *parcel, LinkedList *userInfoList)
379 {
380     uint32_t index = 0;
381     uint32_t userNum;
382     uint32_t version;
383     ResultCode result = StreamRead(parcel, &index, &version, sizeof(uint32_t));
384     if (result != RESULT_SUCCESS) {
385         LOG_ERROR("read version failed");
386         return false;
387     }
388     result = StreamRead(parcel, &index, &userNum, sizeof(uint32_t));
389     if (result != RESULT_SUCCESS) {
390         LOG_ERROR("read userNum failed");
391         return false;
392     }
393     if (userNum > MAX_USER) {
394         LOG_ERROR("bad user num");
395         return false;
396     }
397     for (uint32_t i = 0; i < userNum; ++i) {
398         UserInfo *userInfo = InitUserInfoNode();
399         if (userInfo == NULL) {
400             LOG_ERROR("userInfoNode init failed");
401             return false;
402         }
403         result = StreamReadUserInfo(parcel, &index, userInfo);
404         if (result != RESULT_SUCCESS) {
405             LOG_ERROR("StreamRead failed");
406             DestroyUserInfoNode(userInfo);
407             return false;
408         }
409         result = userInfoList->insert(userInfoList, userInfo);
410         if (result != RESULT_SUCCESS) {
411             LOG_ERROR("userInfoList insert failed");
412             DestroyUserInfoNode(userInfo);
413             return false;
414         }
415     }
416     return true;
417 }
418 
LoadFileInfo(void)419 LinkedList *LoadFileInfo(void)
420 {
421     LOG_INFO("start");
422     FileOperator *fileOperator = GetFileOperator(DEFAULT_FILE_OPERATOR);
423     if (!IsFileOperatorValid(fileOperator)) {
424         LOG_ERROR("invalid file operation");
425         return NULL;
426     }
427     if (!fileOperator->isFileExist(IDM_USER_INFO)) {
428         LOG_ERROR("file is not exist");
429         return CreateLinkedList(DestroyUserInfoNode);
430     }
431     Buffer *parcel = ReadFileInfo();
432     if (parcel == NULL) {
433         LOG_ERROR("read file info failed");
434         return NULL;
435     }
436 
437     LinkedList *userInfoList = CreateLinkedList(DestroyUserInfoNode);
438     if (userInfoList == NULL) {
439         LOG_ERROR("list create failed");
440         DestoryBuffer(parcel);
441         return NULL;
442     }
443     if (!StreamReadFileInfo(parcel, userInfoList)) {
444         LOG_ERROR("StreamReadFileInfo failed");
445         DestoryBuffer(parcel);
446         DestroyLinkedList(userInfoList);
447         return NULL;
448     }
449     DestoryBuffer(parcel);
450     return userInfoList;
451 }