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 }