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