1 /*
2  * Copyright (c) 2024 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 "x509certchain_fuzzer.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include "securec.h"
21 
22 #include "crypto_x509_cert_chain_data_p7b.h"
23 #include "crypto_x509_cert_chain_data_der.h"
24 #include "crypto_x509_cert_chain_data_pem.h"
25 #include "crypto_x509_cert_chain_data_pem_added.h"
26 #include "crypto_x509_cert_chain_data_pem_ex.h"
27 #include "x509_cert_chain_validate_params.h"
28 #include "x509_cert_chain_validate_result.h"
29 #include "crypto_x509_test_common.h"
30 #include "x509_trust_anchor.h"
31 #include "x509_cert_chain_openssl.h"
32 
33 #include "cf_blob.h"
34 #include "cf_result.h"
35 #include "x509_certificate.h"
36 #include "x509_cert_chain.h"
37 #include "cert_chain_validator.h"
38 
39 namespace OHOS {
40     constexpr int32_t CERT_HEADER_LEN = 2;
41     constexpr int32_t CERT_COUNT = 3;
42     constexpr int32_t MAX_DEPTH = 100;
43     static bool g_testCertChainFlag = true;
44     static bool g_testCertChainValidatorFlag = true;
45     static bool g_testCertChainBuildResultFlag = true;
46     static bool g_testCreateTrustAnchorFlag = true;
47 
48     const CfEncodingBlob g_inStreamChainDataP7b = { const_cast<uint8_t *>(g_testChainDataP7b),
49         sizeof(g_testChainDataP7b) / sizeof(g_testChainDataP7b[0]),
50         CF_FORMAT_PKCS7 };
51 
52     const CfEncodingBlob g_inStreamChainDataDer = { const_cast<uint8_t *>(g_testChainDataDer),
53         sizeof(g_testChainDataDer) / sizeof(g_testChainDataDer[0]),
54         CF_FORMAT_DER };
55 
56     const CfEncodingBlob g_inStreamChainDataPem = { reinterpret_cast<uint8_t *>(const_cast<char *>(g_testCertChainPem)),
57         sizeof(g_testCertChainPem) / sizeof(g_testCertChainPem[0]), CF_FORMAT_PEM };
58 
59     const CfEncodingBlob g_inStreamChainDataPemRoot = {
60         reinterpret_cast<uint8_t *>(const_cast<char *>(g_testCertChainPemRoot)),
61         sizeof(g_testCertChainPemRoot) / sizeof(g_testCertChainPemRoot[0]),
62         CF_FORMAT_PEM };
63 
TestGetCertList(HcfCertChain * certChain)64     static CfResult TestGetCertList(HcfCertChain *certChain)
65     {
66         HcfX509CertificateArray certs = {nullptr, 0};
67         CfResult ret = certChain->getCertList(certChain, &certs);
68         if (ret != CF_SUCCESS) {
69             return ret;
70         }
71         if (certs.count != CERT_COUNT) {
72             return CF_INVALID_PARAMS;
73         }
74 
75         return CF_SUCCESS;
76     }
77 
BuildAnchorArr1(const CfEncodingBlob & certInStream,HcfX509TrustAnchorArray & trustAnchorArray)78     static CfResult BuildAnchorArr1(const CfEncodingBlob &certInStream, HcfX509TrustAnchorArray &trustAnchorArray)
79     {
80         HcfX509TrustAnchor *anchor = static_cast<HcfX509TrustAnchor *>(CfMalloc(sizeof(HcfX509TrustAnchor), 0));
81         if (anchor == nullptr) {
82             return CF_ERR_MALLOC;
83         }
84 
85         (void)HcfX509CertificateCreate(&certInStream, &anchor->CACert);
86         trustAnchorArray.data = static_cast<HcfX509TrustAnchor **>(CfMalloc(1 * sizeof(HcfX509TrustAnchor *), 0));
87         if (trustAnchorArray.data == nullptr) {
88             CfFree(anchor);
89             return CF_ERR_MALLOC;
90         }
91         trustAnchorArray.data[0] = anchor;
92         trustAnchorArray.count = 1;
93         return CF_SUCCESS;
94     }
95 
FreeTrustAnchor1(HcfX509TrustAnchor * & trustAnchor)96     static void FreeTrustAnchor1(HcfX509TrustAnchor *&trustAnchor)
97     {
98         if (trustAnchor == nullptr) {
99             return;
100         }
101         CfBlobFree(&trustAnchor->CAPubKey);
102         CfBlobFree(&trustAnchor->CASubject);
103         CfObjDestroy(trustAnchor->CACert);
104         trustAnchor->CACert = nullptr;
105         CfFree(trustAnchor);
106         trustAnchor = nullptr;
107     }
108 
FreeTrustAnchorArr1(HcfX509TrustAnchorArray & trustAnchorArray)109     static void FreeTrustAnchorArr1(HcfX509TrustAnchorArray &trustAnchorArray)
110     {
111         for (uint32_t i = 0; i < trustAnchorArray.count; ++i) {
112             HcfX509TrustAnchor *anchor = trustAnchorArray.data[i];
113             FreeTrustAnchor1(anchor);
114         }
115         CfFree(trustAnchorArray.data);
116         trustAnchorArray.data = nullptr;
117         trustAnchorArray.count = 0;
118     }
119 
TestVerify(HcfCertChain * certChain)120     static CfResult TestVerify(HcfCertChain *certChain)
121     {
122         HcfX509CertChainValidateResult result = { 0 };
123         HcfX509TrustAnchorArray trustAnchorArray = { 0 };
124         CfResult ret = BuildAnchorArr1(g_inStreamChainDataPemRoot, trustAnchorArray);
125         if (ret != CF_SUCCESS) {
126             return ret;
127         }
128 
129         HcfX509CertChainValidateParams pCertChainValidateParams = { 0 };
130         const char *date = "20231212080000Z";
131         CfBlob validDate = { 0 };
132         validDate.data = reinterpret_cast<uint8_t *>(const_cast<char *>(date));
133         validDate.size = strlen(date) + 1;
134         pCertChainValidateParams.date = &validDate;
135         pCertChainValidateParams.trustAnchors = &trustAnchorArray;
136 
137         ret = certChain->validate(certChain, &pCertChainValidateParams, &result);
138         FreeTrustAnchorArr1(trustAnchorArray);
139         return ret;
140     }
141 
GetInvalidCertChainClass(void)142     static const char *GetInvalidCertChainClass(void)
143     {
144         return "HcfInvalidCertChain";
145     }
146 
TestToString(HcfCertChain * certChain)147     static void TestToString(HcfCertChain *certChain)
148     {
149         CfBlob blob = { 0, nullptr };
150         (void)certChain->toString(certChain, &blob);
151         CfBlobDataFree(&blob);
152 
153         HcfCertChain testCertChain = {};
154         testCertChain.base.getClass = GetInvalidCertChainClass;
155         (void)certChain->toString(&testCertChain, &blob);
156         (void)certChain->toString(nullptr, &blob);
157         (void)certChain->toString(certChain, nullptr);
158         (void)certChain->toString(nullptr, nullptr);
159     }
160 
TestHashCode(HcfCertChain * certChain)161     static void TestHashCode(HcfCertChain *certChain)
162     {
163         CfBlob blob = { 0, nullptr };
164         (void)certChain->hashCode(certChain, &blob);
165         CfBlobDataFree(&blob);
166 
167         HcfCertChain testCertChain = {};
168         testCertChain.base.getClass = GetInvalidCertChainClass;
169         (void)certChain->hashCode(&testCertChain, &blob);
170         (void)certChain->hashCode(nullptr, &blob);
171         (void)certChain->hashCode(certChain, nullptr);
172         (void)certChain->hashCode(nullptr, nullptr);
173     }
174 
CreateOneCertChainCore(const CfEncodingBlob * inStream)175     static CfResult CreateOneCertChainCore(const CfEncodingBlob *inStream)
176     {
177         HcfCertChain *certChain = nullptr;
178         CfResult ret = HcfCertChainCreate(inStream, nullptr, &certChain);
179         if (ret != CF_SUCCESS) {
180             return ret;
181         }
182         ret = TestGetCertList(certChain);
183         if (ret != CF_SUCCESS) {
184             CfObjDestroy(certChain);
185             return ret;
186         }
187 
188         (void)TestToString(certChain);
189         (void)TestHashCode(certChain);
190         (void)TestVerify(certChain);
191         CfObjDestroy(certChain);
192         return ret;
193     }
194 
CreateChainByArr()195     static void CreateChainByArr()
196     {
197         HcfX509CertChainSpi *certChainSpi = nullptr;
198         HcfX509CertificateArray certArray;
199         HcfX509Certificate *x509CertObj = nullptr;
200 
201         int certSize = sizeof(g_testSelfSignedCaCert);
202         const CfEncodingBlob cert = { reinterpret_cast<uint8_t *>(const_cast<char *>(g_testSelfSignedCaCert)),
203             certSize, CF_FORMAT_PEM };
204         (void)HcfX509CertificateCreate(&cert, &x509CertObj);
205 
206         certArray.data = static_cast<HcfX509Certificate **>(CfMalloc(1 * sizeof(HcfX509Certificate *), 0));
207         if (certArray.data == nullptr) {
208             return;
209         }
210         certArray.data[0] = x509CertObj;
211         certArray.count = 1;
212 
213         (void)HcfX509CertChainByArrSpiCreate(nullptr, &certChainSpi);
214         (void)HcfX509CertChainByArrSpiCreate(&certArray, nullptr);
215         (void)HcfX509CertChainByArrSpiCreate(&certArray, &certChainSpi);
216 
217         CfFree(certArray.data);
218         CfObjDestroy(x509CertObj);
219         CfObjDestroy(certChainSpi);
220     }
221 
FreeHcfRevocationCheckParam1(HcfRevocationCheckParam * param)222     static void FreeHcfRevocationCheckParam1(HcfRevocationCheckParam *param)
223     {
224         if (param == nullptr) {
225             return;
226         }
227 
228         if (param->options != nullptr) {
229             if (param->options->data != nullptr) {
230                 CfFree(param->options->data);
231             }
232 
233             CfFree(param->options);
234         }
235 
236         if (param->ocspResponses != nullptr) {
237             CfFree(param->ocspResponses);
238         }
239 
240         if (param->ocspResponderCert != nullptr) {
241             CfObjDestroy(param->ocspResponderCert);
242         }
243 
244         CfFree(param);
245     }
246 
ConstructHcfRevocationCheckParam1(const HcfRevChkOption * data,size_t size,CfBlob * ocspResponderURI=NULL,CfBlob * crlDownloadURI=NULL,const CfEncodingBlob * ocspResponderCertStream=NULL)247     static HcfRevocationCheckParam *ConstructHcfRevocationCheckParam1(const HcfRevChkOption *data, size_t size,
248         CfBlob *ocspResponderURI = NULL, CfBlob *crlDownloadURI = NULL,
249         const CfEncodingBlob *ocspResponderCertStream = NULL)
250     {
251         HcfRevChkOpArray *revChkOpArray = static_cast<HcfRevChkOpArray *>(CfMalloc(sizeof(HcfRevChkOpArray), 0));
252         if (revChkOpArray == nullptr) {
253             return nullptr;
254         }
255 
256         revChkOpArray->count = size;
257         revChkOpArray->data =
258             static_cast<HcfRevChkOption *>(CfMalloc(revChkOpArray->count * sizeof(HcfRevChkOption), 0));
259         if (revChkOpArray->data == nullptr) {
260             CfFree(revChkOpArray);
261             return nullptr;
262         }
263 
264         for (size_t i = 0; i < revChkOpArray->count; i++) {
265             revChkOpArray->data[i] = data[i];
266         }
267 
268         CfBlob *resp = static_cast<CfBlob *>(CfMalloc(sizeof(CfBlob), 0));
269         if (resp == nullptr) {
270             CfFree(revChkOpArray->data);
271             CfFree(revChkOpArray);
272             return nullptr;
273         }
274         resp->data = (uint8_t *)(&g_testOcspResponses[0]);
275         resp->size = sizeof(g_testOcspResponses);
276 
277         HcfRevocationCheckParam *param =
278             static_cast<HcfRevocationCheckParam *>(CfMalloc(sizeof(HcfRevocationCheckParam), 0));
279         if (param == nullptr) {
280             CfFree(revChkOpArray->data);
281             CfFree(revChkOpArray);
282             return nullptr;
283         }
284 
285         param->options = revChkOpArray;
286         param->ocspResponses = resp;
287         param->ocspResponderURI = ocspResponderURI;
288         param->crlDownloadURI = crlDownloadURI;
289 
290         if (ocspResponderCertStream != NULL) {
291             (void)HcfX509CertificateCreate(&g_inStreamOcspResponderCert, &(param->ocspResponderCert));
292             if (param->ocspResponderCert == nullptr) {
293                 FreeHcfRevocationCheckParam1(param);
294                 return nullptr;
295             }
296         }
297 
298         return param;
299     }
300 
FreeValidateResult1(HcfX509CertChainValidateResult & result)301     void FreeValidateResult1(HcfX509CertChainValidateResult &result)
302     {
303         if (result.entityCert != nullptr) {
304             CfObjDestroy(result.entityCert);
305             result.entityCert = nullptr;
306         }
307 
308         if (result.trustAnchor != nullptr) {
309             FreeTrustAnchor1(result.trustAnchor);
310         }
311     }
312 
TestEngineValidateInvalid(HcfX509CertChainSpi * spi,const CfEncodingBlob * inStream)313     static void TestEngineValidateInvalid(HcfX509CertChainSpi *spi, const CfEncodingBlob *inStream)
314     {
315         HcfX509TrustAnchorArray trustAnchorArray = { 0 };
316         if (BuildAnchorArr1(*inStream, trustAnchorArray) != CF_SUCCESS) {
317             return;
318         }
319         HcfX509CertChainValidateParams params = { 0 };
320         params.trustAnchors = &trustAnchorArray;
321         HcfX509CertChainValidateResult result = { 0 };
322 
323         params.policy = (HcfValPolicyType)-1;
324         (void)spi->engineValidate(spi, &params, &result);
325 
326         params.policy = VALIDATION_POLICY_TYPE_SSL;
327         (void)spi->engineValidate(spi, &params, &result);
328 
329         FreeTrustAnchorArr1(trustAnchorArray);
330     }
331 
TestEngineValidate(HcfX509CertChainSpi * spi,const CfEncodingBlob * inStream)332     static void TestEngineValidate(HcfX509CertChainSpi *spi, const CfEncodingBlob *inStream)
333     {
334         HcfX509TrustAnchorArray trustAnchorArray = { 0 };
335         if (BuildAnchorArr1(*inStream, trustAnchorArray) != CF_SUCCESS) {
336             return;
337         }
338         HcfX509CertChainValidateParams params = { 0 };
339         params.trustAnchors = &trustAnchorArray;
340 
341         HcfRevChkOption data[] = { REVOCATION_CHECK_OPTION_PREFER_OCSP };
342         params.revocationCheckParam = ConstructHcfRevocationCheckParam1(data, sizeof(data) / sizeof(data[0]));
343         if (params.revocationCheckParam == nullptr) {
344             return;
345         }
346 
347         HcfX509CertChainValidateResult result = { 0 };
348         spi->engineValidate(spi, &params, &result);
349 
350         FreeValidateResult1(result);
351         FreeTrustAnchorArr1(trustAnchorArray);
352         FreeHcfRevocationCheckParam1(params.revocationCheckParam);
353     }
354 
CreateChainByEnc()355     static void CreateChainByEnc()
356     {
357         int pemSize = sizeof(g_testCertChainPem) / sizeof(char);
358         int pem163Size = sizeof(g_testCertChainPem163) / sizeof(char);
359         const CfEncodingBlob pem = { reinterpret_cast<uint8_t *>(const_cast<char *>(g_testCertChainPem)),
360             pemSize, CF_FORMAT_PEM };
361         const CfEncodingBlob pem163 = { reinterpret_cast<uint8_t *>(const_cast<char *>(g_testCertChainPem163)),
362             pem163Size, CF_FORMAT_PEM };
363         HcfX509CertChainSpi *certChainSpi = nullptr;
364         CfResult ret = HcfX509CertChainByEncSpiCreate(&pem, &certChainSpi);
365         if (ret != CF_SUCCESS) {
366             return;
367         }
368         HcfX509CertChainSpi *certChainPemSpi = certChainSpi;
369 
370         certChainSpi = nullptr;
371         ret = HcfX509CertChainByEncSpiCreate(&pem163, &certChainSpi);
372         if (ret != CF_SUCCESS) {
373             CfObjDestroy(certChainPemSpi);
374             return;
375         }
376         HcfX509CertChainSpi *certChainPemSpi163 = certChainSpi;
377 
378         int pemRootSize = sizeof(g_testCertChainPemRoot) / sizeof(char);
379         int pemRoot163Size = sizeof(g_testCertChainPemRoot163) / sizeof(char);
380         const CfEncodingBlob inpemRoot = { reinterpret_cast<uint8_t *>(const_cast<char *>(g_testCertChainPemRoot)),
381             pemRootSize, CF_FORMAT_PEM };
382         const CfEncodingBlob inpemRoot163 = {
383             reinterpret_cast<uint8_t *>(const_cast<char *>(g_testCertChainPemRoot163)),
384             pemRoot163Size, CF_FORMAT_PEM };
385         TestEngineValidateInvalid(certChainPemSpi, &inpemRoot);
386         TestEngineValidateInvalid(certChainPemSpi163, &inpemRoot163);
387         TestEngineValidate(certChainPemSpi163, &inpemRoot163);
388 
389         CfObjDestroy(certChainPemSpi);
390         CfObjDestroy(certChainPemSpi163);
391     }
392 
CreateOneCertChain(CfEncodingFormat encodingFormat)393     static CfResult CreateOneCertChain(CfEncodingFormat encodingFormat)
394     {
395         CreateChainByArr();
396         CreateChainByEnc();
397         switch (encodingFormat) {
398             case CF_FORMAT_DER:
399                 return CreateOneCertChainCore(&g_inStreamChainDataDer);
400             case CF_FORMAT_PKCS7:
401                 return CreateOneCertChainCore(&g_inStreamChainDataP7b);
402             case CF_FORMAT_PEM:
403                 return CreateOneCertChainCore(&g_inStreamChainDataPem);
404             default:
405                 return CF_INVALID_PARAMS;
406         }
407     }
408 
X509CertChainFuzzTest(const uint8_t * data,size_t size,CfEncodingFormat encodingFormat)409     void X509CertChainFuzzTest(const uint8_t* data, size_t size, CfEncodingFormat encodingFormat)
410     {
411         if (g_testCertChainFlag) {
412             if (CreateOneCertChain(encodingFormat) != CF_SUCCESS) {
413                 return;
414             }
415             g_testCertChainFlag = false;
416         }
417         if (data == nullptr) {
418             return;
419         }
420         CfEncodingBlob inStream = { 0 };
421         inStream.data = const_cast<uint8_t *>(data);
422         inStream.encodingFormat = encodingFormat;
423         inStream.len = size;
424         HcfCertChain *x509CertObj = nullptr;
425         CfResult res = HcfCertChainCreate(&inStream, nullptr, &x509CertObj);
426         if (res != CF_SUCCESS) {
427             return;
428         }
429         CfObjDestroy(x509CertObj);
430         return;
431     }
432 
ConstructCertData(HcfCertChainData * certsData)433     static CfResult ConstructCertData(HcfCertChainData *certsData)
434     {
435         certsData->format = CF_FORMAT_PEM;
436         certsData->count = 2; /* level-2 cert chain. */
437         uint32_t caCertLen = strlen(g_testCertChainValidatorCaCert) + 1;
438         uint32_t secondCaCertLen = strlen(g_testCertChainValidatorSecondCaCert) + 1;
439         certsData->dataLen = CERT_HEADER_LEN + secondCaCertLen + CERT_HEADER_LEN + caCertLen;
440         certsData->data = static_cast<uint8_t *>(malloc(certsData->dataLen));
441         if (certsData->data == nullptr) {
442             return CF_ERR_MALLOC;
443         }
444         if (memcpy_s(certsData->data, CERT_HEADER_LEN + secondCaCertLen + CERT_HEADER_LEN + caCertLen,
445             &secondCaCertLen, CERT_HEADER_LEN) != EOK) {
446             goto OUT;
447         }
448         if (memcpy_s(certsData->data + CERT_HEADER_LEN, secondCaCertLen + CERT_HEADER_LEN + caCertLen,
449             g_testCertChainValidatorSecondCaCert, secondCaCertLen) != EOK) {
450             goto OUT;
451         }
452         if (memcpy_s(certsData->data + CERT_HEADER_LEN + secondCaCertLen, CERT_HEADER_LEN + caCertLen,
453             &caCertLen, CERT_HEADER_LEN) != EOK) {
454             goto OUT;
455         }
456         if (memcpy_s(certsData->data + CERT_HEADER_LEN + secondCaCertLen + CERT_HEADER_LEN, caCertLen,
457             g_testCertChainValidatorCaCert, caCertLen) != EOK) {
458             goto OUT;
459         }
460         return CF_SUCCESS;
461 
462     OUT:
463         free(certsData->data);
464         certsData->data = nullptr;
465         return CF_INVALID_PARAMS;
466     }
467 
FreeCertData(HcfCertChainData * certsData)468     static void FreeCertData(HcfCertChainData *certsData)
469     {
470         if (certsData != nullptr && certsData->data != nullptr) {
471             free(certsData->data);
472         }
473     }
474 
CreateOneCertChainValidator()475     static CfResult CreateOneCertChainValidator()
476     {
477         HcfCertChainData certsData = {};
478         ConstructCertData(&certsData);
479         HcfCertChainValidator *pathValidator = nullptr;
480         (void)HcfCertChainValidatorCreate("invalidPKIX", &pathValidator);
481         (void)HcfCertChainValidatorCreate("PKIX", nullptr);
482         CfResult res = HcfCertChainValidatorCreate("PKIX", &pathValidator);
483         if (res != CF_SUCCESS) {
484             goto OUT;
485         }
486         res = pathValidator->validate(pathValidator, &certsData);
487         if (res != CF_SUCCESS) {
488             goto OUT;
489         }
490         (void)pathValidator->getAlgorithm(pathValidator);
491         (void)pathValidator->getAlgorithm(nullptr);
492     OUT:
493         FreeCertData(&certsData);
494         CfObjDestroy(pathValidator);
495         return res;
496     }
497 
X509CertChainValidatorCreateFuzzTest(const uint8_t * data,size_t size,CfEncodingFormat certFormat)498     void X509CertChainValidatorCreateFuzzTest(const uint8_t* data, size_t size, CfEncodingFormat certFormat)
499     {
500         if (g_testCertChainValidatorFlag) {
501             (void)CreateOneCertChainValidator();
502             g_testCertChainValidatorFlag = false;
503         }
504         if (data == nullptr || size < sizeof(uint32_t)) {
505             return;
506         }
507         HcfCertChainData certsData = {};
508         certsData.format = certFormat;
509         certsData.count = *reinterpret_cast<const uint32_t *>(data); /* level-2 cert chain. */
510         certsData.dataLen = size;
511         certsData.data = const_cast<uint8_t *>(data);
512         HcfCertChainValidator *pathValidator = nullptr;
513         CfResult res = HcfCertChainValidatorCreate("PKIX", &pathValidator);
514         if (res != CF_SUCCESS) {
515             return;
516         }
517         CfObjDestroy(pathValidator);
518         return;
519     }
520 
FreeCertArrayData(HcfX509CertificateArray * certs)521     static void FreeCertArrayData(HcfX509CertificateArray *certs)
522     {
523         if (certs == nullptr || certs->data == nullptr) {
524             return;
525         }
526         for (uint32_t i = 0; i < certs->count; ++i) {
527             CfObjDestroy(certs->data[i]);
528         }
529         CfFree(certs->data);
530         certs->data = nullptr;
531         certs->count = 0;
532     }
533 
BuildCollectionArrNoCRL(const CfEncodingBlob * certInStream,HcfCertCRLCollectionArray & certCRLCollections)534     static CfResult BuildCollectionArrNoCRL(const CfEncodingBlob *certInStream,
535         HcfCertCRLCollectionArray &certCRLCollections)
536     {
537         CfResult ret = CF_ERR_MALLOC;
538         HcfX509CertificateArray *certArray = nullptr;
539         HcfCertCrlCollection *x509CertCrlCollection = nullptr;
540         if (certInStream != nullptr) {
541             certArray = static_cast<HcfX509CertificateArray *>(CfMalloc(sizeof(HcfX509CertificateArray), 0));
542             if (certArray == nullptr) {
543                 goto Exit;
544             }
545 
546             HcfX509Certificate *x509CertObj = nullptr;
547             (void)HcfX509CertificateCreate(certInStream, &x509CertObj);
548             if (x509CertObj == nullptr) {
549                 goto Exit;
550             }
551 
552             certArray->data = static_cast<HcfX509Certificate **>(CfMalloc(1 * sizeof(HcfX509Certificate *), 0));
553             if (certArray->data == nullptr) {
554                 goto Exit;
555             }
556             certArray->data[0] = x509CertObj;
557             certArray->count = 1;
558         }
559 
560         ret = HcfCertCrlCollectionCreate(certArray, nullptr, &x509CertCrlCollection);
561         if (ret != CF_SUCCESS) {
562             goto Exit;
563         }
564 
565         certCRLCollections.data = static_cast<HcfCertCrlCollection **>(CfMalloc(1 * sizeof(HcfCertCrlCollection *),
566             0));
567         if (certCRLCollections.data == nullptr) {
568             goto Exit;
569         }
570         certCRLCollections.data[0] = x509CertCrlCollection;
571         certCRLCollections.count = 1;
572 
573         FreeCertArrayData(certArray);
574         CfFree(certArray);
575         return CF_SUCCESS;
576     Exit:
577         FreeCertArrayData(certArray);
578         CfFree(certArray);
579         CfFree(certCRLCollections.data);
580         CfObjDestroy(x509CertCrlCollection);
581         return ret;
582     }
583 
FreeCertCrlCollectionArr1(HcfCertCRLCollectionArray & certCRLCollections)584     static void FreeCertCrlCollectionArr1(HcfCertCRLCollectionArray &certCRLCollections)
585     {
586         for (uint32_t i = 0; i < certCRLCollections.count; ++i) {
587             HcfCertCrlCollection *collection = certCRLCollections.data[i];
588             CfObjDestroy(collection);
589         }
590         CfFree(certCRLCollections.data);
591         certCRLCollections.data = nullptr;
592         certCRLCollections.count = 0;
593     }
594 
BuildX509CertMatchParamsDataNoCRL(const CfEncodingBlob * certInStream,HcfX509CertChainValidateParams * params)595     static CfResult BuildX509CertMatchParamsDataNoCRL(const CfEncodingBlob *certInStream,
596         HcfX509CertChainValidateParams *params)
597     {
598         HcfCertCRLCollectionArray *certCRLCollections = nullptr;
599         CfResult ret = CF_ERR_MALLOC;
600         CfBlob *blob = static_cast<CfBlob *>(CfMalloc(sizeof(CfBlob), 0));
601         if (blob == nullptr) {
602             return CF_ERR_MALLOC;
603         }
604         blob->data = reinterpret_cast<uint8_t *>(const_cast<char *>(g_testUpdateDateTime));
605         blob->size = strlen(g_testUpdateDateTime) + 1;
606         params->date = blob;
607 
608         HcfX509TrustAnchorArray *trustAnchorArray =
609             static_cast<HcfX509TrustAnchorArray *>(CfMalloc(sizeof(HcfX509TrustAnchorArray), 0));
610         if (trustAnchorArray == nullptr) {
611             goto Exit;
612         }
613         ret = BuildAnchorArr1(*certInStream, *trustAnchorArray);
614         if (ret != CF_SUCCESS) {
615             goto Exit;
616         }
617 
618         certCRLCollections = static_cast<HcfCertCRLCollectionArray *>(CfMalloc(sizeof(HcfCertCRLCollectionArray), 0));
619         if (certCRLCollections == nullptr) {
620             goto Exit;
621         }
622         ret = BuildCollectionArrNoCRL(certInStream, *certCRLCollections);
623         if (ret != CF_SUCCESS) {
624             goto Exit;
625         }
626         params->trustAnchors = trustAnchorArray;
627         params->certCRLCollections = certCRLCollections;
628         return CF_SUCCESS;
629     Exit:
630         CfFree(blob);
631         FreeTrustAnchorArr1(*trustAnchorArray);
632         CfFree(trustAnchorArray);
633         CfFree(certCRLCollections);
634         return ret;
635     }
636 
FreeX509CertMatchParamsData(HcfX509CertChainValidateParams * params)637     static void FreeX509CertMatchParamsData(HcfX509CertChainValidateParams *params)
638     {
639         if (params == nullptr) {
640             return;
641         }
642 
643         if (params->date != nullptr) {
644             CfFree(params->date);
645             params->date = nullptr;
646         }
647 
648         if (params->trustAnchors != nullptr) {
649             FreeTrustAnchorArr1(*(params->trustAnchors));
650             CfFree(params->trustAnchors);
651             params->trustAnchors = nullptr;
652         }
653 
654         if (params->certCRLCollections != nullptr) {
655             FreeCertCrlCollectionArr1(*(params->certCRLCollections));
656             CfFree(params->certCRLCollections);
657             params->certCRLCollections = nullptr;
658         }
659     }
660 
FreeTrustAnchorData(HcfX509TrustAnchor * trustAnchor)661     static void FreeTrustAnchorData(HcfX509TrustAnchor *trustAnchor)
662     {
663         if (trustAnchor == NULL) {
664             return;
665         }
666         CfBlobFree(&trustAnchor->CAPubKey);
667         CfBlobFree(&trustAnchor->CASubject);
668         CfObjDestroy(trustAnchor->CACert);
669         trustAnchor->CACert = NULL;
670     }
671 
FreeHcfX509CertChainBuildResult(HcfX509CertChainBuildResult * result)672     static void FreeHcfX509CertChainBuildResult(HcfX509CertChainBuildResult *result)
673     {
674         if (result == nullptr) {
675             return;
676         }
677 
678         CfObjDestroy(result->certChain);
679         CfFree(result);
680     }
681 
CreateOneCertChainBuildResultCreate()682     static CfResult CreateOneCertChainBuildResultCreate()
683     {
684         HcfX509CertChainBuildParameters inParams = {};
685         HcfX509CertChainBuildResult *returnObj = nullptr;
686         CfEncodingBlob inStream = { 0 };
687         HcfCertChain *certChain = nullptr;
688         inStream.data = reinterpret_cast<uint8_t *>(const_cast<char *>(g_testSelfSignedCaCertValid));
689         inStream.encodingFormat = CF_FORMAT_PEM;
690         inStream.len = strlen(g_testSelfSignedCaCertValid) + 1;
691 
692         CfResult ret = BuildX509CertMatchParamsDataNoCRL(&inStream, &inParams.validateParameters);
693         if (ret != CF_SUCCESS) {
694             goto Exit;
695         }
696 
697         inParams.maxlength = MAX_DEPTH;
698 
699         CfBlob issue;
700         issue.data = const_cast<uint8_t *>(g_testIssuerValid);
701         issue.size = sizeof(g_testIssuerValid);
702         inParams.certMatchParameters.issuer = &issue;
703         inParams.certMatchParameters.minPathLenConstraint = -1;
704 
705         ret = HcfCertChainBuildResultCreate(&inParams, &returnObj);
706         if (ret != CF_SUCCESS) {
707             goto Exit;
708         }
709         certChain = returnObj->certChain;
710         ret = certChain->validate(certChain, &inParams.validateParameters, &returnObj->validateResult);
711         if (ret != CF_SUCCESS) {
712             goto Exit;
713         }
714 
715     Exit:
716         if (returnObj != nullptr) {
717             FreeTrustAnchorData(returnObj->validateResult.trustAnchor);
718             CF_FREE_PTR(returnObj->validateResult.trustAnchor);
719             CfObjDestroy(returnObj->validateResult.entityCert);
720             FreeHcfX509CertChainBuildResult(returnObj);
721         }
722 
723         FreeX509CertMatchParamsData(&inParams.validateParameters);
724         return ret;
725     }
726 
X509BuildResultCreateFuzzTest(const uint8_t * data,size_t size,CfEncodingFormat certFormat)727     void X509BuildResultCreateFuzzTest(const uint8_t* data, size_t size, CfEncodingFormat certFormat)
728     {
729         if (g_testCertChainBuildResultFlag) {
730             (void)CreateOneCertChainBuildResultCreate();
731             g_testCertChainBuildResultFlag = false;
732         }
733         const char *date = "20231212080000Z";
734         if (data == nullptr || size < sizeof(int32_t) || size < (strlen(date) + 1)) {
735             return;
736         }
737 
738         HcfX509CertChainBuildParameters inParams = {};
739         HcfX509CertChainBuildResult *returnObj = nullptr;
740         CfEncodingBlob inStream = { 0 };
741         inStream.data = reinterpret_cast<uint8_t *>(const_cast<char *>(g_testSelfSignedCaCertValid));
742         inStream.encodingFormat = CF_FORMAT_PEM;
743         inStream.len = strlen(g_testSelfSignedCaCertValid) + 1;
744         CfResult ret = BuildX509CertMatchParamsDataNoCRL(&inStream, &inParams.validateParameters);
745         if (ret != CF_SUCCESS) {
746             return;
747         }
748 
749         inParams.maxlength = *reinterpret_cast<const int32_t *>(data);
750         CfBlob issue;
751         issue.data = const_cast<uint8_t *>(data);
752         issue.size = size;
753         inParams.certMatchParameters.issuer = &issue;
754         inParams.certMatchParameters.minPathLenConstraint = -1;
755 
756         CfBlob validDate;
757         validDate.data = const_cast<uint8_t *>(data);
758         validDate.size = strlen(date) + 1;
759         inParams.certMatchParameters.issuer = &issue;
760 
761         ret = HcfCertChainBuildResultCreate(&inParams, &returnObj);
762         if (ret != CF_SUCCESS) {
763             FreeX509CertMatchParamsData(&inParams.validateParameters);
764             return;
765         }
766         FreeX509CertMatchParamsData(&inParams.validateParameters);
767         FreeHcfX509CertChainBuildResult(returnObj);
768     }
769 
OneCreateTrustAnchorWithKeyStore()770     static void OneCreateTrustAnchorWithKeyStore()
771     {
772         CfBlob keyStore;
773         CfBlob pwd;
774         HcfX509TrustAnchorArray *trustAnchorArray = NULL;
775 
776         keyStore.data = const_cast<uint8_t *>(g_testChainKeystore);
777         keyStore.size = sizeof(g_testChainKeystore);
778         pwd.data = reinterpret_cast<uint8_t *>(const_cast<char *>(g_testKeystorePwd));
779         pwd.size = sizeof(g_testKeystorePwd);
780         CfResult result = HcfCreateTrustAnchorWithKeyStore(&keyStore, &pwd, &trustAnchorArray);
781         if (result != CF_SUCCESS) {
782             return;
783         }
784         FreeTrustAnchorArr1(*trustAnchorArray);
785         CfFree(trustAnchorArray);
786         return;
787     }
788 
X509BuildResultCreateFuzzTest(const uint8_t * data,size_t size)789     void X509BuildResultCreateFuzzTest(const uint8_t* data, size_t size)
790     {
791         if (g_testCreateTrustAnchorFlag) {
792             OneCreateTrustAnchorWithKeyStore();
793             g_testCreateTrustAnchorFlag = false;
794         }
795         CfBlob keyStore;
796         CfBlob pwd;
797         HcfX509TrustAnchorArray *trustAnchorArray = NULL;
798 
799         keyStore.data = const_cast<uint8_t *>(data);
800         keyStore.size = size;
801         pwd.data = reinterpret_cast<uint8_t *>(const_cast<char *>(g_testKeystorePwd));
802         pwd.size = sizeof(g_testKeystorePwd);
803         CfResult result = HcfCreateTrustAnchorWithKeyStore(&keyStore, &pwd, &trustAnchorArray);
804         if (result != CF_SUCCESS) {
805             return;
806         }
807         FreeTrustAnchorArr1(*trustAnchorArray);
808         CfFree(trustAnchorArray);
809         return;
810     }
811     }
812 
813 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)814 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
815 {
816     /* Run your code on data */
817     OHOS::X509CertChainFuzzTest(data, size, CF_FORMAT_DER);
818     OHOS::X509CertChainFuzzTest(data, size, CF_FORMAT_PKCS7);
819     OHOS::X509CertChainFuzzTest(data, size, CF_FORMAT_PEM);
820     OHOS::X509CertChainValidatorCreateFuzzTest(data, size, CF_FORMAT_DER);
821     OHOS::X509CertChainValidatorCreateFuzzTest(data, size, CF_FORMAT_PKCS7);
822     OHOS::X509CertChainValidatorCreateFuzzTest(data, size, CF_FORMAT_PEM);
823     OHOS::X509BuildResultCreateFuzzTest(data, size, CF_FORMAT_DER);
824     OHOS::X509BuildResultCreateFuzzTest(data, size, CF_FORMAT_PKCS7);
825     OHOS::X509BuildResultCreateFuzzTest(data, size, CF_FORMAT_PEM);
826     OHOS::X509BuildResultCreateFuzzTest(data, size);
827     return 0;
828 }
829