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