• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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