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 }