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