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_query.h"
17
18 #include "securec.h"
19 #include "cm_cert_property_rdb.h"
20 #include "cm_log.h"
21 #include "cm_type.h"
22 #include "cm_x509.h"
23 #include "cert_manager_file.h"
24 #include "cert_manager_mem.h"
25 #include "cert_manager_uri.h"
26 #include "cert_manager_storage.h"
27 #include "cert_manager_status.h"
28 #include "cert_manager_file_operator.h"
29
30 #define MAX_PATH_LEN 256
31
MallocCertPath(struct CmMutableBlob * cPath,const char * path)32 static int32_t MallocCertPath(struct CmMutableBlob *cPath, const char *path)
33 {
34 uint32_t pathSize = strlen(path) + 1;
35 cPath->data = (uint8_t *)CMMalloc(pathSize);
36 if (cPath->data == NULL) {
37 CM_LOG_E("malloc cPathLists failed");
38 return CMR_ERROR_MALLOC_FAIL;
39 }
40 cPath->size = pathSize;
41 (void)memset_s(cPath->data, pathSize, 0, pathSize);
42 return CM_SUCCESS;
43 }
44
CmFreePathList(struct CmMutableBlob * pList,uint32_t pathCount)45 void CmFreePathList(struct CmMutableBlob *pList, uint32_t pathCount)
46 {
47 if (pList == NULL) {
48 return;
49 }
50
51 for (uint32_t i = 0; i < pathCount; i++) {
52 pList[i].size = 0;
53 CM_FREE_PTR(pList[i].data);
54 }
55 CM_FREE_PTR(pList);
56 }
57
ConstrutPathList(const char * useridPath,struct CmMutableBlob * cPathList,uint32_t dirCount)58 static int32_t ConstrutPathList(const char *useridPath, struct CmMutableBlob *cPathList, uint32_t dirCount)
59 {
60 int32_t ret = CM_SUCCESS;
61 void *d = CmOpenDir(useridPath);
62 if (d == NULL) {
63 CM_LOG_E("Failed to open directory");
64 return CM_FAILURE;
65 }
66
67 uint32_t dealCert = 0;
68 struct CmFileDirentInfo dire = {0};
69 while (CmGetSubDir(d, &dire) == CMR_OK) {
70 if (dealCert >= dirCount) {
71 CM_LOG_E("uid dir count beyond dirCount");
72 break;
73 }
74
75 char pathBuf[MAX_PATH_LEN] = {0};
76 if (sprintf_s(pathBuf, MAX_PATH_LEN, "%s/%s", useridPath, dire.fileName) < 0) {
77 CM_LOG_E("copy uid path failed");
78 ret = CM_FAILURE;
79 break;
80 }
81
82 ret = MallocCertPath(&cPathList[dealCert], pathBuf); /* uniformly free memory by caller */
83 if (ret != CM_SUCCESS) {
84 break;
85 }
86
87 if (sprintf_s((char *)cPathList[dealCert].data, cPathList[dealCert].size, "%s", pathBuf) < 0) {
88 ret = CM_FAILURE;
89 break;
90 }
91 dealCert++;
92 }
93
94 (void) CmCloseDir(d);
95 if (dealCert != dirCount) { /* real dir count less than dirCount */
96 ret = CM_FAILURE;
97 }
98 return ret;
99 }
100
CreateCertPathList(const char * useridPath,struct CmMutableBlob * pathList)101 static int32_t CreateCertPathList(const char *useridPath, struct CmMutableBlob *pathList)
102 {
103 int32_t uidCount = GetNumberOfDirs(useridPath);
104 if (uidCount < 0) {
105 CM_LOG_E("Failed to obtain number of uid from path");
106 return CM_FAILURE;
107 }
108
109 if (uidCount == 0) {
110 return CM_SUCCESS;
111 }
112
113 if (uidCount > MAX_COUNT_CERTIFICATE) {
114 CM_LOG_E("uidCount beyond max");
115 return CM_FAILURE;
116 }
117
118 uint32_t arraySize = sizeof(struct CmMutableBlob) * (uint32_t)uidCount;
119 struct CmMutableBlob *cPathList = (struct CmMutableBlob *)CMMalloc(arraySize);
120 if (cPathList == NULL) {
121 CM_LOG_E("malloc cPathList failed");
122 return CMR_ERROR_MALLOC_FAIL;
123 }
124 (void)memset_s(cPathList, arraySize, 0, arraySize);
125
126 int32_t ret = ConstrutPathList(useridPath, cPathList, (uint32_t)uidCount);
127 if (ret != CM_SUCCESS) {
128 CM_LOG_E("construct cPathList failed");
129 CmFreePathList(cPathList, uidCount);
130 return ret;
131 }
132
133 pathList->data = (uint8_t *)cPathList;
134 pathList->size = (uint32_t)uidCount;
135
136 return CM_SUCCESS;
137 }
138
CmGetCertPathList(const struct CmContext * context,uint32_t store,struct CmMutableBlob * pathList)139 int32_t CmGetCertPathList(const struct CmContext *context, uint32_t store, struct CmMutableBlob *pathList)
140 {
141 char userIdPath[MAX_PATH_LEN] = {0};
142
143 int32_t ret = ConstructUserIdPath(context, store, userIdPath, MAX_PATH_LEN);
144 if (ret != CM_SUCCESS) {
145 CM_LOG_E("Failed obtain userpath for store %u", store);
146 return ret;
147 }
148
149 ret = CreateCertPathList(userIdPath, pathList);
150 if (ret != CM_SUCCESS) {
151 CM_LOG_E("Failed create pathList for userid %u", context->userId);
152 return ret;
153 }
154
155 return CM_SUCCESS;
156 }
157
CmGetSysCertPathList(const struct CmContext * context,struct CmMutableBlob * pathList)158 int32_t CmGetSysCertPathList(const struct CmContext *context, struct CmMutableBlob *pathList)
159 {
160 uint32_t sysPathCnt = 1; /* system root ca path only have one layer */
161 uint32_t listSize = sizeof(struct CmMutableBlob) * sysPathCnt;
162 struct CmMutableBlob *cPathList = (struct CmMutableBlob *)CMMalloc(listSize);
163 if (cPathList == NULL) {
164 CM_LOG_E("malloc cPathList failed");
165 return CMR_ERROR_MALLOC_FAIL;
166 }
167 (void)memset_s(cPathList, listSize, 0, listSize);
168
169 int32_t ret = MallocCertPath(&cPathList[0], SYSTEM_CA_STORE);
170 if (ret != CM_SUCCESS) {
171 CM_LOG_E("malloc cPathList[0] failed");
172 CmFreePathList(cPathList, sysPathCnt);
173 return ret;
174 }
175
176 if (sprintf_s((char *)cPathList[0].data, cPathList[0].size, "%s", SYSTEM_CA_STORE) < 0) {
177 CM_LOG_E("sprintf_s path failed");
178 CmFreePathList(cPathList, sysPathCnt);
179 return CMR_ERROR_INVALID_OPERATION;
180 }
181
182 pathList->data = (uint8_t *)cPathList;
183 pathList->size = sysPathCnt;
184
185 return CM_SUCCESS;
186 }
187
CmFreeCertFiles(struct CertFileInfo * cFileList,uint32_t certCount)188 void CmFreeCertFiles(struct CertFileInfo *cFileList, uint32_t certCount)
189 {
190 if (cFileList == NULL) {
191 return;
192 }
193
194 for (uint32_t i = 0; i < certCount; i++) {
195 cFileList[i].path.size = 0;
196 CM_FREE_PTR(cFileList[i].path.data);
197
198 cFileList[i].fileName.size = 0;
199 CM_FREE_PTR(cFileList[i].fileName.data);
200 }
201 CMFree(cFileList);
202 }
203
MallocCertNameAndPath(struct CertFileInfo * certFile,const char * path,const char * fName)204 static int32_t MallocCertNameAndPath(struct CertFileInfo *certFile, const char *path,
205 const char *fName)
206 {
207 uint32_t pathSize = strlen(path) + 1;
208 certFile->path.data = (uint8_t *)CMMalloc(pathSize);
209 if (certFile->path.data == NULL) {
210 CM_LOG_E("malloc path data failed");
211 return CMR_ERROR_MALLOC_FAIL;
212 }
213 certFile->path.size = pathSize;
214 (void)memset_s(certFile->path.data, pathSize, 0, pathSize);
215
216 uint32_t nameSize = strlen(fName) + 1;
217 certFile->fileName.data = (uint8_t *)CMMalloc(nameSize);
218 if (certFile->fileName.data == NULL) {
219 CM_LOG_E("malloc filename data failed");
220 return CMR_ERROR_MALLOC_FAIL;
221 }
222 certFile->fileName.size = nameSize;
223 (void)memset_s(certFile->fileName.data, nameSize, 0, nameSize);
224
225 return CM_SUCCESS;
226 }
227
GetCertNameAndPath(struct CertFileInfo * certFile,const char * path,const char * fileName)228 static int32_t GetCertNameAndPath(struct CertFileInfo *certFile, const char *path, const char *fileName)
229 {
230 int32_t ret = MallocCertNameAndPath(certFile, path, fileName); /* uniformly free memory by caller */
231 if (ret != CM_SUCCESS) {
232 CM_LOG_E("malloc certfile for cert failed");
233 return ret;
234 }
235
236 if (sprintf_s((char *)certFile->path.data, certFile->path.size, "%s", path) < 0) {
237 CM_LOG_E("copy path failed");
238 return CM_FAILURE;
239 }
240
241 if (sprintf_s((char *)certFile->fileName.data, certFile->fileName.size, "%s", fileName) < 0) {
242 CM_LOG_E("copy file name failed");
243 return CM_FAILURE;
244 }
245
246 return ret;
247 }
248
CreateCertFile(struct CertFileInfo * cFileList,const char * path,uint32_t * certCount)249 static int32_t CreateCertFile(struct CertFileInfo *cFileList, const char *path, uint32_t *certCount)
250 {
251 if (path == NULL) {
252 CM_LOG_E("invaild path");
253 return CMR_ERROR_INVALID_ARGUMENT;
254 }
255
256 int32_t fileNums = GetCertCount(path);
257 if (fileNums == 0) {
258 CM_LOG_D("no cert file in path");
259 return CM_SUCCESS;
260 }
261
262 if (fileNums < 0) {
263 CM_LOG_E("Failed to obtain number of files");
264 return CM_FAILURE;
265 }
266
267 void *isOpen = CmOpenDir(path);
268 if (isOpen == NULL) {
269 CM_LOG_E("Failed to open directory");
270 return CM_FAILURE;
271 }
272
273 int32_t ret;
274 uint32_t getCount = *certCount;
275 struct CmFileDirentInfo dire = {0};
276 while (CmGetDirFile(isOpen, &dire) == CMR_OK) {
277 if (getCount >= MAX_COUNT_CERTIFICATE_ALL) {
278 CM_LOG_E("cert count beyond MAX");
279 break;
280 }
281 ret = GetCertNameAndPath(&cFileList[getCount], path, dire.fileName);
282 if (ret != CM_SUCCESS) {
283 CM_LOG_E("malloc certfile for cert failed");
284 break;
285 }
286
287 getCount++;
288 }
289
290 (void) CmCloseDir(isOpen);
291 uint32_t realCount = getCount - *certCount;
292 *certCount += realCount;
293 if (realCount != (uint32_t)fileNums) {
294 return CM_FAILURE;
295 }
296 return ret;
297 }
298
CreateCertFileList(const struct CmMutableBlob * pathList,struct CmMutableBlob * certFileList)299 int32_t CreateCertFileList(const struct CmMutableBlob *pathList, struct CmMutableBlob *certFileList)
300 {
301 if (pathList->size == 0) {
302 return CM_SUCCESS;
303 }
304
305 uint32_t arraySize = sizeof(struct CertFileInfo) * MAX_COUNT_CERTIFICATE_ALL;
306 struct CertFileInfo *cFileList = (struct CertFileInfo *)CMMalloc(arraySize);
307 if (cFileList == NULL) {
308 CM_LOG_E("malloc cFileList failed");
309 return CMR_ERROR_MALLOC_FAIL;
310 }
311 (void)memset_s(cFileList, arraySize, 0, arraySize);
312
313 int32_t ret = CM_SUCCESS;
314 uint32_t certCount = 0;
315 struct CmMutableBlob *uidPath = (struct CmMutableBlob *)pathList->data;
316
317 for (uint32_t i = 0; i < pathList->size; i++) {
318 ret = CreateCertFile(cFileList, (char *)uidPath[i].data, &certCount);
319 if (ret != CM_SUCCESS) {
320 CM_LOG_E("Create CertFile fail of %u_th", i);
321 CmFreeCertFiles(cFileList, certCount);
322 return ret;
323 }
324 }
325 certFileList->data = (uint8_t *)cFileList;
326 certFileList->size = certCount;
327 return ret;
328 }
329
CmMallocCertBlob(struct CertBlob * certBlob,uint32_t certCount)330 static int32_t CmMallocCertBlob(struct CertBlob *certBlob, uint32_t certCount)
331 {
332 if (certBlob == NULL) {
333 return CMR_ERROR_NULL_POINTER;
334 }
335
336 for (uint32_t i = 0; i < certCount; i++) {
337 certBlob->uri[i].size = MAX_LEN_URI;
338 certBlob->uri[i].data = (uint8_t *)CMMalloc(MAX_LEN_URI);
339 if (certBlob->uri[i].data == NULL) {
340 return CMR_ERROR_MALLOC_FAIL;
341 }
342 (void)memset_s(certBlob->uri[i].data, MAX_LEN_URI, 0, MAX_LEN_URI);
343
344 certBlob->subjectName[i].size = MAX_LEN_SUBJECT_NAME;
345 certBlob->subjectName[i].data = (uint8_t *)CMMalloc(MAX_LEN_SUBJECT_NAME);
346 if (certBlob->subjectName[i].data == NULL) {
347 return CMR_ERROR_MALLOC_FAIL;
348 }
349 (void)memset_s(certBlob->subjectName[i].data, MAX_LEN_SUBJECT_NAME, 0, MAX_LEN_SUBJECT_NAME);
350
351 certBlob->certAlias[i].size = MAX_LEN_CERT_ALIAS;
352 certBlob->certAlias[i].data = (uint8_t *)CMMalloc(MAX_LEN_CERT_ALIAS);
353 if (certBlob->certAlias[i].data == NULL) {
354 return CMR_ERROR_MALLOC_FAIL;
355 }
356 (void)memset_s(certBlob->certAlias[i].data, MAX_LEN_CERT_ALIAS, 0, MAX_LEN_CERT_ALIAS);
357 }
358 return CM_SUCCESS;
359 }
360
GetUserCertAlias(const char * uri,struct CmBlob * alias)361 static int32_t GetUserCertAlias(const char *uri, struct CmBlob *alias)
362 {
363 int32_t ret = CM_SUCCESS;
364 struct CMUri certUri;
365 (void)memset_s(&certUri, sizeof(certUri), 0, sizeof(certUri));
366
367 ret = CertManagerUriDecode(&certUri, uri);
368 if (ret != CM_SUCCESS) {
369 CM_LOG_E("uri decode failed, ret = %d", ret);
370 return ret;
371 }
372 if (certUri.object == NULL) {
373 CM_LOG_E("uri's object is invalid after decode");
374 (void)CertManagerFreeUri(&certUri);
375 return CMR_ERROR_INVALID_ARGUMENT;
376 }
377
378 struct CertProperty certProperty;
379 (void)memset_s(&certProperty, sizeof(struct CertProperty), 0, sizeof(struct CertProperty));
380 ret = QueryCertProperty(uri, &certProperty);
381 if (ret != CM_SUCCESS) {
382 CM_LOG_E("Failed to QueryCertProperty, ret: %d", ret);
383 (void)CertManagerFreeUri(&certUri);
384 return ret;
385 }
386
387 uint32_t size = strlen(certProperty.alias) + 1;
388 if (size <= 1) {
389 size = strlen(certUri.object) + 1;
390 if (memcpy_s(alias->data, size, certUri.object, size) != EOK) {
391 (void)CertManagerFreeUri(&certUri);
392 return CM_FAILURE;
393 }
394 } else {
395 if (memcpy_s(alias->data, size, (uint8_t *)certProperty.alias, size) != EOK) {
396 (void)CertManagerFreeUri(&certUri);
397 return CM_FAILURE;
398 }
399 }
400 alias->size = size;
401 (void)CertManagerFreeUri(&certUri);
402 return ret;
403 }
404
GetSysCertAlias(const struct CmBlob * certData,struct CmBlob * alias)405 static int32_t GetSysCertAlias(const struct CmBlob *certData, struct CmBlob *alias)
406 {
407 X509 *cert = InitCertContext(certData->data, certData->size);
408 if (cert == NULL) {
409 CM_LOG_E("cert data can't convert x509 format");
410 return CM_FAILURE;
411 }
412
413 int32_t aliasLen = GetX509SubjectName(cert, CM_ORGANIZATION_NAME, (char *)alias->data, alias->size);
414 if (aliasLen <= 0) {
415 aliasLen = GetX509SubjectName(cert, CM_COMMON_NAME, (char *)alias->data, alias->size);
416 if (aliasLen <= 0) {
417 CM_LOG_E("Failed to get certificates CN name");
418 FreeCertContext(cert);
419 return CM_FAILURE;
420 }
421 }
422 alias->size = (uint32_t)aliasLen + 1;
423
424 FreeCertContext(cert);
425 return CM_SUCCESS;
426 }
427
CmGetCertAlias(const uint32_t store,const char * uri,const struct CmBlob * certData,struct CmBlob * alias)428 int32_t CmGetCertAlias(const uint32_t store, const char *uri, const struct CmBlob *certData, struct CmBlob *alias)
429 {
430 int32_t ret;
431
432 if (store == CM_USER_TRUSTED_STORE) {
433 ret = GetUserCertAlias(uri, alias);
434 } else if (store == CM_SYSTEM_TRUSTED_STORE) {
435 ret = GetSysCertAlias(certData, alias);
436 } else {
437 CM_LOG_E("Invalid store");
438 return CM_FAILURE;
439 }
440
441 if (ret != CM_SUCCESS) {
442 CM_LOG_E("Failed to get cert certAlias");
443 return ret;
444 }
445
446 return CM_SUCCESS;
447 }
448
CmGetCertSubjectName(const struct CmBlob * certData,struct CmBlob * subjectName)449 static int32_t CmGetCertSubjectName(const struct CmBlob *certData, struct CmBlob *subjectName)
450 {
451 X509 *cert = InitCertContext(certData->data, certData->size);
452 if (cert == NULL) {
453 CM_LOG_E("cert data can't convert x509 format");
454 return CM_FAILURE;
455 }
456
457 int32_t subjectLen = GetX509SubjectNameLongFormat(cert, (char *)subjectName->data, MAX_LEN_SUBJECT_NAME);
458 if (subjectLen <= 0) {
459 CM_LOG_E("get cert subjectName failed");
460 FreeCertContext(cert);
461 return CM_FAILURE;
462 }
463 subjectName->size = (uint32_t)subjectLen + 1;
464
465 FreeCertContext(cert);
466 return CM_SUCCESS;
467 }
468
CmGetCertListInfo(const struct CmContext * context,uint32_t store,const struct CmMutableBlob * certFileList,struct CertBlob * certBlob,uint32_t * status)469 int32_t CmGetCertListInfo(const struct CmContext *context, uint32_t store,
470 const struct CmMutableBlob *certFileList, struct CertBlob *certBlob, uint32_t *status)
471 {
472 int32_t ret = CM_SUCCESS;
473 struct CertFileInfo *cFileList = (struct CertFileInfo *)certFileList->data;
474
475 ret = CmMallocCertBlob(certBlob, certFileList->size);
476 if (ret != CM_SUCCESS) {
477 CM_LOG_E("malloc certBlob failed");
478 return ret;
479 }
480
481 for (uint32_t i = 0; i < certFileList->size; i++) {
482 ret = CmGetCertStatus(context, &cFileList[i], store, &status[i]); /* status */
483 if (ret != CM_SUCCESS) {
484 CM_LOG_E("Failed to get cert status");
485 return CM_FAILURE;
486 }
487
488 if (memcpy_s(certBlob->uri[i].data, MAX_LEN_URI, cFileList[i].fileName.data,
489 cFileList[i].fileName.size) != EOK) {
490 CM_LOG_E("Failed to get cert uri");
491 return CM_FAILURE;
492 }
493
494 certBlob->uri[i].size = cFileList[i].fileName.size; /* uri */
495
496 struct CmBlob certData = { 0, NULL };
497 ret = CmStorageGetBuf((char *)cFileList[i].path.data, (char *)cFileList[i].fileName.data, &certData);
498 if (ret != CM_SUCCESS) {
499 CM_LOG_E("get cert data failed");
500 return CM_FAILURE;
501 }
502
503 ret = CmGetCertAlias(store, (char *)cFileList[i].fileName.data, &certData,
504 &(certBlob->certAlias[i])); /* alias */
505 if (ret != CM_SUCCESS) {
506 CM_LOG_E("Failed to get cert certAlias");
507 CM_FREE_BLOB(certData);
508 return CM_FAILURE;
509 }
510
511 ret = CmGetCertSubjectName(&certData, &(certBlob->subjectName[i])); /* subjectName */
512 if (ret != CM_SUCCESS) {
513 CM_LOG_E("Failed to get cert subjectName");
514 CM_FREE_BLOB(certData);
515 return CM_FAILURE;
516 }
517 CM_FREE_BLOB(certData);
518 }
519 return ret;
520 }
521
CmFreeCertBlob(struct CertBlob * certBlob)522 void CmFreeCertBlob(struct CertBlob *certBlob)
523 {
524 if (certBlob == NULL) {
525 CM_LOG_E("certBlob is null");
526 return;
527 }
528
529 for (uint32_t i = 0; i < MAX_COUNT_CERTIFICATE; i++) {
530 CM_FREE_BLOB(certBlob->uri[i]);
531 CM_FREE_BLOB(certBlob->subjectName[i]);
532 CM_FREE_BLOB(certBlob->certAlias[i]);
533 }
534 }
535
CmGetMatchedCertIndex(const struct CmMutableBlob * certFileList,const struct CmBlob * certUri)536 uint32_t CmGetMatchedCertIndex(const struct CmMutableBlob *certFileList, const struct CmBlob *certUri)
537 {
538 if (certFileList->size == 0) {
539 CM_LOG_D("no cert file exist");
540 return MAX_COUNT_CERTIFICATE;
541 }
542
543 struct CertFileInfo *cFileList = (struct CertFileInfo *)certFileList->data;
544 uint32_t matchIndex = certFileList->size;
545
546 for (uint32_t i = 0; i < certFileList->size; i++) {
547 if (cFileList[i].fileName.data == NULL) {
548 CM_LOG_E("Corrupted file name at index: %u.\n", i);
549 continue;
550 }
551
552 if ((certUri->size <= cFileList[i].fileName.size) &&
553 (memcmp(certUri->data, cFileList[i].fileName.data, certUri->size) == 0)) {
554 matchIndex = i;
555 break;
556 }
557 }
558 return matchIndex;
559 }
560
GetRdbAuthStorageLevel(const struct CmBlob * keyUri,enum CmAuthStorageLevel * level)561 int32_t GetRdbAuthStorageLevel(const struct CmBlob *keyUri, enum CmAuthStorageLevel *level)
562 {
563 CM_LOG_D("enter GetRdbAuthStorageLevel");
564 if (keyUri == NULL || level == NULL) {
565 CM_LOG_E("Invalid input parameters: keyUri or level is NULL");
566 return CMR_ERROR_INVALID_ARGUMENT;
567 }
568
569 struct CertProperty certProp;
570 (void)memset_s(&certProp, sizeof(struct CertProperty), 0, sizeof(struct CertProperty));
571
572 certProp.level = ERROR_LEVEL;
573 int32_t ret = QueryCertProperty((char *)keyUri->data, &certProp);
574 if (ret != CM_SUCCESS) {
575 CM_LOG_E("Failed to QueryCertProperty, ret: %d", ret);
576 return ret;
577 }
578 /* If the return value of level is ERROR_LEVEL, nothing is found */
579 *level = certProp.level;
580
581 return ret;
582 }
583