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 i = 0;
68 struct CmFileDirentInfo dire = {0};
69 while (CmGetSubDir(d, &dire) == CMR_OK) {
70 if (i >= 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[i], pathBuf); /* uniformly free memory by caller */
83 if (ret != CM_SUCCESS) {
84 break;
85 }
86
87 if (sprintf_s((char *)cPathList[i].data, cPathList[i].size, "%s", pathBuf) < 0) {
88 ret = CM_FAILURE;
89 break;
90 }
91 i++;
92 }
93
94 (void) CmCloseDir(d);
95 if (i != 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 *d = CmOpenDir(path);
268 if (d == NULL) {
269 CM_LOG_E("Failed to open directory");
270 return CM_FAILURE;
271 }
272
273 int32_t ret;
274 uint32_t i = *certCount;
275 struct CmFileDirentInfo dire = {0};
276 while (CmGetDirFile(d, &dire) == CMR_OK) {
277 if (i >= MAX_COUNT_CERTIFICATE) {
278 CM_LOG_E("cert count beyond MAX");
279 break;
280 }
281
282 ret = GetCertNameAndPath(&cFileList[i], path, dire.fileName);
283 if (ret != CM_SUCCESS) {
284 CM_LOG_E("malloc certfile for cert failed");
285 break;
286 }
287
288 i++;
289 }
290
291 (void) CmCloseDir(d);
292 uint32_t realCount = i - *certCount;
293 *certCount += realCount;
294 if (realCount != (uint32_t)fileNums) {
295 return CM_FAILURE;
296 }
297 return ret;
298 }
299
CreateCertFileList(const struct CmMutableBlob * pathList,struct CmMutableBlob * certFileList)300 int32_t CreateCertFileList(const struct CmMutableBlob *pathList, struct CmMutableBlob *certFileList)
301 {
302 if (pathList->size == 0) {
303 return CM_SUCCESS;
304 }
305
306 uint32_t arraySize = sizeof(struct CertFileInfo) * MAX_COUNT_CERTIFICATE;
307 struct CertFileInfo *cFileList = (struct CertFileInfo *)CMMalloc(arraySize);
308 if (cFileList == NULL) {
309 CM_LOG_E("malloc cFileList failed");
310 return CMR_ERROR_MALLOC_FAIL;
311 }
312 (void)memset_s(cFileList, arraySize, 0, arraySize);
313
314 int32_t ret = CM_SUCCESS;
315 uint32_t certCount = 0;
316 struct CmMutableBlob *uidPath = (struct CmMutableBlob *)pathList->data;
317
318 for (uint32_t i = 0; i < pathList->size; i++) {
319 ret = CreateCertFile(cFileList, (char *)uidPath[i].data, &certCount);
320 if (ret != CM_SUCCESS) {
321 CM_LOG_E("Create CertFile fail of %u_th", i);
322 CmFreeCertFiles(cFileList, certCount);
323 return ret;
324 }
325 }
326 certFileList->data = (uint8_t *)cFileList;
327 certFileList->size = certCount;
328 return ret;
329 }
330
CmMallocCertBlob(struct CertBlob * certBlob,uint32_t certCount)331 static int32_t CmMallocCertBlob(struct CertBlob *certBlob, uint32_t certCount)
332 {
333 if (certBlob == NULL) {
334 return CMR_ERROR_NULL_POINTER;
335 }
336
337 for (uint32_t i = 0; i < certCount; i++) {
338 certBlob->uri[i].size = MAX_LEN_URI;
339 certBlob->uri[i].data = (uint8_t *)CMMalloc(MAX_LEN_URI);
340 if (certBlob->uri[i].data == NULL) {
341 return CMR_ERROR_MALLOC_FAIL;
342 }
343 (void)memset_s(certBlob->uri[i].data, MAX_LEN_URI, 0, MAX_LEN_URI);
344
345 certBlob->subjectName[i].size = MAX_LEN_SUBJECT_NAME;
346 certBlob->subjectName[i].data = (uint8_t *)CMMalloc(MAX_LEN_SUBJECT_NAME);
347 if (certBlob->subjectName[i].data == NULL) {
348 return CMR_ERROR_MALLOC_FAIL;
349 }
350 (void)memset_s(certBlob->subjectName[i].data, MAX_LEN_SUBJECT_NAME, 0, MAX_LEN_SUBJECT_NAME);
351
352 certBlob->certAlias[i].size = MAX_LEN_CERT_ALIAS;
353 certBlob->certAlias[i].data = (uint8_t *)CMMalloc(MAX_LEN_CERT_ALIAS);
354 if (certBlob->certAlias[i].data == NULL) {
355 return CMR_ERROR_MALLOC_FAIL;
356 }
357 (void)memset_s(certBlob->certAlias[i].data, MAX_LEN_CERT_ALIAS, 0, MAX_LEN_CERT_ALIAS);
358 }
359 return CM_SUCCESS;
360 }
361
GetUserCertAlias(const char * uri,struct CmBlob * alias)362 static int32_t GetUserCertAlias(const char *uri, struct CmBlob *alias)
363 {
364 int32_t ret = CM_SUCCESS;
365 struct CMUri certUri;
366 (void)memset_s(&certUri, sizeof(certUri), 0, sizeof(certUri));
367
368 ret = CertManagerUriDecode(&certUri, uri);
369 if (ret != CM_SUCCESS) {
370 CM_LOG_E("uri decode failed, ret = %d", ret);
371 return ret;
372 }
373 if (certUri.object == NULL) {
374 CM_LOG_E("uri's object is invalid after decode");
375 (void)CertManagerFreeUri(&certUri);
376 return CMR_ERROR_INVALID_ARGUMENT;
377 }
378
379 struct CertProperty certProperty;
380 (void)memset_s(&certProperty, sizeof(struct CertProperty), 0, sizeof(struct CertProperty));
381 ret = QueryCertProperty(uri, &certProperty);
382 if (ret != CM_SUCCESS) {
383 CM_LOG_E("Failed to QueryCertProperty, ret: %d", ret);
384 (void)CertManagerFreeUri(&certUri);
385 return ret;
386 }
387
388 uint32_t size = strlen(certProperty.alias) + 1;
389 if (size <= 1) {
390 size = strlen(certUri.object) + 1;
391 if (memcpy_s(alias->data, size, certUri.object, size) != EOK) {
392 (void)CertManagerFreeUri(&certUri);
393 return CM_FAILURE;
394 }
395 } else {
396 if (memcpy_s(alias->data, size, (uint8_t *)certProperty.alias, size) != EOK) {
397 (void)CertManagerFreeUri(&certUri);
398 return CM_FAILURE;
399 }
400 }
401 alias->size = size;
402 (void)CertManagerFreeUri(&certUri);
403 return ret;
404 }
405
GetSysCertAlias(const struct CmBlob * certData,struct CmBlob * alias)406 static int32_t GetSysCertAlias(const struct CmBlob *certData, struct CmBlob *alias)
407 {
408 X509 *cert = InitCertContext(certData->data, certData->size);
409 if (cert == NULL) {
410 CM_LOG_E("cert data can't convert x509 format");
411 return CM_FAILURE;
412 }
413
414 int32_t aliasLen = GetX509SubjectName(cert, CM_ORGANIZATION_NAME, (char *)alias->data, alias->size);
415 if (aliasLen <= 0) {
416 aliasLen = GetX509SubjectName(cert, CM_COMMON_NAME, (char *)alias->data, alias->size);
417 if (aliasLen <= 0) {
418 CM_LOG_E("Failed to get certificates CN name");
419 FreeCertContext(cert);
420 return CM_FAILURE;
421 }
422 }
423 alias->size = (uint32_t)aliasLen + 1;
424
425 FreeCertContext(cert);
426 return CM_SUCCESS;
427 }
428
CmGetCertAlias(const uint32_t store,const char * uri,const struct CmBlob * certData,struct CmBlob * alias)429 int32_t CmGetCertAlias(const uint32_t store, const char *uri, const struct CmBlob *certData, struct CmBlob *alias)
430 {
431 int32_t ret;
432
433 if (store == CM_USER_TRUSTED_STORE) {
434 ret = GetUserCertAlias(uri, alias);
435 } else if (store == CM_SYSTEM_TRUSTED_STORE) {
436 ret = GetSysCertAlias(certData, alias);
437 } else {
438 CM_LOG_E("Invalid store");
439 return CM_FAILURE;
440 }
441
442 if (ret != CM_SUCCESS) {
443 CM_LOG_E("Failed to get cert certAlias");
444 return ret;
445 }
446
447 return CM_SUCCESS;
448 }
449
CmGetCertSubjectName(const struct CmBlob * certData,struct CmBlob * subjectName)450 static int32_t CmGetCertSubjectName(const struct CmBlob *certData, struct CmBlob *subjectName)
451 {
452 X509 *cert = InitCertContext(certData->data, certData->size);
453 if (cert == NULL) {
454 CM_LOG_E("cert data can't convert x509 format");
455 return CM_FAILURE;
456 }
457
458 int32_t subjectLen = GetX509SubjectNameLongFormat(cert, (char *)subjectName->data, MAX_LEN_SUBJECT_NAME);
459 if (subjectLen <= 0) {
460 CM_LOG_E("get cert subjectName failed");
461 FreeCertContext(cert);
462 return CM_FAILURE;
463 }
464 subjectName->size = (uint32_t)subjectLen + 1;
465
466 FreeCertContext(cert);
467 return CM_SUCCESS;
468 }
469
CmGetCertListInfo(const struct CmContext * context,uint32_t store,const struct CmMutableBlob * certFileList,struct CertBlob * certBlob,uint32_t * status)470 int32_t CmGetCertListInfo(const struct CmContext *context, uint32_t store,
471 const struct CmMutableBlob *certFileList, struct CertBlob *certBlob, uint32_t *status)
472 {
473 int32_t ret = CM_SUCCESS;
474 struct CertFileInfo *cFileList = (struct CertFileInfo *)certFileList->data;
475
476 ret = CmMallocCertBlob(certBlob, certFileList->size);
477 if (ret != CM_SUCCESS) {
478 CM_LOG_E("malloc certBlob failed");
479 return ret;
480 }
481
482 for (uint32_t i = 0; i < certFileList->size; i++) {
483 ret = CmGetCertStatus(context, &cFileList[i], store, &status[i]); /* status */
484 if (ret != CM_SUCCESS) {
485 CM_LOG_E("Failed to get cert status");
486 return CM_FAILURE;
487 }
488
489 if (memcpy_s(certBlob->uri[i].data, MAX_LEN_URI, cFileList[i].fileName.data,
490 cFileList[i].fileName.size) != EOK) {
491 CM_LOG_E("Failed to get cert uri");
492 return CM_FAILURE;
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