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 "cert_manager_auth_list_mgr.h"
17
18 #include "securec.h"
19
20 #include "cert_manager.h"
21 #include "cert_manager_file_operator.h"
22 #include "cert_manager_mem.h"
23 #include "cert_manager_storage.h"
24 #include "cert_manager_uri.h"
25 #include "cm_log.h"
26 #include "cm_type.h"
27
28 #define MAX_PATH_LEN 512
29 #define MAX_AUTH_COUNT 256
30 #define AUTH_LIST_VERSON 0
31
CheckAuthListFileSizeValid(const struct CmBlob * originList,uint32_t * authCount)32 static int32_t CheckAuthListFileSizeValid(const struct CmBlob *originList, uint32_t *authCount)
33 {
34 if (originList->size < (sizeof(uint32_t) + sizeof(uint32_t))) { /* version and count size */
35 CM_LOG_E("invalid authlist size[%u]", originList->size);
36 return CMR_ERROR_INVALID_OPERATION;
37 }
38
39 uint32_t count = 0;
40 (void)memcpy_s(&count, sizeof(count), originList->data + sizeof(uint32_t), sizeof(count));
41 if (count > MAX_OUT_BLOB_SIZE) {
42 CM_LOG_E("invalid auth count[%u]", count);
43 return CMR_ERROR_INVALID_OPERATION;
44 }
45
46 uint32_t size = sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) * count;
47 if (originList->size != size) {
48 CM_LOG_E("invalid auth list file size[%u], count[%u]", originList->size, count);
49 return CMR_ERROR_INVALID_OPERATION;
50 }
51
52 *authCount = count;
53 return CM_SUCCESS;
54 }
55
IsUidExist(const struct CmBlob * list,uint32_t count,uint32_t targetUid,uint32_t * position)56 static bool IsUidExist(const struct CmBlob *list, uint32_t count, uint32_t targetUid, uint32_t *position)
57 {
58 uint32_t uid;
59 uint32_t offset = sizeof(uint32_t) + sizeof(uint32_t);
60 for (uint32_t i = 0; i < count; ++i) {
61 (void)memcpy_s(&uid, sizeof(uint32_t), list->data + offset, sizeof(uint32_t));
62 offset += sizeof(uint32_t);
63 if (uid == targetUid) {
64 *position = offset;
65 return true;
66 }
67 }
68 return false;
69 }
70
CopyBlob(const struct CmBlob * originList,struct CmBlob * outList)71 static int32_t CopyBlob(const struct CmBlob *originList, struct CmBlob *outList)
72 {
73 uint8_t *data = (uint8_t *)CMMalloc(originList->size);
74 if (data == NULL) {
75 CM_LOG_E("out data malloc failed");
76 return CMR_ERROR_MALLOC_FAIL;
77 }
78
79 (void)memcpy_s(data, originList->size, originList->data, originList->size);
80
81 outList->data = data;
82 outList->size = originList->size;
83 return CM_SUCCESS;
84 }
85
InsertUid(const struct CmBlob * originList,uint32_t uid,struct CmBlob * addedList)86 static int32_t InsertUid(const struct CmBlob *originList, uint32_t uid, struct CmBlob *addedList)
87 {
88 uint32_t count = 0;
89 int32_t ret = CheckAuthListFileSizeValid(originList, &count);
90 if (ret != CM_SUCCESS) {
91 return ret;
92 }
93
94 uint32_t position = 0;
95 bool isUidExist = IsUidExist(originList, count, uid, &position);
96 if (isUidExist) {
97 /* exist then copy origin */
98 return CopyBlob(originList, addedList);
99 }
100
101 if (count >= MAX_AUTH_COUNT) {
102 return CMR_ERROR_INVALID_OPERATION;
103 }
104
105 uint32_t size = originList->size + sizeof(uint32_t); /* add one uid */
106 uint8_t *data = (uint8_t *)CMMalloc(size);
107 if (data == NULL) {
108 return CMR_ERROR_MALLOC_FAIL;
109 }
110
111 do {
112 ret = CMR_ERROR_INVALID_OPERATION;
113 if (memcpy_s(data, size, originList->data, originList->size) != EOK) {
114 CM_LOG_E("copy origin list failed");
115 break;
116 }
117 if (memcpy_s(data + originList->size, size - originList->size, &uid, sizeof(uint32_t)) != EOK) {
118 CM_LOG_E("copy inserted uid failed");
119 break;
120 }
121
122 /* refresh count after add */
123 uint32_t countAfterAdd = count + 1;
124 if (memcpy_s(data + sizeof(uint32_t), sizeof(countAfterAdd), &countAfterAdd, sizeof(countAfterAdd)) != EOK) {
125 CM_LOG_E("refresh count after add failed");
126 break;
127 }
128 ret = CM_SUCCESS;
129 } while (0);
130 if (ret != CM_SUCCESS) {
131 CM_FREE_PTR(data);
132 return ret;
133 }
134
135 addedList->data = data;
136 addedList->size = size;
137 return CM_SUCCESS;
138 }
139
RemoveUid(const struct CmBlob * originList,uint32_t uid,struct CmBlob * removedList)140 static int32_t RemoveUid(const struct CmBlob *originList, uint32_t uid, struct CmBlob *removedList)
141 {
142 uint32_t count = 0;
143 int32_t ret = CheckAuthListFileSizeValid(originList, &count);
144 if (ret != CM_SUCCESS) {
145 return ret;
146 }
147
148 uint32_t position = 0;
149 bool isUidExist = IsUidExist(originList, count, uid, &position);
150 if (!isUidExist) {
151 /* not exist then copy origin */
152 return CopyBlob(originList, removedList);
153 }
154
155 uint32_t size = originList->size - sizeof(uint32_t); /* delete one uid */
156 uint8_t *data = (uint8_t *)CMMalloc(size);
157 if (data == NULL) {
158 return CMR_ERROR_MALLOC_FAIL;
159 }
160
161 do {
162 ret = CMR_ERROR_INVALID_OPERATION;
163 uint32_t beforeSize = position - sizeof(uint32_t); /* positon >= 12 */
164 if (memcpy_s(data, size, originList->data, beforeSize) != EOK) {
165 CM_LOG_E("copy origin list before uid failed");
166 break;
167 }
168
169 if (size > beforeSize) { /* has buffer after uid */
170 if (memcpy_s(data + beforeSize, size - beforeSize, originList->data + position,
171 originList->size - position) != EOK) {
172 CM_LOG_E("copy origin list after uid failed");
173 break;
174 }
175 }
176
177 /* refresh count after remove */
178 uint32_t countAfterRemove = count - 1; /* count > 1 */
179 if (memcpy_s(data + sizeof(uint32_t), sizeof(countAfterRemove),
180 &countAfterRemove, sizeof(countAfterRemove)) != EOK) {
181 CM_LOG_E("refresh count after delete failed");
182 break;
183 }
184 ret = CM_SUCCESS;
185 } while (0);
186 if (ret != CM_SUCCESS) {
187 CM_FREE_PTR(data);
188 return ret;
189 }
190
191 removedList->data = data;
192 removedList->size = size;
193 return CM_SUCCESS;
194 }
195
RefreshAuthListBuf(const char * path,const char * fileName,uint32_t uid,bool isAdd,struct CmBlob * authList)196 static int32_t RefreshAuthListBuf(const char *path, const char *fileName, uint32_t uid, bool isAdd,
197 struct CmBlob *authList)
198 {
199 struct CmBlob list = { 0, NULL };
200 int32_t ret = CmStorageGetBuf(path, fileName, &list);
201 if (ret != CM_SUCCESS) {
202 return ret;
203 }
204
205 if (isAdd) {
206 ret = InsertUid(&list, uid, authList);
207 } else {
208 ret = RemoveUid(&list, uid, authList);
209 }
210 CM_FREE_PTR(list.data);
211 return ret;
212 }
213
214 /*
215 * auth list buffer format:
216 * |--version--|--uidCount(n)--|--uid0--|--uid1--|...|--uid(n-1)--|
217 * | 4Byte | 4Byte | 4Byte | 4Byte |...| 4Byte |
218 */
InitAuthListBuf(uint32_t uid,struct CmBlob * authList)219 static int32_t InitAuthListBuf(uint32_t uid, struct CmBlob *authList)
220 {
221 uint32_t count = 1;
222 uint32_t version = AUTH_LIST_VERSON;
223 uint32_t size = sizeof(version) + sizeof(count) + sizeof(uid) * count;
224 uint8_t *data = (uint8_t *)CMMalloc(size);
225 if (data == NULL) {
226 CM_LOG_E("malloc file buffer failed");
227 return CMR_ERROR_MALLOC_FAIL;
228 }
229 (void)memset_s(data, size, 0, size);
230
231 int32_t ret = CM_SUCCESS;
232 uint32_t offset = 0;
233 do {
234 if (memcpy_s(data + offset, size - offset, &version, sizeof(version)) != EOK) {
235 CM_LOG_E("copy count failed");
236 ret = CMR_ERROR_INVALID_OPERATION;
237 break;
238 }
239 offset += sizeof(version);
240
241 if (memcpy_s(data + offset, size - offset, &count, sizeof(count)) != EOK) {
242 CM_LOG_E("copy count failed");
243 ret = CMR_ERROR_INVALID_OPERATION;
244 break;
245 }
246 offset += sizeof(count);
247
248 if (memcpy_s(data + offset, size - offset, &uid, sizeof(uid)) != EOK) {
249 CM_LOG_E("copy uid failed");
250 ret = CMR_ERROR_INVALID_OPERATION;
251 break;
252 }
253 } while (0);
254 if (ret != CM_SUCCESS) {
255 CM_FREE_PTR(data);
256 return ret;
257 }
258
259 authList->data = data;
260 authList->size = size;
261 return CM_SUCCESS;
262 }
263
RefreshAuthList(const char * path,const char * fileName,uint32_t uid,bool isAdd)264 static int32_t RefreshAuthList(const char *path, const char *fileName, uint32_t uid, bool isAdd)
265 {
266 bool isAuthListExist = false;
267 int32_t ret = CmIsFileExist(path, fileName);
268 if (ret == CM_SUCCESS) {
269 isAuthListExist = true;
270 }
271
272 if (!isAuthListExist && !isAdd) {
273 CM_LOG_D("auth list file not exit when delete uid");
274 return CM_SUCCESS; /* auth list file not exit when delete uid */
275 }
276
277 struct CmBlob authList = { 0, NULL };
278 if (isAuthListExist) {
279 ret = RefreshAuthListBuf(path, fileName, uid, isAdd, &authList);
280 } else { /* auth list file not exit when add uid */
281 ret = InitAuthListBuf(uid, &authList);
282 }
283 if (ret != CM_SUCCESS) {
284 return ret;
285 }
286
287 ret = CmFileWrite(path, fileName, 0, authList.data, authList.size);
288 if (ret != CM_SUCCESS) {
289 CM_LOG_E("write file failed");
290 }
291 CM_FREE_PTR(authList.data);
292 return ret;
293 }
294
FormatAppUidList(const struct CmBlob * list,struct CmAppUidList * appUidList)295 static int32_t FormatAppUidList(const struct CmBlob *list, struct CmAppUidList *appUidList)
296 {
297 uint32_t count = 0;
298 int32_t ret = CheckAuthListFileSizeValid(list, &count);
299 if (ret != CM_SUCCESS) {
300 return ret;
301 }
302
303 if (count == 0) {
304 appUidList->appUidCount = 0;
305 CM_LOG_D("auth list has no auth uid");
306 return CM_SUCCESS; /* has no auth uid */
307 }
308
309 uint8_t *data = (uint8_t *)CMMalloc(count * sizeof(uint32_t));
310 if (data == NULL) {
311 CM_LOG_E("malloc app uid buffer failed");
312 return ret = CMR_ERROR_MALLOC_FAIL;
313 }
314
315 uint32_t offsetOut = 0;
316 uint32_t offset = sizeof(uint32_t) + sizeof(uint32_t);
317 for (uint32_t i = 0; i < count; ++i) {
318 (void)memcpy_s(data + offsetOut, sizeof(uint32_t), list->data + offset, sizeof(uint32_t));
319 offset += sizeof(uint32_t);
320 offsetOut += sizeof(uint32_t);
321 }
322
323 appUidList->appUidCount = count;
324 appUidList->appUid = (uint32_t *)data;
325 return CM_SUCCESS;
326 }
327
CmAddAuthUid(const struct CmContext * context,const struct CmBlob * uri,uint32_t uid)328 int32_t CmAddAuthUid(const struct CmContext *context, const struct CmBlob *uri, uint32_t uid)
329 {
330 int32_t ret = CmCheckCredentialExist(context, uri);
331 if (ret != CM_SUCCESS) {
332 return ret;
333 }
334
335 char authListPath[MAX_PATH_LEN] = { 0 };
336 ret = ConstructAuthListPath(context, CM_CREDENTIAL_STORE, authListPath, MAX_PATH_LEN);
337 if (ret != CM_SUCCESS) {
338 return ret;
339 }
340
341 ret = RefreshAuthList(authListPath, (char *)uri->data, uid, true);
342 if (ret != CM_SUCCESS) {
343 CM_LOG_E("refresh auth list failed, ret = %d", ret);
344 }
345 return ret;
346 }
347
CmRemoveAuthUid(const struct CmContext * context,const struct CmBlob * uri,uint32_t uid)348 int32_t CmRemoveAuthUid(const struct CmContext *context, const struct CmBlob *uri, uint32_t uid)
349 {
350 char authListPath[MAX_PATH_LEN] = { 0 };
351 int32_t ret = ConstructAuthListPath(context, CM_CREDENTIAL_STORE, authListPath, MAX_PATH_LEN);
352 if (ret != CM_SUCCESS) {
353 return ret;
354 }
355
356 ret = RefreshAuthList(authListPath, (char *)uri->data, uid, false);
357 if (ret != CM_SUCCESS) {
358 CM_LOG_E("refresh auth list failed, ret = %d", ret);
359 }
360 return ret;
361 }
362
CmGetAuthList(const struct CmContext * context,const struct CmBlob * uri,struct CmAppUidList * appUidList)363 int32_t CmGetAuthList(const struct CmContext *context, const struct CmBlob *uri, struct CmAppUidList *appUidList)
364 {
365 char authListPath[MAX_PATH_LEN] = { 0 };
366 int32_t ret = ConstructAuthListPath(context, CM_CREDENTIAL_STORE, authListPath, MAX_PATH_LEN);
367 if (ret != CM_SUCCESS) {
368 return ret;
369 }
370
371 /* auth list file not exist */
372 ret = CmIsFileExist(authListPath, (char *)uri->data);
373 if (ret != CM_SUCCESS) {
374 CM_LOG_D("auth list file not exist.");
375 appUidList->appUidCount = 0;
376 return CM_SUCCESS;
377 }
378
379 struct CmBlob list = { 0, NULL };
380 ret = CmStorageGetBuf(authListPath, (char *)uri->data, &list);
381 if (ret != CM_SUCCESS) {
382 return ret;
383 }
384
385 ret = FormatAppUidList(&list, appUidList);
386 CM_FREE_PTR(list.data);
387 return ret;
388 }
389
CmDeleteAuthListFile(const struct CmContext * context,const struct CmBlob * uri)390 int32_t CmDeleteAuthListFile(const struct CmContext *context, const struct CmBlob *uri)
391 {
392 char authListPath[MAX_PATH_LEN] = { 0 };
393 int32_t ret = ConstructAuthListPath(context, CM_CREDENTIAL_STORE, authListPath, MAX_PATH_LEN);
394 if (ret != CM_SUCCESS) {
395 return ret;
396 }
397
398 ret = CmIsFileExist(authListPath, (char *)uri->data);
399 if (ret != CM_SUCCESS) { /* auth list file not exist */
400 return CM_SUCCESS;
401 }
402
403 ret = CmFileRemove(authListPath, (char *)uri->data);
404 if (ret != CM_SUCCESS) {
405 CM_LOG_E("remove file failed, ret = %d", ret);
406 }
407 return ret;
408 }
409
CmCheckIsAuthUidExist(const struct CmContext * context,const struct CmBlob * uri,uint32_t targetUid,bool * isInAuthList)410 int32_t CmCheckIsAuthUidExist(const struct CmContext *context, const struct CmBlob *uri,
411 uint32_t targetUid, bool *isInAuthList)
412 {
413 *isInAuthList = false;
414
415 char authListPath[MAX_PATH_LEN] = { 0 };
416 int32_t ret = ConstructAuthListPath(context, CM_CREDENTIAL_STORE, authListPath, MAX_PATH_LEN);
417 if (ret != CM_SUCCESS) {
418 return ret;
419 }
420
421 ret = CmIsFileExist(authListPath, (char *)uri->data);
422 if (ret != CM_SUCCESS) { /* auth list file not exist */
423 return CM_SUCCESS;
424 }
425
426 struct CmBlob list = { 0, NULL };
427 ret = CmStorageGetBuf(authListPath, (char *)uri->data, &list);
428 if (ret != CM_SUCCESS) {
429 return ret;
430 }
431
432 uint32_t count = 0;
433 ret = CheckAuthListFileSizeValid(&list, &count);
434 if (ret != CM_SUCCESS) {
435 CM_FREE_PTR(list.data);
436 return ret;
437 }
438
439 uint32_t position = 0;
440 *isInAuthList = IsUidExist(&list, count, targetUid, &position);
441 CM_FREE_PTR(list.data);
442
443 return CM_SUCCESS;
444 }
445
CmRemoveAuthUidByUserId(uint32_t userId,uint32_t targetUid,const struct CmBlob * uri)446 int32_t CmRemoveAuthUidByUserId(uint32_t userId, uint32_t targetUid, const struct CmBlob *uri)
447 {
448 uint32_t uid = 0;
449 int32_t ret = CertManagerGetUidFromUri(uri, &uid);
450 if (ret != CM_SUCCESS) {
451 return ret;
452 }
453
454 struct CmContext context = { userId, uid, { 0 } };
455 return CmRemoveAuthUid(&context, uri, targetUid);
456 }
457
CmGetAuthListByUserId(uint32_t userId,const struct CmBlob * uri,struct CmAppUidList * appUidList)458 int32_t CmGetAuthListByUserId(uint32_t userId, const struct CmBlob *uri, struct CmAppUidList *appUidList)
459 {
460 uint32_t uid = 0;
461 int32_t ret = CertManagerGetUidFromUri(uri, &uid);
462 if (ret != CM_SUCCESS) {
463 return ret;
464 }
465
466 struct CmContext context = { userId, uid, { 0 } };
467 return CmGetAuthList(&context, uri, appUidList);
468 }
469
CmDeleteAuthListFileByUserId(uint32_t userId,const struct CmBlob * uri)470 int32_t CmDeleteAuthListFileByUserId(uint32_t userId, const struct CmBlob *uri)
471 {
472 uint32_t uid = 0;
473 int32_t ret = CertManagerGetUidFromUri(uri, &uid);
474 if (ret != CM_SUCCESS) {
475 return ret;
476 }
477
478 struct CmContext context = { userId, uid, { 0 } };
479 return CmDeleteAuthListFile(&context, uri);
480 }
481
CmCheckIsAuthUidExistByUserId(uint32_t userId,uint32_t targetUid,const struct CmBlob * uri,bool * isInAuthList)482 int32_t CmCheckIsAuthUidExistByUserId(uint32_t userId, uint32_t targetUid,
483 const struct CmBlob *uri, bool *isInAuthList)
484 {
485 uint32_t uid = 0;
486 int32_t ret = CertManagerGetUidFromUri(uri, &uid);
487 if (ret != CM_SUCCESS) {
488 return ret;
489 }
490
491 struct CmContext context = { userId, uid, { 0 } };
492 return CmCheckIsAuthUidExist(&context, uri, targetUid, isInAuthList);
493 }
494
CmCheckCredentialExist(const struct CmContext * context,const struct CmBlob * uri)495 int32_t CmCheckCredentialExist(const struct CmContext *context, const struct CmBlob *uri)
496 {
497 char uidPath[MAX_PATH_LEN] = { 0 };
498 int32_t ret = ConstructUidPath(context, CM_CREDENTIAL_STORE, uidPath, MAX_PATH_LEN);
499 if (ret != CM_SUCCESS) {
500 return ret;
501 }
502
503 char *fileName = (char *)uri->data;
504 ret = CmIsFileExist(uidPath, fileName);
505 if (ret != CM_SUCCESS) {
506 CM_LOG_E("Credential file not exist.");
507 }
508 return ret;
509 }
510
511