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, ¶ms, &result);
325
326 params.policy = VALIDATION_POLICY_TYPE_SSL;
327 (void)spi->engineValidate(spi, ¶ms, &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, ¶ms, &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