1 /*
2  * Copyright (c) 2023 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_chain_validator.h"
17 
18 #include <securec.h>
19 
20 #include "cf_blob.h"
21 #include "cert_chain_validator_spi.h"
22 #include "config.h"
23 #include "cf_result.h"
24 #include "cf_log.h"
25 #include "cf_memory.h"
26 #include "utils.h"
27 #include "x509_cert_chain_validator_openssl.h"
28 
29 #define LV_LENGTH_LEN sizeof(uint16_t)
30 #define MAX_CERT_PATH_DATA_LEN 8192
31 
32 typedef CfResult (*CertChainValidatorSpiCreateFunc)(HcfCertChainValidatorSpi **);
33 
34 typedef struct {
35     HcfCertChainValidator base;
36     HcfCertChainValidatorSpi *spiObj;
37     char *algorithm;
38 } CertChainValidatorImpl;
39 
40 typedef struct {
41     CertChainValidatorSpiCreateFunc createFunc;
42 } HcfCertChainValidatorFuncSet;
43 
44 typedef struct {
45     const char *algorithm;
46     HcfCertChainValidatorFuncSet funcSet;
47 } HcfCertChainValidatorAbility;
48 
49 static const HcfCertChainValidatorAbility CERT_PATH_VALIDATOR_ABILITY_SET[] = {
50     { "PKIX", { HcfCertChainValidatorSpiCreate } }
51 };
52 
FindAbility(const char * algorithm)53 static const HcfCertChainValidatorFuncSet *FindAbility(const char *algorithm)
54 {
55     for (uint32_t i = 0; i < sizeof(CERT_PATH_VALIDATOR_ABILITY_SET) / sizeof(HcfCertChainValidatorAbility); i++) {
56         if (strcmp(CERT_PATH_VALIDATOR_ABILITY_SET[i].algorithm, algorithm) == 0) {
57             return &(CERT_PATH_VALIDATOR_ABILITY_SET[i].funcSet);
58         }
59     }
60     LOGE("Algorithm for certChain validator is not support! [algorithm]: %s", algorithm);
61     return NULL;
62 }
63 
GetCertChainValidatorClass(void)64 static const char *GetCertChainValidatorClass(void)
65 {
66     return "HcfCertChainValidator";
67 }
68 
DestroyCertChainValidator(CfObjectBase * self)69 static void DestroyCertChainValidator(CfObjectBase *self)
70 {
71     if (self == NULL) {
72         LOGE("Invalid input parameter.");
73         return;
74     }
75     if (!CfIsClassMatch(self, GetCertChainValidatorClass())) {
76         LOGE("Class is not match.");
77         return;
78     }
79     CertChainValidatorImpl *validatorImpl = (CertChainValidatorImpl *)self;
80     CfObjDestroy(validatorImpl->spiObj);
81     CfFree(validatorImpl->algorithm);
82     validatorImpl->algorithm = NULL;
83     CfFree(validatorImpl);
84 }
85 
ConvertCertBuffer2List(const HcfCertChainData * certChainData,CfArray * certsList)86 static CfResult ConvertCertBuffer2List(const HcfCertChainData *certChainData, CfArray *certsList)
87 {
88     uint8_t *msg = certChainData->data;
89     const uint8_t *boundary = certChainData->data + certChainData->dataLen;
90     uint32_t index = 0;
91     CfResult res = CF_SUCCESS;
92     while (msg < boundary) {
93         if (index >= certsList->count || (msg + LV_LENGTH_LEN > boundary)) {
94             LOGE("Invalid index for l-v len!");
95             res = CF_INVALID_PARAMS;
96             break;
97         }
98         uint16_t entryLen = 0;
99         if (memcpy_s(&entryLen, LV_LENGTH_LEN, msg, LV_LENGTH_LEN) != EOK) {
100             LOGE("Input data in too long.");
101             return CF_ERR_COPY;
102         }
103         msg = msg + LV_LENGTH_LEN;
104         certsList->data[index].data = (uint8_t *)CfMalloc(entryLen, 0);
105         if (certsList->data[index].data == NULL) {
106             LOGE("Failed to malloc data for cert, index = %u.", index);
107             res = CF_ERR_MALLOC;
108             break;
109         }
110         if (msg + entryLen > boundary) {
111             LOGE("Entry len is overflow for boundary!");
112             res = CF_INVALID_PARAMS;
113             break;
114         }
115         if (memcpy_s(certsList->data[index].data, entryLen, msg, entryLen) != EOK) {
116             res = CF_ERR_COPY;
117             break;
118         }
119         certsList->data[index].size = entryLen;
120         msg = msg + entryLen;
121         index++;
122     }
123     return res;
124 }
125 
Validate(HcfCertChainValidator * self,const HcfCertChainData * certChainData)126 static CfResult Validate(HcfCertChainValidator *self, const HcfCertChainData *certChainData)
127 {
128     if ((self == NULL) || (certChainData == NULL) || (certChainData->dataLen > MAX_CERT_PATH_DATA_LEN)) {
129         LOGE("Invalid input parameter.");
130         return CF_INVALID_PARAMS;
131     }
132     if (!CfIsClassMatch((CfObjectBase *)self, GetCertChainValidatorClass())) {
133         LOGE("Class is not match.");
134         return CF_INVALID_PARAMS;
135     }
136     CertChainValidatorImpl *impl = (CertChainValidatorImpl *)self;
137     CfArray certsList = { NULL, 0 };
138     certsList.format = certChainData->format;
139     certsList.count = certChainData->count;
140     uint32_t certsLen = sizeof(CfBlob) * certsList.count;
141     certsList.data = (CfBlob *)CfMalloc(certsLen, 0);
142     if (certsList.data == NULL) {
143         LOGE("Failed to new memory for certs.");
144         return CF_ERR_MALLOC;
145     }
146     CfResult res = ConvertCertBuffer2List(certChainData, &certsList);
147     if (res != CF_SUCCESS) {
148         LOGE("Failed to convert buffer to lists.");
149         CfArrayDataClearAndFree(&certsList);
150         return res;
151     }
152     res = impl->spiObj->engineValidate(impl->spiObj, &certsList);
153     CfArrayDataClearAndFree(&certsList);
154     return res;
155 }
156 
GetAlgorithm(HcfCertChainValidator * self)157 static const char *GetAlgorithm(HcfCertChainValidator *self)
158 {
159     if (self == NULL) {
160         LOGE("Invalid input parameter.");
161         return NULL;
162     }
163     if (!CfIsClassMatch((CfObjectBase *)self, GetCertChainValidatorClass())) {
164         LOGE("Class is not match.");
165         return NULL;
166     }
167     CertChainValidatorImpl *impl = (CertChainValidatorImpl *)self;
168     const char *algo = (const char *)impl->algorithm;
169     return algo;
170 }
171 
HcfCertChainValidatorCreate(const char * algorithm,HcfCertChainValidator ** pathValidator)172 CfResult HcfCertChainValidatorCreate(const char *algorithm, HcfCertChainValidator **pathValidator)
173 {
174     CF_LOG_I("enter");
175     if (!CfIsStrValid(algorithm, HCF_MAX_STR_LEN) || (pathValidator == NULL)) {
176         return CF_INVALID_PARAMS;
177     }
178     const HcfCertChainValidatorFuncSet *func = FindAbility(algorithm);
179     if (func == NULL) {
180         LOGE("Func is null!");
181         return CF_NOT_SUPPORT;
182     }
183 
184     HcfCertChainValidatorSpi *spiObj = NULL;
185     CfResult res = func->createFunc(&spiObj);
186     if (res != CF_SUCCESS) {
187         LOGE("Failed to create certChain validator spi object!");
188         return res;
189     }
190     CertChainValidatorImpl *returnValidator = (CertChainValidatorImpl *)CfMalloc(sizeof(CertChainValidatorImpl), 0);
191     if (returnValidator == NULL) {
192         LOGE("Failed to allocate returnValidator memory!");
193         CfObjDestroy(spiObj);
194         return CF_ERR_MALLOC;
195     }
196     returnValidator->base.validate = Validate;
197     returnValidator->base.getAlgorithm = GetAlgorithm;
198     returnValidator->base.base.destroy = DestroyCertChainValidator;
199     returnValidator->base.base.getClass = GetCertChainValidatorClass;
200     returnValidator->spiObj = spiObj;
201     uint32_t algoNameLen = strlen(algorithm) + 1;
202     returnValidator->algorithm = (char *)CfMalloc(algoNameLen, 0);
203     if (returnValidator->algorithm == NULL) {
204         LOGE("Failed to allocate algorithm memory!");
205         CfFree(returnValidator);
206         CfObjDestroy(spiObj);
207         return CF_ERR_MALLOC;
208     }
209     (void)memcpy_s(returnValidator->algorithm, algoNameLen, algorithm, algoNameLen);
210 
211     *pathValidator = (HcfCertChainValidator *)returnValidator;
212     return CF_SUCCESS;
213 }