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_log.h"
20 #include "cm_type.h"
21 #include "cm_x509.h"
22 #include "cert_manager_file.h"
23 #include "cert_manager_mem.h"
24 #include "cert_manager_uri.h"
25 #include "cert_manager_storage.h"
26 #include "cert_manager_status.h"
27 #include "cert_manager_file_operator.h"
28
29 #define MAX_PATH_LEN 256
30
MallocCertPath(struct CmMutableBlob * cPath,const char * path)31 static int32_t MallocCertPath(struct CmMutableBlob *cPath, const char *path)
32 {
33 uint32_t pathSize = strlen(path) + 1;
34 cPath->data = (uint8_t *)CMMalloc(pathSize);
35 if (cPath->data == NULL) {
36 CM_LOG_E("malloc cPathLists failed");
37 return CMR_ERROR_MALLOC_FAIL;
38 }
39 cPath->size = pathSize;
40 (void)memset_s(cPath->data, pathSize, 0, pathSize);
41 return CM_SUCCESS;
42 }
43
CmFreePathList(struct CmMutableBlob * pList,uint32_t pathCount)44 void CmFreePathList(struct CmMutableBlob *pList, uint32_t pathCount)
45 {
46 if (pList == NULL) {
47 return;
48 }
49
50 for (uint32_t i = 0; i < pathCount; i++) {
51 pList[i].size = 0;
52 CM_FREE_PTR(pList[i].data);
53 }
54 CMFree(pList);
55 }
56
ConstrutPathList(const char * useridPath,struct CmMutableBlob * cPathList,uint32_t dirCount)57 static int32_t ConstrutPathList(const char *useridPath, struct CmMutableBlob *cPathList, uint32_t dirCount)
58 {
59 int32_t ret = CM_SUCCESS;
60 void *d = CmOpenDir(useridPath);
61 if (d == NULL) {
62 CM_LOG_E("Failed to open directory");
63 return CM_FAILURE;
64 }
65
66 uint32_t i = 0;
67 struct CmFileDirentInfo dire = {0};
68 while (CmGetSubDir(d, &dire) == CMR_OK) {
69 if (i >= dirCount) {
70 CM_LOG_E("uid dir count beyond dirCount");
71 break;
72 }
73
74 char pathBuf[MAX_PATH_LEN] = {0};
75 if (sprintf_s(pathBuf, MAX_PATH_LEN, "%s/%s", useridPath, dire.fileName) < 0) {
76 CM_LOG_E("copy uid path failed");
77 ret = CM_FAILURE;
78 break;
79 }
80
81 ret = MallocCertPath(&cPathList[i], pathBuf); /* uniformly free memory by caller */
82 if (ret != CM_SUCCESS) {
83 break;
84 }
85
86 if (sprintf_s((char *)cPathList[i].data, cPathList[i].size, "%s", pathBuf) < 0) {
87 ret = CM_FAILURE;
88 break;
89 }
90 i++;
91 }
92
93 (void) CmCloseDir(d);
94 if (i != dirCount) { /* real dir count less than dirCount */
95 ret = CM_FAILURE;
96 }
97 return ret;
98 }
99
CreateCertPathList(const char * useridPath,struct CmMutableBlob * pathList)100 static int32_t CreateCertPathList(const char *useridPath, struct CmMutableBlob *pathList)
101 {
102 int32_t uidCount = GetNumberOfDirs(useridPath);
103 if (uidCount < 0) {
104 CM_LOG_E("Failed to obtain number of uid from path");
105 return CM_FAILURE;
106 }
107
108 if (uidCount == 0) {
109 CM_LOG_I("dir is empty");
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_I("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 CM_LOG_I("dir is empty");
304 return CM_SUCCESS;
305 }
306
307 uint32_t arraySize = sizeof(struct CertFileInfo) * MAX_COUNT_CERTIFICATE;
308 struct CertFileInfo *cFileList = (struct CertFileInfo *)CMMalloc(arraySize);
309 if (cFileList == NULL) {
310 CM_LOG_E("malloc cFileList failed");
311 return CMR_ERROR_MALLOC_FAIL;
312 }
313 (void)memset_s(cFileList, arraySize, 0, arraySize);
314
315 int32_t ret = CM_SUCCESS;
316 uint32_t certCount = 0;
317 struct CmMutableBlob *uidPath = (struct CmMutableBlob *)pathList->data;
318
319 for (uint32_t i = 0; i < pathList->size; i++) {
320 ret = CreateCertFile(cFileList, (char *)uidPath[i].data, &certCount);
321 if (ret != CM_SUCCESS) {
322 CM_LOG_E("Create CertFile fail of %u_th", i);
323 CmFreeCertFiles(cFileList, certCount);
324 return ret;
325 }
326 }
327 certFileList->data = (uint8_t *)cFileList;
328 certFileList->size = certCount;
329 return ret;
330 }
331
CmMallocCertBlob(struct CertBlob * certBlob,uint32_t certCount)332 static int32_t CmMallocCertBlob(struct CertBlob *certBlob, uint32_t certCount)
333 {
334 if (certBlob == NULL) {
335 return CMR_ERROR_NULL_POINTER;
336 }
337
338 for (uint32_t i = 0; i < certCount; i++) {
339 certBlob->uri[i].size = MAX_LEN_URI;
340 certBlob->uri[i].data = (uint8_t *)CMMalloc(MAX_LEN_URI);
341 if (certBlob->uri[i].data == NULL) {
342 return CMR_ERROR_MALLOC_FAIL;
343 }
344 (void)memset_s(certBlob->uri[i].data, MAX_LEN_URI, 0, MAX_LEN_URI);
345
346 certBlob->subjectName[i].size = MAX_LEN_SUBJECT_NAME;
347 certBlob->subjectName[i].data = (uint8_t *)CMMalloc(MAX_LEN_SUBJECT_NAME);
348 if (certBlob->subjectName[i].data == NULL) {
349 return CMR_ERROR_MALLOC_FAIL;
350 }
351 (void)memset_s(certBlob->subjectName[i].data, MAX_LEN_SUBJECT_NAME, 0, MAX_LEN_SUBJECT_NAME);
352
353 certBlob->certAlias[i].size = MAX_LEN_CERT_ALIAS;
354 certBlob->certAlias[i].data = (uint8_t *)CMMalloc(MAX_LEN_CERT_ALIAS);
355 if (certBlob->certAlias[i].data == NULL) {
356 return CMR_ERROR_MALLOC_FAIL;
357 }
358 (void)memset_s(certBlob->certAlias[i].data, MAX_LEN_CERT_ALIAS, 0, MAX_LEN_CERT_ALIAS);
359 }
360 return CM_SUCCESS;
361 }
362
GetUserCertAlias(const char * uri,struct CmBlob * alias)363 static int32_t GetUserCertAlias(const char *uri, struct CmBlob *alias)
364 {
365 int32_t ret = CM_SUCCESS;
366 struct CMUri certUri;
367 (void)memset_s(&certUri, sizeof(certUri), 0, sizeof(certUri));
368
369 ret = CertManagerUriDecode(&certUri, uri);
370 if (ret != CM_SUCCESS) {
371 CM_LOG_E("uri decode failed, ret = %d", ret);
372 return ret;
373 }
374 if (certUri.object == NULL) {
375 CM_LOG_E("uri's object is invalid after decode");
376 (void)CertManagerFreeUri(&certUri);
377 return CMR_ERROR_INVALID_ARGUMENT;
378 }
379
380 uint32_t objectSize = strlen(certUri.object) + 1;
381 if (memcpy_s(alias->data, alias->size, (uint8_t *)certUri.object, objectSize) != EOK) {
382 (void)CertManagerFreeUri(&certUri);
383 return CM_FAILURE;
384 }
385 alias->size = objectSize;
386 (void)CertManagerFreeUri(&certUri);
387 return ret;
388 }
389
GetSysCertAlias(const struct CmBlob * certData,struct CmBlob * alias)390 static int32_t GetSysCertAlias(const struct CmBlob *certData, struct CmBlob *alias)
391 {
392 X509 *cert = InitCertContext(certData->data, certData->size);
393 if (cert == NULL) {
394 CM_LOG_E("cert data can't convert x509 format");
395 return CM_FAILURE;
396 }
397
398 int32_t aliasLen = GetX509SubjectName(cert, CM_ORGANIZATION_NAME, (char *)alias->data, alias->size);
399 if (aliasLen <= 0) {
400 aliasLen = GetX509SubjectName(cert, CM_COMMON_NAME, (char *)alias->data, alias->size);
401 if (aliasLen <= 0) {
402 CM_LOG_E("Failed to get certificates CN name");
403 FreeCertContext(cert);
404 return CM_FAILURE;
405 }
406 }
407 alias->size = (uint32_t)aliasLen + 1;
408
409 FreeCertContext(cert);
410 return CM_SUCCESS;
411 }
412
CmGetCertAlias(const uint32_t store,const char * uri,const struct CmBlob * certData,struct CmBlob * alias)413 int32_t CmGetCertAlias(const uint32_t store, const char *uri, const struct CmBlob *certData, struct CmBlob *alias)
414 {
415 int32_t ret;
416
417 if (store == CM_USER_TRUSTED_STORE) {
418 ret = GetUserCertAlias(uri, alias);
419 } else if (store == CM_SYSTEM_TRUSTED_STORE) {
420 ret = GetSysCertAlias(certData, alias);
421 } else {
422 CM_LOG_E("Invalid store");
423 return CM_FAILURE;
424 }
425
426 if (ret != CM_SUCCESS) {
427 CM_LOG_E("Failed to get cert certAlias");
428 return ret;
429 }
430
431 return CM_SUCCESS;
432 }
433
CmGetCertSubjectName(const struct CmBlob * certData,struct CmBlob * subjectName)434 static int32_t CmGetCertSubjectName(const struct CmBlob *certData, struct CmBlob *subjectName)
435 {
436 X509 *cert = InitCertContext(certData->data, certData->size);
437 if (cert == NULL) {
438 CM_LOG_E("cert data can't convert x509 format");
439 return CM_FAILURE;
440 }
441
442 int32_t subjectLen = GetX509SubjectNameLongFormat(cert, (char *)subjectName->data, MAX_LEN_SUBJECT_NAME);
443 if (subjectLen <= 0) {
444 CM_LOG_E("get cert subjectName failed");
445 FreeCertContext(cert);
446 return CM_FAILURE;
447 }
448 subjectName->size = (uint32_t)subjectLen + 1;
449
450 FreeCertContext(cert);
451 return CM_SUCCESS;
452 }
453
CmGetCertListInfo(const struct CmContext * context,uint32_t store,const struct CmMutableBlob * certFileList,struct CertBlob * certBlob,uint32_t * status)454 int32_t CmGetCertListInfo(const struct CmContext *context, uint32_t store,
455 const struct CmMutableBlob *certFileList, struct CertBlob *certBlob, uint32_t *status)
456 {
457 int32_t ret = CM_SUCCESS;
458 struct CertFileInfo *cFileList = (struct CertFileInfo *)certFileList->data;
459
460 ret = CmMallocCertBlob(certBlob, certFileList->size);
461 if (ret != CM_SUCCESS) {
462 CM_LOG_E("malloc certBlob failed");
463 return ret;
464 }
465
466 for (uint32_t i = 0; i < certFileList->size; i++) {
467 ret = CmGetCertStatus(context, &cFileList[i], store, &status[i]); /* status */
468 if (ret != CM_SUCCESS) {
469 CM_LOG_E("Failed to get cert status");
470 return CM_FAILURE;
471 }
472
473 if (memcpy_s(certBlob->uri[i].data, MAX_LEN_URI, cFileList[i].fileName.data,
474 cFileList[i].fileName.size) != EOK) {
475 CM_LOG_E("Failed to get cert uri");
476 return CM_FAILURE;
477 }
478 certBlob->uri[i].size = cFileList[i].fileName.size; /* uri */
479
480 struct CmBlob certData = { 0, NULL };
481 ret = CmStorageGetBuf((char *)cFileList[i].path.data, (char *)cFileList[i].fileName.data, &certData);
482 if (ret != CM_SUCCESS) {
483 CM_LOG_E("get cert data failed");
484 return CM_FAILURE;
485 }
486
487 ret = CmGetCertAlias(store, (char *)cFileList[i].fileName.data, &certData,
488 &(certBlob->certAlias[i])); /* alias */
489 if (ret != CM_SUCCESS) {
490 CM_LOG_E("Failed to get cert certAlias");
491 CM_FREE_BLOB(certData);
492 return CM_FAILURE;
493 }
494
495 ret = CmGetCertSubjectName(&certData, &(certBlob->subjectName[i])); /* subjectName */
496 if (ret != CM_SUCCESS) {
497 CM_LOG_E("Failed to get cert subjectName");
498 CM_FREE_BLOB(certData);
499 return CM_FAILURE;
500 }
501 CM_FREE_BLOB(certData);
502 }
503 return ret;
504 }
505
CmFreeCertBlob(struct CertBlob * certBlob)506 void CmFreeCertBlob(struct CertBlob *certBlob)
507 {
508 if (certBlob == NULL) {
509 CM_LOG_E("certBlob is null");
510 return;
511 }
512
513 for (uint32_t i = 0; i < MAX_COUNT_CERTIFICATE; i++) {
514 CM_FREE_BLOB(certBlob->uri[i]);
515 CM_FREE_BLOB(certBlob->subjectName[i]);
516 CM_FREE_BLOB(certBlob->certAlias[i]);
517 }
518 }
519
CmGetMatchedCertIndex(const struct CmMutableBlob * certFileList,const struct CmBlob * certUri)520 uint32_t CmGetMatchedCertIndex(const struct CmMutableBlob *certFileList, const struct CmBlob *certUri)
521 {
522 if (certFileList->size == 0) {
523 CM_LOG_I("no cert file exist");
524 return MAX_COUNT_CERTIFICATE;
525 }
526
527 struct CertFileInfo *cFileList = (struct CertFileInfo *)certFileList->data;
528 uint32_t matchIndex = certFileList->size;
529
530 for (uint32_t i = 0; i < certFileList->size; i++) {
531 if (cFileList[i].fileName.data == NULL) {
532 CM_LOG_E("Corrupted file name at index: %u.\n", i);
533 continue;
534 }
535
536 if ((certUri->size <= cFileList[i].fileName.size) &&
537 (memcmp(certUri->data, cFileList[i].fileName.data, certUri->size) == 0)) {
538 matchIndex = i;
539 break;
540 }
541 }
542 return matchIndex;
543 }
544