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 }