1 /*
2 * Copyright (c) 2022-2025 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.h"
17
18 #include <unistd.h>
19 #include <libgen.h>
20
21 #include "cert_manager_auth_mgr.h"
22 #include "cert_manager_file.h"
23 #include "cert_manager_file_operator.h"
24 #include "cert_manager_key_operation.h"
25 #include "cert_manager_mem.h"
26 #include "cert_manager_permission_check.h"
27 #include "cert_manager_status.h"
28 #include "cert_manager_storage.h"
29 #include "cert_manager_uri.h"
30 #include "cert_manager_query.h"
31 #include "cm_cert_property_rdb.h"
32 #include "cert_manager_crypto_operation.h"
33 #include "cm_log.h"
34 #include "cm_type.h"
35 #include "cm_x509.h"
36 #include "cm_util.h"
37
38 #include "securec.h"
39
40 #include "hks_api.h"
41
42 // LCOV_EXCL_START
43 #define MAX_PATH_LEN 256
44
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48
49 static bool g_hksInitialized = false;
50
CertManagerInitialize(void)51 int32_t CertManagerInitialize(void)
52 {
53 int32_t ret;
54 if (!g_hksInitialized) {
55 ret = HksInitialize();
56 if (ret != HKS_SUCCESS) {
57 CM_LOG_E("HUKS init failed, ret = %d", ret);
58 return CMR_ERROR_SA_START_HUKS_INIT_FAILED;
59 }
60 g_hksInitialized = true;
61 }
62
63 if (CmMakeDir(CERT_DIR) == CMR_ERROR_MAKE_DIR_FAIL) {
64 CM_LOG_E("Failed to create folder\n");
65 return CMR_ERROR_MAKE_DIR_FAIL;
66 }
67
68 ret = CreateCertPropertyRdb();
69 if (ret != CM_SUCCESS) {
70 return ret;
71 }
72
73 ret = CertManagerStatusInit();
74 if (ret != CM_SUCCESS) {
75 return (ret == CM_FAILURE) ? CMR_ERROR_SA_START_STATUS_INIT_FAILED : ret;
76 }
77
78 return CM_SUCCESS;
79 }
80
GetFilePath(const struct CmContext * context,uint32_t store,char * pathPtr,char * suffix,uint32_t * suffixLen)81 static int32_t GetFilePath(const struct CmContext *context, uint32_t store, char *pathPtr,
82 char *suffix, uint32_t *suffixLen)
83 {
84 int32_t ret;
85
86 if (context == NULL) {
87 CM_LOG_E("Null pointer failture");
88 return CMR_ERROR_NULL_POINTER;
89 }
90
91 if (suffix == NULL || suffixLen == NULL) {
92 CM_LOG_E("NULL pointer failure");
93 return CMR_ERROR_NULL_POINTER;
94 }
95
96 switch (store) {
97 case CM_CREDENTIAL_STORE:
98 ret = sprintf_s(pathPtr, MAX_PATH_LEN, "%s%u", CREDNTIAL_STORE, context->userId);
99 break;
100 case CM_USER_TRUSTED_STORE:
101 ret = sprintf_s(pathPtr, MAX_PATH_LEN, "%s%u", USER_CA_STORE, context->userId);
102 break;
103 case CM_PRI_CREDENTIAL_STORE:
104 ret = sprintf_s(pathPtr, MAX_PATH_LEN, "%s%u", PRI_CREDNTIAL_STORE, context->userId);
105 break;
106 case CM_SYS_CREDENTIAL_STORE:
107 ret = sprintf_s(pathPtr, MAX_PATH_LEN, "%s%u", SYS_CREDNTIAL_STORE, context->userId);
108 break;
109 case CM_SYSTEM_TRUSTED_STORE:
110 ret = sprintf_s(pathPtr, MAX_PATH_LEN, "%s", SYSTEM_CA_STORE);
111 break;
112 default:
113 return CMR_ERROR_INVALID_ARGUMENT_STORE_TYPE;
114 }
115
116 if (ret < 0) {
117 CM_LOG_E("Construct file Path failed ret: %d", ret);
118 return CMR_ERROR_MEM_OPERATION_PRINT;
119 }
120
121 // construct file suffix
122 if (store != CM_SYSTEM_TRUSTED_STORE) {
123 ret = sprintf_s(suffix, MAX_SUFFIX_LEN, "%u", context->uid);
124 if (ret < 0) {
125 CM_LOG_E("Construct file suffix failed ret: %d", ret);
126 return CMR_ERROR_MEM_OPERATION_PRINT;
127 }
128 }
129
130 *suffixLen = (uint32_t)strlen(suffix);
131 return CMR_OK;
132 }
133
CmGetFilePath(const struct CmContext * context,uint32_t store,struct CmMutableBlob * pathBlob)134 static int32_t CmGetFilePath(const struct CmContext *context, uint32_t store, struct CmMutableBlob *pathBlob)
135 {
136 char pathPtr[MAX_PATH_LEN] = {0};
137 uint32_t suffixLen = 0;
138 char suffixBuf[MAX_SUFFIX_LEN] = {0};
139
140 if ((pathBlob == NULL) || (pathBlob->data == NULL) || (pathBlob->size == 0)) {
141 CM_LOG_E("Null pointer failure");
142 return CMR_ERROR_NULL_POINTER;
143 }
144 int32_t ret = GetFilePath(context, store, pathPtr, suffixBuf, &suffixLen);
145 if (ret != CMR_OK) {
146 CM_LOG_E("Get file path faild");
147 return ret;
148 }
149
150 /* Create folder if it does not exist */
151 if (CmMakeDir(pathPtr) == CMR_ERROR_MAKE_DIR_FAIL) {
152 CM_LOG_E("Failed to create path folder");
153 return CMR_ERROR_MAKE_DIR_FAIL;
154 }
155
156 if (pathBlob->size - 1 < strlen(pathPtr) + suffixLen) {
157 CM_LOG_E("Failed to copy path");
158 return CMR_ERROR_BUFFER_TOO_SMALL;
159 }
160
161 char *path = (char *)pathBlob->data;
162 if (suffixLen == 0) {
163 if (sprintf_s(path, MAX_PATH_LEN, "%s", pathPtr) < 0) {
164 return CMR_ERROR_MEM_OPERATION_PRINT;
165 }
166 } else {
167 if (sprintf_s(path, MAX_PATH_LEN, "%s/%s", pathPtr, suffixBuf) < 0) {
168 return CMR_ERROR_MEM_OPERATION_PRINT;
169 }
170 }
171
172 pathBlob->size = strlen(path) + 1;
173 if (CmMakeDir(path) == CMR_ERROR_MAKE_DIR_FAIL) {
174 CM_LOG_E("Failed to create folder");
175 return CMR_ERROR_MAKE_DIR_FAIL;
176 }
177 return CMR_OK;
178 }
179
FindObjectCert(const struct CmBlob * certUri,const struct CmMutableBlob * fNames,uint32_t certCount)180 static int32_t FindObjectCert(const struct CmBlob *certUri, const struct CmMutableBlob *fNames, uint32_t certCount)
181 {
182 for (uint32_t i = 0; i < certCount; i++) {
183 if (fNames[i].data == NULL) {
184 CM_LOG_E("Corrupted file name at index: %u", i);
185 return CMR_ERROR_STORAGE;
186 }
187 /* Check if url is matching with the cert filename */
188 if ((certUri->size <= fNames[i].size) && (memcmp(certUri->data, fNames[i].data, certUri->size) == 0)) {
189 return CM_SUCCESS;
190 }
191 }
192 return CMR_ERROR_NOT_FOUND;
193 }
194
GetGmSystemCaCertPath(struct CmMutableBlob * path)195 static int32_t GetGmSystemCaCertPath(struct CmMutableBlob *path)
196 {
197 if ((path == NULL) || (path->data == NULL) || (path->size == 0)) {
198 CM_LOG_E("Null pointer failure");
199 return CMR_ERROR_NULL_POINTER;
200 }
201
202 /* get gm system ca cert path */
203 char *pathStr = (char *)path->data;
204 if (sprintf_s(pathStr, path->size, "%s", SYSTEM_CA_STORE_GM) < 0) {
205 CM_LOG_E("sprintf gm system ca path failed");
206 return CMR_ERROR_MEM_OPERATION_PRINT;
207 }
208
209 path->size = strlen(pathStr) + 1;
210 return CM_SUCCESS;
211 }
212
CertManagerFindCertFileNameByUri(const struct CmContext * context,const struct CmBlob * certUri,uint32_t store,bool isGmSysCert,struct CmMutableBlob * path)213 int32_t CertManagerFindCertFileNameByUri(const struct CmContext *context, const struct CmBlob *certUri,
214 uint32_t store, bool isGmSysCert, struct CmMutableBlob *path)
215 {
216 ASSERT_ARGS(context && certUri && certUri->data);
217
218 int32_t ret;
219 if (!isGmSysCert) {
220 ret = CmGetFilePath(context, store, path);
221 } else {
222 if (CmIsDirExist(SYSTEM_CA_STORE_GM) != CM_SUCCESS) {
223 return CMR_ERROR_NOT_FOUND;
224 }
225 ret = GetGmSystemCaCertPath(path);
226 }
227 if (ret != CM_SUCCESS) {
228 CM_LOG_E("Failed obtain path for store %x\n", store);
229 return ret;
230 }
231
232 struct CmMutableBlob fileNames = { 0, NULL };
233 ret = CertManagerGetFilenames(&fileNames, (char *)path->data);
234 if (ret != CM_SUCCESS) {
235 CM_LOG_E("Failed obtain filenames from path");
236 return ret;
237 }
238
239 struct CmMutableBlob *fNames = (struct CmMutableBlob *)fileNames.data;
240 ret = FindObjectCert(certUri, fNames, fileNames.size);
241 FreeFileNames(fNames, fileNames.size);
242 if (ret != CM_SUCCESS) {
243 CM_LOG_E("No cert matched, err: %d", ret);
244 }
245 return ret;
246 }
247
CmRemoveAppCert(const struct CmContext * context,const struct CmBlob * keyUri,const uint32_t store)248 int32_t CmRemoveAppCert(const struct CmContext *context, const struct CmBlob *keyUri,
249 const uint32_t store)
250 {
251 ASSERT_ARGS(context && keyUri && keyUri->data && keyUri->size);
252
253 enum CmAuthStorageLevel level;
254 int32_t ret = GetRdbAuthStorageLevel(keyUri, &level);
255 if (ret != CM_SUCCESS) {
256 CM_LOG_E("get rdb auth storage level failed, ret = %d", ret);
257 return ret;
258 }
259 if (level == ERROR_LEVEL) {
260 level = CM_AUTH_STORAGE_LEVEL_EL1;
261 CM_LOG_I("Remove cred level is ERROR_LEVEL, change to default level el1");
262 }
263
264 if (store == CM_CREDENTIAL_STORE) {
265 ret = CmAuthDeleteAuthInfo(context, keyUri, level);
266 if (ret != CM_SUCCESS) {
267 CM_LOG_E("delete auth info failed when remove app certificate."); /* ignore ret code, only record log */
268 }
269 }
270
271 ret = DeleteCertProperty((char *)keyUri->data);
272 if (ret != CM_SUCCESS) {
273 CM_LOG_E("Failed delete cert: %s rdbData", (char *)keyUri->data);
274 return ret;
275 }
276
277 char pathBuf[CERT_MAX_PATH_LEN] = {0};
278 struct CmMutableBlob path = { sizeof(pathBuf), (uint8_t*) pathBuf };
279
280 ret = CmGetFilePath(context, store, &path);
281 if (ret != CMR_OK) {
282 CM_LOG_E("Failed obtain path for store %u", store);
283 return ret;
284 }
285 ret = CertManagerFileRemove(pathBuf, (char *)keyUri->data);
286 if (ret != CMR_OK) {
287 CM_LOG_E("CertManagerFileRemove failed ret: %d", ret);
288 return ret;
289 }
290 ret = CmKeyOpDeleteKey(keyUri, level);
291 if (ret != CM_SUCCESS) { /* ignore the return of deleteKey */
292 CM_LOG_E("CertManagerKeyRemove failed, ret: %d", ret);
293 }
294
295 return CMR_OK;
296 }
297
ClearAuthInfo(const struct CmContext * context,const struct CmBlob * keyUri,const uint32_t store,enum CmAuthStorageLevel level)298 static void ClearAuthInfo(const struct CmContext *context, const struct CmBlob *keyUri, const uint32_t store,
299 enum CmAuthStorageLevel level)
300 {
301 if (store != CM_CREDENTIAL_STORE) {
302 return;
303 }
304
305 int32_t ret = CmAuthDeleteAuthInfo(context, keyUri, level);
306 if (ret != CM_SUCCESS) {
307 CM_LOG_E("delete auth info failed."); /* ignore ret code, only record log */
308 }
309 }
310
CmAppCertGetFilePath(const struct CmContext * context,const uint32_t store,struct CmBlob * path)311 static int32_t CmAppCertGetFilePath(const struct CmContext *context, const uint32_t store, struct CmBlob *path)
312 {
313 int32_t ret = CM_FAILURE;
314
315 switch (store) {
316 case CM_CREDENTIAL_STORE :
317 ret = sprintf_s((char*)path->data, MAX_PATH_LEN, "%s%u/%u", CREDNTIAL_STORE, context->userId, context->uid);
318 break;
319 case CM_PRI_CREDENTIAL_STORE :
320 ret = sprintf_s((char*)path->data, MAX_PATH_LEN, "%s%u", PRI_CREDNTIAL_STORE, context->userId);
321 break;
322 case CM_SYS_CREDENTIAL_STORE:
323 ret = sprintf_s((char *)path->data, MAX_PATH_LEN, "%s%u", SYS_CREDNTIAL_STORE, context->userId);
324 break;
325 case CM_USER_TRUSTED_STORE:
326 ret = sprintf_s((char *)path->data, MAX_PATH_LEN, "%s%u", USER_CA_STORE, context->userId);
327 break;
328 default:
329 return CMR_ERROR_INVALID_ARGUMENT_STORE_TYPE;
330 }
331 if (ret < 0) {
332 return CMR_ERROR_MEM_OPERATION_PRINT;
333 }
334 return CM_SUCCESS;
335 }
336
CmCallingAppCertGetFilePath(const struct CmContext * context,const uint32_t store,struct CmBlob * path)337 static int32_t CmCallingAppCertGetFilePath(const struct CmContext *context, const uint32_t store, struct CmBlob *path)
338 {
339 int32_t ret = CM_FAILURE;
340
341 switch (store) {
342 case CM_CREDENTIAL_STORE :
343 ret = sprintf_s((char*)path->data, MAX_PATH_LEN, "%s%u/%u",
344 CREDNTIAL_STORE, context->userId, context->uid);
345 break;
346 case CM_PRI_CREDENTIAL_STORE :
347 ret = sprintf_s((char*)path->data, MAX_PATH_LEN, "%s%u/%u",
348 PRI_CREDNTIAL_STORE, context->userId, context->uid);
349 break;
350 case CM_SYS_CREDENTIAL_STORE:
351 ret = sprintf_s((char *)path->data, MAX_PATH_LEN, "%s%u/%u",
352 SYS_CREDNTIAL_STORE, context->userId, context->uid);
353 break;
354 case CM_USER_TRUSTED_STORE:
355 ret = sprintf_s((char *)path->data, MAX_PATH_LEN, "%s%u/%u",
356 USER_CA_STORE, context->userId, context->uid);
357 break;
358 default:
359 return CMR_ERROR_INVALID_ARGUMENT_STORE_TYPE;
360 }
361 if (ret < 0) {
362 return CMR_ERROR_MEM_OPERATION_PRINT;
363 }
364 return CM_SUCCESS;
365 }
366
CmFreeFileNames(struct CmBlob * fileNames,const uint32_t fileSize)367 void CmFreeFileNames(struct CmBlob *fileNames, const uint32_t fileSize)
368 {
369 if (fileNames == NULL) {
370 CM_LOG_E("CmFreeFileNames fileNames is null");
371 return;
372 }
373
374 for (uint32_t i = 0; i < fileSize; i++) {
375 if (fileNames[i].data != NULL) {
376 CMFree(fileNames[i].data);
377 fileNames[i].size = 0;
378 }
379 }
380 }
381
CmGetUri(const char * filePath,struct CmBlob * uriBlob)382 int32_t CmGetUri(const char *filePath, struct CmBlob *uriBlob)
383 {
384 if ((filePath == NULL) || (uriBlob == NULL) || (uriBlob->data == NULL)) {
385 CM_LOG_E("CmGetUri param is null");
386 return CM_FAILURE;
387 }
388
389 uint32_t filePathLen = strlen(filePath);
390 if ((filePathLen == 0) || (filePathLen > CM_MAX_FILE_NAME_LEN)) {
391 return CMR_ERROR_INVALID_ARGUMENT;
392 }
393
394 int32_t i = (int32_t)(filePathLen - 1);
395 for (; i >= 0; i--) {
396 if (filePath[i] == '/') {
397 break;
398 }
399 }
400
401 int32_t index = i + 1; /* index range: 0 to filePathLen */
402 uint32_t uriLen = filePathLen - (uint32_t)index + 1; /* include '\0' at end, range: 1 to filePathLen + 1 */
403 if (memcpy_s(uriBlob->data, uriBlob->size, &filePath[index], uriLen) != EOK) {
404 return CMR_ERROR_BUFFER_TOO_SMALL;
405 }
406 uriBlob->size = uriLen;
407
408 return CM_SUCCESS;
409 }
410
GetUriAndDeleteRdbData(const char * filePath,struct CmBlob * uriBlob,enum CmAuthStorageLevel * level)411 static int32_t GetUriAndDeleteRdbData(const char *filePath, struct CmBlob *uriBlob, enum CmAuthStorageLevel *level)
412 {
413 int32_t ret = CmGetUri(filePath, uriBlob);
414 if (ret != CM_SUCCESS) {
415 CM_LOG_E("Get uri failed");
416 return ret;
417 }
418
419 ret = GetRdbAuthStorageLevel(uriBlob, level);
420 if (ret != CM_SUCCESS) {
421 CM_LOG_E("get rdb auth storage level failed, ret = %d", ret);
422 return ret;
423 }
424 if (*level == ERROR_LEVEL) {
425 *level = CM_AUTH_STORAGE_LEVEL_EL1;
426 CM_LOG_I("Delete rdb level is ERROR_LEVEL, change to default level el1");
427 }
428
429 ret = DeleteCertProperty((char *)uriBlob->data);
430 if (ret != CM_SUCCESS) {
431 CM_LOG_E("Failed delete cert: %s rdbData", (char *)uriBlob->data);
432 return ret;
433 }
434 return CM_SUCCESS;
435 }
436
CmRemoveSpecifiedAppCert(const struct CmContext * context,const uint32_t store)437 static int32_t CmRemoveSpecifiedAppCert(const struct CmContext *context, const uint32_t store)
438 {
439 uint32_t fileCount = 0;
440 int32_t ret = CM_SUCCESS;
441 char pathBuf[CERT_MAX_PATH_LEN] = {0};
442 char uriBuf[MAX_LEN_URI] = {0};
443 struct CmBlob fileNames[MAX_COUNT_CERTIFICATE];
444 struct CmBlob path = { sizeof(pathBuf), (uint8_t*)pathBuf };
445 struct CmBlob uriBlob = { sizeof(uriBuf), (uint8_t*)uriBuf };
446 uint32_t len = MAX_COUNT_CERTIFICATE * sizeof(struct CmBlob);
447 (void)memset_s(fileNames, len, 0, len);
448
449 do {
450 ret = CmAppCertGetFilePath(context, store, &path);
451 if (ret != CM_SUCCESS) {
452 CM_LOG_E("Get file path for store:%u faild", store);
453 break;
454 }
455
456 if (store == CM_CREDENTIAL_STORE) {
457 ret = CmUidLayerGetFileCountAndNames(pathBuf, fileNames, MAX_COUNT_CERTIFICATE, &fileCount);
458 } else {
459 ret = CmUserIdLayerGetFileCountAndNames(pathBuf, fileNames, MAX_COUNT_CERTIFICATE, &fileCount);
460 }
461 if (ret != CM_SUCCESS) {
462 CM_LOG_E("Get file count and names from path faild");
463 break;
464 }
465
466 for (uint32_t i = 0; i < fileCount; i++) {
467 if (CertManagerFileRemove(NULL, (char *)fileNames[i].data) != CM_SUCCESS) {
468 CM_LOG_E("App cert %u remove faild", i);
469 continue;
470 }
471
472 uriBlob.size = sizeof(uriBuf);
473 (void)memset_s(uriBuf, uriBlob.size, 0, uriBlob.size);
474 enum CmAuthStorageLevel level;
475 if (GetUriAndDeleteRdbData((char *)fileNames[i].data, &uriBlob, &level) != CM_SUCCESS) {
476 CM_LOG_E("Get uri failed");
477 continue;
478 }
479
480 int32_t retCode = CmKeyOpDeleteKey(&uriBlob, level);
481 if (retCode != CM_SUCCESS) { /* ignore the return of deleteKey */
482 CM_LOG_E("App key %u remove failed ret: %d", i, retCode);
483 }
484 ClearAuthInfo(context, &uriBlob, store, level);
485 }
486 } while (0);
487 CmFreeFileNames(fileNames, MAX_COUNT_CERTIFICATE);
488 return ret;
489 }
490
CmRemoveAllAppCert(const struct CmContext * context)491 int32_t CmRemoveAllAppCert(const struct CmContext *context)
492 {
493 if (!CmHasPrivilegedPermission() || !CmHasCommonPermission() || !CmHasSystemAppPermission()) {
494 CM_LOG_E("permission check failed");
495 return CMR_ERROR_PERMISSION_DENIED;
496 }
497 if (!CmIsSystemApp()) {
498 CM_LOG_E("remove app cert: caller is not system app");
499 return CMR_ERROR_NOT_SYSTEMP_APP;
500 }
501
502 /* Only public and private credential removed can be returned */
503 /* remove pubic credential app cert */
504 int32_t ret = CmRemoveSpecifiedAppCert(context, CM_CREDENTIAL_STORE);
505 if (ret != CM_SUCCESS) {
506 CM_LOG_E("remove pubic credential app cert faild");
507 }
508
509 /* remove private credential app cert */
510 ret = CmRemoveSpecifiedAppCert(context, CM_PRI_CREDENTIAL_STORE);
511 if (ret != CM_SUCCESS) {
512 CM_LOG_E("remove private credential app cert faild");
513 }
514
515 /* remove system credential app cert */
516 ret = CmRemoveSpecifiedAppCert(context, CM_SYS_CREDENTIAL_STORE);
517 if (ret != CM_SUCCESS) {
518 CM_LOG_E("remove system credential app cert faild");
519 }
520
521 return ret;
522 }
523
CmServiceGetAppCertList(const struct CmContext * context,uint32_t store,struct CmBlob * fileNames,const uint32_t fileSize,uint32_t * fileCount)524 int32_t CmServiceGetAppCertList(const struct CmContext *context, uint32_t store, struct CmBlob *fileNames,
525 const uint32_t fileSize, uint32_t *fileCount)
526 {
527 char pathBuf[CERT_MAX_PATH_LEN] = {0};
528 struct CmBlob path = { sizeof(pathBuf), (uint8_t*)pathBuf };
529
530 int32_t ret = CmAppCertGetFilePath(context, store, &path);
531 if (ret != CM_SUCCESS) {
532 CM_LOG_E("Get file path for store:%u faild", store);
533 return CM_FAILURE;
534 }
535
536 if (store == CM_CREDENTIAL_STORE) {
537 ret = CmUidLayerGetFileCountAndNames(pathBuf, fileNames, fileSize, fileCount);
538 } else {
539 ret = CmUserIdLayerGetFileCountAndNames(pathBuf, fileNames, fileSize, fileCount);
540 }
541 if (ret != CM_SUCCESS) {
542 CM_LOG_E("Get file count and names from path faild ret:%d", ret);
543 return ret;
544 }
545
546 return CM_SUCCESS;
547 }
548
CmServiceGetCallingAppCertList(const struct CmContext * context,uint32_t store,struct CmBlob * fileNames,const uint32_t fileSize,uint32_t * fileCount)549 int32_t CmServiceGetCallingAppCertList(const struct CmContext *context, uint32_t store, struct CmBlob *fileNames,
550 const uint32_t fileSize, uint32_t *fileCount)
551 {
552 char pathBuf[CERT_MAX_PATH_LEN] = {0};
553 struct CmBlob path = { sizeof(pathBuf), (uint8_t*)pathBuf };
554
555 int32_t ret = CmCallingAppCertGetFilePath(context, store, &path);
556 if (ret != CM_SUCCESS) {
557 CM_LOG_E("Get file path for store:%u faild", store);
558 return CM_FAILURE;
559 }
560
561 ret = CmUidLayerGetFileCountAndNames(pathBuf, fileNames, fileSize, fileCount);
562 if (ret != CM_SUCCESS) {
563 CM_LOG_E("Get file count and names from path faild ret:%d", ret);
564 return ret;
565 }
566
567 return CM_SUCCESS;
568 }
569
GetCertOrCredCount(const struct CmContext * context,const uint32_t store,uint32_t * certCount)570 int32_t GetCertOrCredCount(const struct CmContext *context, const uint32_t store, uint32_t *certCount)
571 {
572 if (context == NULL || certCount == NULL) {
573 CM_LOG_E("null pointer");
574 return CMR_ERROR_NULL_POINTER;
575 }
576 uint32_t fileCount = 0;
577 struct CmBlob fileNames[MAX_COUNT_CERTIFICATE];
578 uint32_t len = MAX_COUNT_CERTIFICATE * sizeof(struct CmBlob);
579 (void)memset_s(fileNames, len, 0, len);
580
581 int32_t ret = CmServiceGetAppCertList(context, store, fileNames, MAX_COUNT_CERTIFICATE, &fileCount);
582 CmFreeFileNames(fileNames, MAX_COUNT_CERTIFICATE);
583 if (ret != CM_SUCCESS) {
584 CM_LOG_E("Failed to get app cert list");
585 return ret;
586 }
587
588 *certCount = fileCount;
589 return CM_SUCCESS;
590 }
591
CmCheckCertCount(const struct CmContext * context,const uint32_t store,const char * fileName)592 int32_t CmCheckCertCount(const struct CmContext *context, const uint32_t store, const char *fileName)
593 {
594 if (context == NULL || fileName == NULL) {
595 return CMR_ERROR_INVALID_ARGUMENT;
596 }
597
598 int32_t ret = CM_FAILURE;
599 do {
600 uint32_t certCount = 0;
601 int32_t retVal = GetCertOrCredCount(context, store, &certCount);
602 if (retVal != CM_SUCCESS) {
603 CM_LOG_E("Failed obtain cert count for store:%u", store);
604 break;
605 }
606 if (certCount < MAX_COUNT_CERTIFICATE) {
607 ret = CM_SUCCESS;
608 break;
609 }
610
611 char pathBuf[CERT_MAX_PATH_LEN] = {0};
612 retVal = ConstructUidPath(context, store, pathBuf, sizeof(pathBuf));
613 if (retVal != CM_SUCCESS) {
614 CM_LOG_E("Failed obtain path for store:%u", store);
615 break;
616 }
617
618 char fullFileName[CM_MAX_FILE_NAME_LEN] = {0};
619 if (snprintf_s(fullFileName, CM_MAX_FILE_NAME_LEN, CM_MAX_FILE_NAME_LEN - 1, "%s/%s", pathBuf, fileName) < 0) {
620 CM_LOG_E("mkdir full name failed");
621 ret = CMR_ERROR_MEM_OPERATION_PRINT;
622 break;
623 }
624
625 if (access(fullFileName, F_OK) == 0) {
626 ret = CM_SUCCESS;
627 break;
628 }
629 } while (0);
630 return ret;
631 }
632
ConstructCertUri(const struct CmContext * context,const struct CmBlob * certAlias,struct CmBlob * certUri)633 static int32_t ConstructCertUri(const struct CmContext *context, const struct CmBlob *certAlias,
634 struct CmBlob *certUri)
635 {
636 struct CmBlob commonUri = { 0, NULL };
637 int32_t ret;
638 do {
639 ret = CmConstructCommonUri(context, CM_URI_TYPE_CERTIFICATE, certAlias, &commonUri);
640 if (ret != CM_SUCCESS) {
641 CM_LOG_E("construct cert uri get common uri failed");
642 break;
643 }
644
645 if (certUri->size < commonUri.size) {
646 CM_LOG_E("out cert uri size[%u] too small", certUri->size);
647 ret = CMR_ERROR_BUFFER_TOO_SMALL;
648 break;
649 }
650
651 if (memcpy_s(certUri->data, certUri->size, commonUri.data, commonUri.size) != EOK) {
652 CM_LOG_E("copy cert uri failed");
653 ret = CMR_ERROR_MEM_OPERATION_COPY;
654 break;
655 }
656
657 certUri->size = commonUri.size;
658 } while (0);
659
660 CM_FREE_PTR(commonUri.data);
661 return ret;
662 }
663
CmWriteUserCert(const struct CmContext * context,struct CmMutableBlob * pathBlob,const struct CmBlob * userCert,const struct CmBlob * certAlias,struct CmBlob * certUri)664 int32_t CmWriteUserCert(const struct CmContext *context, struct CmMutableBlob *pathBlob,
665 const struct CmBlob *userCert, const struct CmBlob *certAlias, struct CmBlob *certUri)
666 {
667 if (certAlias->size > MAX_LEN_CERT_ALIAS) {
668 CM_LOG_E("alias size[%u] is too large", certAlias->size);
669 return CMR_ERROR_ALIAS_LENGTH_REACHED_LIMIT;
670 }
671
672 int32_t ret;
673 do {
674 ret = ConstructCertUri(context, certAlias, certUri);
675 if (ret != CM_SUCCESS) {
676 CM_LOG_E("get cert uri failed");
677 break;
678 }
679
680 if (certUri->size > MAX_LEN_URI) {
681 CM_LOG_E("uri size is too large");
682 ret = CMR_ERROR_INVALID_ARGUMENT;
683 break;
684 }
685
686 ret = CmCheckCertCount(context, CM_USER_TRUSTED_STORE, (char *)certUri->data);
687 if (ret != CM_SUCCESS) {
688 CM_LOG_E("cert count beyond maxcount, can't install");
689 ret = CMR_ERROR_MAX_CERT_COUNT_REACHED;
690 break;
691 }
692
693 if (CmFileWrite((char*)pathBlob->data, (char *)certUri->data, 0, userCert->data, userCert->size) != CMR_OK) {
694 CM_LOG_E("Failed to write certificate");
695 ret = CMR_ERROR_WRITE_FILE_FAIL;
696 break;
697 }
698 } while (0);
699 return ret;
700 }
701
CmGetDisplayNameByURI(const struct CmBlob * uri,const char * object,struct CmBlob * displayName)702 int32_t CmGetDisplayNameByURI(const struct CmBlob *uri, const char *object, struct CmBlob *displayName)
703 {
704 if ((CmCheckBlob(uri) != CM_SUCCESS) || (object == NULL) ||
705 (CmCheckBlob(displayName) != CM_SUCCESS)) {
706 CM_LOG_E("input param is invalid");
707 return CMR_ERROR_INVALID_ARGUMENT;
708 }
709 int32_t ret = CM_SUCCESS;
710 struct CertProperty certProperty;
711 (void)memset_s(&certProperty, sizeof(struct CertProperty), 0, sizeof(struct CertProperty));
712 ret = QueryCertProperty((char *)uri->data, &certProperty);
713 if (ret != CM_SUCCESS) {
714 CM_LOG_E("Failed to query certProperty, ret=%d", ret);
715 return ret;
716 }
717 const char *temp = NULL;
718 if (strlen(certProperty.uri) != 0) {
719 temp = (const char *)certProperty.alias;
720 } else {
721 temp = object;
722 }
723 if (memcpy_s(displayName->data, displayName->size, temp, strlen(temp) + 1) != CM_SUCCESS) {
724 CM_LOG_E("Failed to copy displayName->data");
725 ret = CMR_ERROR_MEM_OPERATION_COPY;
726 }
727 displayName->size = strlen(temp) + 1;
728 return ret;
729 }
730
GetCertType(uint32_t store)731 static const char* GetCertType(uint32_t store)
732 {
733 switch (store) {
734 case CM_USER_TRUSTED_STORE:
735 return "c";
736
737 case CM_CREDENTIAL_STORE:
738 return "ak";
739
740 case CM_PRI_CREDENTIAL_STORE:
741 return "ak";
742
743 case CM_SYS_CREDENTIAL_STORE:
744 return "sk";
745
746 default:
747 return NULL;
748 }
749 return NULL;
750 }
751
RdbInsertCertProperty(const struct CertPropertyOri * propertyOri)752 int32_t RdbInsertCertProperty(const struct CertPropertyOri *propertyOri)
753 {
754 struct CertProperty certProp;
755 (void)memset_s(&certProp, sizeof(struct CertProperty), 0, sizeof(struct CertProperty));
756 certProp.userId = (int32_t)propertyOri->context->userId;
757 certProp.uid = (int32_t)propertyOri->context->uid;
758 certProp.level = propertyOri->level;
759
760 const char *certType = GetCertType(propertyOri->store);
761 if (certType == NULL) {
762 CM_LOG_E("Type does not support installation");
763 return CMR_ERROR_INVALID_ARGUMENT;
764 }
765 certProp.certStore = (int32_t)propertyOri->store;
766 if (memcpy_s(certProp.certType, MAX_LEN_CERT_TYPE, certType, strlen(certType)) != EOK) {
767 CM_LOG_E("memcpy certType fail");
768 return CMR_ERROR_MEM_OPERATION_COPY;
769 }
770
771 if (memcpy_s(certProp.uri, MAX_LEN_URI, (char *)propertyOri->uri->data, propertyOri->uri->size) != EOK) {
772 CM_LOG_E("memcpy uri fail");
773 return CMR_ERROR_MEM_OPERATION_COPY;
774 }
775 if (memcpy_s(certProp.alias, MAX_LEN_CERT_ALIAS, (char *)propertyOri->alias->data, propertyOri->alias->size)
776 != EOK) {
777 CM_LOG_E("memcpy subjectName fail");
778 return CMR_ERROR_MEM_OPERATION_COPY;
779 }
780 if (memcpy_s(certProp.subjectName, MAX_LEN_SUBJECT_NAME, (char *)propertyOri->subjectName->data,
781 propertyOri->subjectName->size) != EOK) {
782 CM_LOG_E("memcpy subjectName fail");
783 return CMR_ERROR_MEM_OPERATION_COPY;
784 }
785
786 int32_t ret = InsertCertProperty(&certProp);
787 if (ret != CM_SUCCESS) {
788 CM_LOG_E("Failed to InsertCertProperty");
789 return ret;
790 }
791 return CM_SUCCESS;
792 }
793
CmStoreUserCert(const char * path,const struct CmBlob * userCert,const char * userCertName)794 int32_t CmStoreUserCert(const char *path, const struct CmBlob *userCert, const char *userCertName)
795 {
796 int32_t ret = CM_SUCCESS;
797 if (CmUserBackupFileWrite(path, userCertName, 0, userCert->data, userCert->size) != CMR_OK) {
798 CM_LOG_E("Failed to write certificate");
799 ret = CMR_ERROR_WRITE_FILE_FAIL;
800 }
801 return ret;
802 }
803
CmGenerateSaConf(const char * userCertConfigPath,const char * userCertBakupDirPath,const char * userCertName)804 int32_t CmGenerateSaConf(const char *userCertConfigPath, const char *userCertBakupDirPath, const char *userCertName)
805 {
806 int32_t ret = CM_SUCCESS;
807 char userCertBackupFilePath[CERT_MAX_PATH_LEN] = { 0 };
808
809 if (userCertBakupDirPath == NULL) {
810 if (snprintf_s(userCertBackupFilePath, CERT_MAX_PATH_LEN, CERT_MAX_PATH_LEN - 1, "%s", userCertName) < 0) {
811 CM_LOG_E("construct userCertBackupFilePath failed");
812 return CMR_ERROR_MEM_OPERATION_PRINT;
813 }
814 } else {
815 if (snprintf_s(userCertBackupFilePath, CERT_MAX_PATH_LEN, CERT_MAX_PATH_LEN - 1, "%s/%s", userCertBakupDirPath,
816 userCertName) < 0) {
817 CM_LOG_E("construct userCertBackupFilePath failed");
818 return CMR_ERROR_MEM_OPERATION_PRINT;
819 }
820 }
821
822 if (CmFileWrite(NULL, userCertConfigPath, 0, (const uint8_t *)userCertBackupFilePath,
823 strlen(userCertBackupFilePath)) != CMR_OK) {
824 CM_LOG_E("Failed to write saconf file content");
825 ret = CMR_ERROR_WRITE_FILE_FAIL;
826 }
827 return ret;
828 }
829
CmRemoveUserCert(struct CmMutableBlob * pathBlob,const struct CmBlob * certUri)830 int32_t CmRemoveUserCert(struct CmMutableBlob *pathBlob, const struct CmBlob *certUri)
831 {
832 return CertManagerFileRemove((char *)pathBlob->data, (char *)certUri->data);
833 }
834
CmBackupRemove(uint32_t userId,const char * path,const struct CmBlob * certUri)835 int32_t CmBackupRemove(uint32_t userId, const char *path, const struct CmBlob *certUri)
836 {
837 if (path == NULL) {
838 CM_LOG_E("input params is invaild");
839 return CMR_ERROR_INVALID_ARGUMENT;
840 }
841
842 uint32_t uid = 0;
843 char *uidStr = basename((char *)path);
844 if (CmIsNumeric(uidStr, strlen(uidStr) + 1, &uid) != CM_SUCCESS) {
845 CM_LOG_E("parse string to uint32 failed.");
846 return CMR_ERROR_INVALID_ARGUMENT;
847 }
848
849 char userCertConfigFilePath[CERT_MAX_PATH_LEN] = { 0 };
850 int32_t ret = CmGetCertConfPath(userId, uid, certUri, userCertConfigFilePath, CERT_MAX_PATH_LEN);
851 if (ret != CM_SUCCESS) {
852 CM_LOG_E("Get user cert config path failed ret = %d", ret);
853 return CM_FAILURE;
854 }
855
856 ret = CmRemoveBackupUserCert(NULL, NULL, userCertConfigFilePath);
857 if (ret != CMR_OK) {
858 CM_LOG_E("User Cert remove config and backup file failed, ret: %d", ret);
859 }
860 return ret;
861 }
862
RemoveAllUserCert(const struct CmContext * context,uint32_t store,const char * path)863 static int32_t RemoveAllUserCert(const struct CmContext *context, uint32_t store, const char* path)
864 {
865 ASSERT_ARGS(path);
866 struct CmMutableBlob fileNames = { 0, NULL };
867 struct CmBlob certUri = { 0, NULL };
868 int32_t ret = CertManagerGetFilenames(&fileNames, path);
869 if (ret != CM_SUCCESS) {
870 CM_LOG_E("Failed obtain filenames from path");
871 return ret;
872 }
873
874 struct CmMutableBlob *fNames = (struct CmMutableBlob *)fileNames.data;
875 for (uint32_t i = 0; i < fileNames.size; i++) {
876 certUri.data = (uint8_t *)fNames[i].data;
877 certUri.size = fNames[i].size - 1;
878 ret = CertManagerFileRemove(path, (char *)fNames[i].data);
879 if (ret != CMR_OK) {
880 CM_LOG_E("User Cert %u remove failed, ret: %d", i, ret);
881 continue;
882 }
883 ret = CmBackupRemove(context->userId, path, &certUri);
884 if (ret != CMR_OK) {
885 CM_LOG_E("User Cert %u remove config and backup file failed, ret: %d", i, ret);
886 }
887 ret = DeleteCertProperty((char *)certUri.data);
888 if (ret != CM_SUCCESS) {
889 CM_LOG_E("Failed delete cert: %s rdbData", (char *)certUri.data);
890 }
891 }
892
893 FreeFileNames(fNames, fileNames.size);
894 return ret;
895 }
896
RemoveAllUidDir(const char * path)897 static int32_t RemoveAllUidDir(const char* path)
898 {
899 return CM_ERROR(CmDirRemove(path));
900 }
901
RemoveAllConfUidDir(uint32_t userId,const char * uidPath)902 static int32_t RemoveAllConfUidDir(uint32_t userId, const char *uidPath)
903 {
904 if (uidPath == NULL) {
905 CM_LOG_E("input params is invaild");
906 return CMR_ERROR_INVALID_ARGUMENT;
907 }
908 char configUidDirPath[CERT_MAX_PATH_LEN] = { 0 };
909 uint32_t uid = 0;
910 char *uidStr = basename((char *)uidPath);
911 if (CmIsNumeric(uidStr, strlen(uidStr) + 1, &uid) != CM_SUCCESS) {
912 CM_LOG_E("parse string to uint32 failed.");
913 return CMR_ERROR_INVALID_ARGUMENT;
914 }
915
916 int32_t ret = CmGetCertConfUidDir(userId, uid, configUidDirPath, CERT_MAX_PATH_LEN);
917 if (ret != CM_SUCCESS) {
918 CM_LOG_E("Get user cert config file UidDirPath failed, ret = %d", ret);
919 return ret;
920 }
921
922 ret = CmDirRemove(configUidDirPath);
923 if (ret != CM_SUCCESS) {
924 CM_LOG_E("Remove user cert config file configUidDirPath fail, ret = %d", ret);
925 }
926 return ret;
927 }
928
CmRemoveAllUserCert(const struct CmContext * context,uint32_t store,const struct CmMutableBlob * pathList)929 int32_t CmRemoveAllUserCert(const struct CmContext *context, uint32_t store, const struct CmMutableBlob *pathList)
930 {
931 ASSERT_ARGS(pathList && pathList->data && pathList->size);
932 int32_t ret = CM_SUCCESS;
933 struct CmMutableBlob *path = (struct CmMutableBlob *)pathList->data;
934
935 for (uint32_t i = 0; i < pathList->size; i++) {
936 ret = RemoveAllUserCert(context, store, (char *)path[i].data);
937 if (ret != CM_SUCCESS) {
938 CM_LOG_E("Failed remove usercert at %u_th dir", i);
939 continue;
940 }
941 ret = RemoveAllUidDir((char *)path[i].data);
942 if (ret != CM_SUCCESS) {
943 CM_LOG_E("Remove UidPath fail, ret = %d", ret);
944 continue;
945 }
946 ret = RemoveAllConfUidDir(context->userId, (char *)path[i].data);
947 if (ret != CM_SUCCESS) {
948 CM_LOG_E("Remove all config UidPath fail, ret = %d", ret);
949 continue;
950 }
951 }
952 return ret;
953 }
954
CmRemoveBackupUserCert(const struct CmContext * context,const struct CmBlob * certUri,const char * userCertConfigFilePath)955 int32_t CmRemoveBackupUserCert(const struct CmContext *context, const struct CmBlob *certUri,
956 const char *userCertConfigFilePath)
957 {
958 int32_t ret = CM_SUCCESS;
959 char userConfigFilePath[CERT_MAX_PATH_LEN] = { 0 };
960 char *userConfFilePath = NULL;
961
962 if (userCertConfigFilePath == NULL) {
963 if ((context == NULL) || (CmCheckBlob(certUri) != CM_SUCCESS)) {
964 CM_LOG_E("Invalid input arguments");
965 return CMR_ERROR_INVALID_ARGUMENT;
966 }
967
968 ret = CmGetCertConfPath(context->userId, context->uid, certUri, userConfigFilePath, CERT_MAX_PATH_LEN);
969 if (ret != CM_SUCCESS) {
970 CM_LOG_E("CmGetCertConfPath failed, ret = %d", ret);
971 return ret;
972 }
973 userConfFilePath = userConfigFilePath;
974 } else {
975 userConfFilePath = (char *)userCertConfigFilePath;
976 }
977
978 ret = CmRmUserCert(userConfFilePath);
979 if (ret != CM_SUCCESS) {
980 CM_LOG_E("RmUserCertFile failed, ret = %d", ret);
981 return ret;
982 }
983
984 ret = CmRmSaConf(userConfFilePath);
985 if (ret != CM_SUCCESS) {
986 CM_LOG_E("RmSaConfFile fail, ret = %d", ret);
987 return ret;
988 }
989
990 return CM_SUCCESS;
991 }
992
GetObjNameFromCertData(const struct CmBlob * certData,const struct CmBlob * certAlias,struct CmBlob * objectName)993 int32_t GetObjNameFromCertData(const struct CmBlob *certData, const struct CmBlob *certAlias,
994 struct CmBlob *objectName)
995 {
996 if ((CmCheckBlob(certData) != CM_SUCCESS) || (CmCheckBlob(certAlias) != CM_SUCCESS) || (objectName == NULL)) {
997 CM_LOG_E("input param is invalid");
998 return CMR_ERROR_INVALID_ARGUMENT;
999 }
1000 struct CmBlob object = { certAlias->size, certAlias->data };
1001 uint8_t encodeBuf[MAX_LEN_BASE64URL_SHA256] = { 0 };
1002 struct CmBlob encodeTarget = { sizeof(encodeBuf), encodeBuf };
1003 if (strcmp("", (char *)certAlias->data) == 0) {
1004 int32_t ret = GetNameEncode(certData, &encodeTarget);
1005 if (ret != CM_SUCCESS) {
1006 CM_LOG_E("base64urlsha256 failed");
1007 return ret;
1008 }
1009 object.data = encodeTarget.data;
1010 object.size = encodeTarget.size;
1011 }
1012
1013 if (memcpy_s(objectName->data, objectName->size, object.data, object.size) != CM_SUCCESS) {
1014 CM_LOG_E("memcpy object name failed");
1015 return CMR_ERROR_MEM_OPERATION_COPY;
1016 }
1017 return CM_SUCCESS;
1018 }
1019 #ifdef __cplusplus
1020 }
1021 #endif
1022 // LCOV_EXCL_STOP