• 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_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 }