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_crl_collection.h"
17 
18 #include <securec.h>
19 
20 #include "cf_blob.h"
21 #include "config.h"
22 #include "cf_result.h"
23 #include "cf_log.h"
24 #include "cf_memory.h"
25 #include "utils.h"
26 #include "x509_certificate.h"
27 #include "x509_crl.h"
28 #include "cert_crl_common.h"
29 
30 typedef struct {
31     HcfCertCrlCollection base;
32     HcfX509CertificateArray certs;
33     HcfX509CrlArray crls;
34 } CertCrlCollectionImpl;
35 
GetCertCrlCollectionClass(void)36 static const char *GetCertCrlCollectionClass(void)
37 {
38     return "HcfCertCrlCollection";
39 }
40 
DestroyCertCrlCollection(CfObjectBase * self)41 static void DestroyCertCrlCollection(CfObjectBase *self)
42 {
43     if (self == NULL) {
44         LOGE("Invalid input parameter.");
45         return;
46     }
47     if (!CfIsClassMatch(self, GetCertCrlCollectionClass())) {
48         LOGE("Class is not match.");
49         return;
50     }
51 
52     CertCrlCollectionImpl *collectionImpl = (CertCrlCollectionImpl *)self;
53     FreeCertArrayData(&collectionImpl->certs);
54     FreeCrlArrayData(&collectionImpl->crls);
55     CfFree(collectionImpl);
56 }
57 
GetMatchCerts(const HcfX509CertificateArray * inCerts,const HcfX509CertMatchParams * matchParams,HcfX509CertificateArray * outCerts)58 static CfResult GetMatchCerts(const HcfX509CertificateArray *inCerts, const HcfX509CertMatchParams *matchParams,
59     HcfX509CertificateArray *outCerts)
60 {
61     HcfX509CertificateArray tmpArr = { NULL, 0 };
62     tmpArr.count = inCerts->count;
63     /* inCerts is inner object, the size has been checked in function HcfCertCrlCollectionCreate */
64     tmpArr.data = (HcfX509Certificate **)CfMalloc(inCerts->count * sizeof(HcfX509Certificate *), 0);
65     if (tmpArr.data == NULL) {
66         LOGE("Failed to allocate memory!");
67         return CF_ERR_MALLOC;
68     }
69     uint32_t outInd = 0;
70     for (uint32_t i = 0; i < inCerts->count; ++i) {
71         HcfX509Certificate *cert = inCerts->data[i];
72         bool out = false;
73         CfResult res = cert->match(cert, matchParams, &out);
74         if (res != CF_SUCCESS) {
75             LOGE("match failed");
76             FreeCertArrayData(&tmpArr);
77             return res;
78         }
79         if (!out) {
80             continue;
81         }
82         res = CloneCertificateObj(cert, &(tmpArr.data[outInd]));
83         if (res != CF_SUCCESS) {
84             LOGE("cert clone failed");
85             FreeCertArrayData(&tmpArr);
86             return res;
87         }
88         outInd++;
89     }
90     if (outInd == 0) {
91         LOGI("no any match!");
92         FreeCertArrayData(&tmpArr);
93         return CF_SUCCESS;
94     }
95     outCerts->data = (HcfX509Certificate **)CfMalloc(outInd * sizeof(HcfX509Certificate *), 0);
96     if (outCerts->data == NULL) {
97         LOGE("Failed to allocate memory!");
98         FreeCertArrayData(&tmpArr);
99         return CF_ERR_MALLOC;
100     }
101     outCerts->count = outInd;
102     for (uint32_t i = 0; i < outInd; ++i) {
103         outCerts->data[i] = tmpArr.data[i];
104     }
105     CfFree(tmpArr.data);
106     return CF_SUCCESS;
107 }
108 
GetMatchCRLs(const HcfX509CrlArray * inCrls,const HcfX509CrlMatchParams * matchParams,HcfX509CrlArray * outCrls)109 static CfResult GetMatchCRLs(
110     const HcfX509CrlArray *inCrls, const HcfX509CrlMatchParams *matchParams, HcfX509CrlArray *outCrls)
111 {
112     HcfX509CrlArray tmpArr = { NULL, 0 };
113     tmpArr.count = inCrls->count;
114     /* inCrls is inner object, the size has been checked in function HcfCertCrlCollectionCreate */
115     tmpArr.data = (HcfX509Crl **)CfMalloc(inCrls->count * sizeof(HcfX509Crl *), 0);
116     if (tmpArr.data == NULL) {
117         LOGE("Failed to allocate memory!");
118         return CF_ERR_MALLOC;
119     }
120     uint32_t outInd = 0;
121     for (uint32_t i = 0; i < inCrls->count; ++i) {
122         HcfX509Crl *crl = inCrls->data[i];
123         bool out = false;
124         CfResult res = crl->match(crl, matchParams, &out);
125         if (res != CF_SUCCESS) {
126             LOGE("match failed");
127             FreeCrlArrayData(&tmpArr);
128             return res;
129         }
130         if (!out) {
131             continue;
132         }
133         res = CloneCrlObj(crl, &tmpArr.data[outInd]);
134         if (res != CF_SUCCESS) {
135             LOGE("crl clone failed");
136             FreeCrlArrayData(&tmpArr);
137             return res;
138         }
139         outInd++;
140     }
141     if (outInd == 0) {
142         LOGI("no any match!");
143         FreeCrlArrayData(&tmpArr);
144         return CF_SUCCESS;
145     }
146     outCrls->data = (HcfX509Crl **)CfMalloc(outInd * sizeof(HcfX509Crl *), 0);
147     if (outCrls->data == NULL) {
148         LOGE("Failed to allocate memory!");
149         FreeCrlArrayData(&tmpArr);
150         return CF_ERR_MALLOC;
151     }
152     outCrls->count = outInd;
153     for (uint32_t i = 0; i < outInd; ++i) {
154         outCrls->data[i] = tmpArr.data[i];
155     }
156     CfFree(tmpArr.data);
157     return CF_SUCCESS;
158 }
159 
SelectCerts(HcfCertCrlCollection * self,const HcfX509CertMatchParams * matchParams,HcfX509CertificateArray * retCerts)160 static CfResult SelectCerts(
161     HcfCertCrlCollection *self, const HcfX509CertMatchParams *matchParams, HcfX509CertificateArray *retCerts)
162 {
163     if (self == NULL || matchParams == NULL || retCerts == NULL) {
164         LOGE("Invalid input parameter.");
165         return CF_INVALID_PARAMS;
166     }
167     if (!CfIsClassMatch((CfObjectBase *)self, GetCertCrlCollectionClass())) {
168         LOGE("Class is not match.");
169         return CF_INVALID_PARAMS;
170     }
171     CertCrlCollectionImpl *collectionImpl = (CertCrlCollectionImpl *)self;
172     if (collectionImpl->certs.count == 0) {
173         LOGE("no any certs for select.");
174         return CF_INVALID_PARAMS;
175     }
176     CfResult res = GetMatchCerts(&collectionImpl->certs, matchParams, retCerts);
177     if (res != CF_SUCCESS) {
178         LOGE("match failed");
179         return res;
180     }
181     return CF_SUCCESS;
182 }
183 
SelectCRLs(HcfCertCrlCollection * self,const HcfX509CrlMatchParams * matchParams,HcfX509CrlArray * retCrls)184 static CfResult SelectCRLs(
185     HcfCertCrlCollection *self, const HcfX509CrlMatchParams *matchParams, HcfX509CrlArray *retCrls)
186 {
187     if (self == NULL || matchParams == NULL || retCrls == NULL) {
188         LOGE("Invalid input parameter.");
189         return CF_INVALID_PARAMS;
190     }
191     if (!CfIsClassMatch((CfObjectBase *)self, GetCertCrlCollectionClass())) {
192         LOGE("Class is not match.");
193         return CF_INVALID_PARAMS;
194     }
195     CertCrlCollectionImpl *collectionImpl = (CertCrlCollectionImpl *)self;
196     if (collectionImpl->crls.count == 0) {
197         LOGE("no any crls for select.");
198         return CF_INVALID_PARAMS;
199     }
200     CfResult res = GetMatchCRLs(&collectionImpl->crls, matchParams, retCrls);
201     if (res != CF_SUCCESS) {
202         LOGE("match failed");
203         return res;
204     }
205     return CF_SUCCESS;
206 }
207 
GetCRLs(HcfCertCrlCollection * self,HcfX509CrlArray ** retCrls)208 static CfResult GetCRLs(HcfCertCrlCollection *self, HcfX509CrlArray **retCrls)
209 {
210     if (self == NULL || retCrls == NULL) {
211         LOGE("Invalid input parameter.");
212         return CF_INVALID_PARAMS;
213     }
214     if (!CfIsClassMatch((CfObjectBase *)self, GetCertCrlCollectionClass())) {
215         LOGE("Class is not match.");
216         return CF_INVALID_PARAMS;
217     }
218     CertCrlCollectionImpl *collectionImpl = (CertCrlCollectionImpl *)self;
219     *retCrls = &(collectionImpl->crls);
220 
221     return CF_SUCCESS;
222 }
223 
CloneCertArray(const HcfX509CertificateArray * inCerts,HcfX509CertificateArray * certs)224 static CfResult CloneCertArray(const HcfX509CertificateArray *inCerts, HcfX509CertificateArray *certs)
225 {
226     if (inCerts == NULL || inCerts->count == 0) {
227         LOGI("inCerts is null, or count is 0.");
228         return CF_SUCCESS;
229     }
230 
231     if (inCerts->count > MAX_LEN_OF_CERT_CRL_ARR || certs == NULL) {
232         LOGE("array count is over limit.");
233         return CF_INVALID_PARAMS;
234     }
235 
236     certs->data = (HcfX509Certificate **)CfMalloc(inCerts->count * sizeof(HcfX509Certificate *), 0);
237     if (certs->data == NULL) {
238         LOGE("Failed to allocate memory!");
239         return CF_ERR_MALLOC;
240     }
241     certs->count = inCerts->count;
242     CfResult res = CF_SUCCESS;
243     for (uint32_t i = 0; i < inCerts->count; ++i) {
244         res = CloneCertificateObj(inCerts->data[i], &(certs->data[i]));
245         if (res != CF_SUCCESS) {
246             break;
247         }
248     }
249     if (res != CF_SUCCESS) {
250         FreeCertArrayData(certs);
251         LOGE("Failed to clone cert!");
252         return res;
253     }
254     return CF_SUCCESS;
255 }
256 
CloneCrlArray(const HcfX509CrlArray * inCrls,HcfX509CrlArray * crls)257 static CfResult CloneCrlArray(const HcfX509CrlArray *inCrls, HcfX509CrlArray *crls)
258 {
259     if (inCrls == NULL || inCrls->count == 0) {
260         LOGI("inCrls is null, or count is 0.");
261         return CF_SUCCESS;
262     }
263 
264     if (inCrls->count > MAX_LEN_OF_CERT_CRL_ARR || crls == NULL) {
265         LOGE("array count is over limit.");
266         return CF_INVALID_PARAMS;
267     }
268 
269     crls->data = (HcfX509Crl **)CfMalloc(inCrls->count * sizeof(HcfX509Crl *), 0);
270     if (crls->data == NULL) {
271         LOGE("Failed to allocate memory!");
272         return CF_ERR_MALLOC;
273     }
274 
275     crls->count = inCrls->count;
276     CfResult res = CF_SUCCESS;
277     for (uint32_t i = 0; i < inCrls->count; ++i) {
278         res = CloneCrlObj(inCrls->data[i], &(crls->data[i]));
279         if (res != CF_SUCCESS) {
280             break;
281         }
282     }
283     if (res != CF_SUCCESS) {
284         FreeCrlArrayData(crls);
285         LOGE("Failed to clone crl!");
286         return res;
287     }
288     return CF_SUCCESS;
289 }
290 
HcfCertCrlCollectionCreate(const HcfX509CertificateArray * inCerts,const HcfX509CrlArray * inCrls,HcfCertCrlCollection ** out)291 CfResult HcfCertCrlCollectionCreate(
292     const HcfX509CertificateArray *inCerts, const HcfX509CrlArray *inCrls, HcfCertCrlCollection **out)
293 {
294     if (out == NULL) {
295         LOGE("input params invalid!");
296         return CF_INVALID_PARAMS;
297     }
298 
299     CertCrlCollectionImpl *ret = (CertCrlCollectionImpl *)CfMalloc(sizeof(CertCrlCollectionImpl), 0);
300     if (ret == NULL) {
301         LOGE("Failed to allocate ret memory!");
302         return CF_ERR_MALLOC;
303     }
304 
305     ret->base.base.destroy = DestroyCertCrlCollection;
306     ret->base.base.getClass = GetCertCrlCollectionClass;
307     ret->base.selectCerts = SelectCerts;
308     ret->base.selectCRLs = SelectCRLs;
309     ret->base.getCRLs = GetCRLs;
310 
311     CfResult res = CloneCertArray(inCerts, &(ret->certs));
312     if (res != CF_SUCCESS) {
313         LOGE("Failed to clone cert array!");
314         CfFree(ret);
315         return res;
316     }
317     res = CloneCrlArray(inCrls, &(ret->crls));
318     if (res != CF_SUCCESS) {
319         LOGE("Failed to clone crl array!");
320         FreeCertArrayData(&ret->certs);
321         CfFree(ret);
322         return res;
323     }
324 
325     *out = (HcfCertCrlCollection *)ret;
326     return CF_SUCCESS;
327 }
328