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 }