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 "x509certificate_fuzzer.h"
17
18 #include <cstddef>
19 #include <cstdint>
20 #include "securec.h"
21
22 #include "pub_key.h"
23 #include "cf_blob.h"
24 #include "cf_result.h"
25 #include "x509_certificate.h"
26
27 namespace OHOS {
28 static char g_fuzzCert[] =
29 "-----BEGIN CERTIFICATE-----\r\n"
30 "MIIEMjCCAxqgAwIBAgICARAwDQYJKoZIhvcNAQELBQAwdjELMAkGA1UEBhMCQ04x\r\n"
31 "CzAJBgNVBAgMAkJKMQswCQYDVQQHDAJCSjELMAkGA1UECgwCSEQxDDAKBgNVBAsM\r\n"
32 "A2RldjELMAkGA1UEAwwCY2ExJTAjBgkqhkiG9w0BCQEWFmNhQGNyeXB0b2ZyYW1l\r\n"
33 "d29yay5jb20wHhcNMjIwODE5MTI0OTA2WhcNMzIwODE2MTI0OTA2WjB2MQswCQYD\r\n"
34 "VQQGEwJDTjELMAkGA1UECAwCQkoxCzAJBgNVBAcMAkJKMQswCQYDVQQKDAJIRDEM\r\n"
35 "MAoGA1UECwwDZGV2MQswCQYDVQQDDAJjYTElMCMGCSqGSIb3DQEJARYWY2FAY3J5\r\n"
36 "cHRvZnJhbWV3b3JrLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\r\n"
37 "AJ8p0IWE7WwwbtATg+AbYQj33WNBBktU+/AVf+Tl1aAa4TOeW2/ZARc4sdwLVTxd\r\n"
38 "XCipFseuiGN30hwXrXFUHrcMf0w2sCkznJVZ/rQcfEO5Kb1vBz6DEEcgISYEhhqO\r\n"
39 "BfYBit5qfpq5R2+2R/Th/ybV+kBrUl+GssXbDAe6oZCy56lGphDvmHMUO7a13j+S\r\n"
40 "FmThMbI2yeyua1LagSoaBJfY1J+i7jWPmmEFR0dQ2p0EGjHTgQGhRo5VuwDHipNS\r\n"
41 "v0XP8OUA/PYbL/SBj1Fq4C3gtfvjeswUbzVaMoq/wCuy1qcXI80ZLe3whR24c0cX\r\n"
42 "YFO0uGi9egPp24fw7yYGqgECAwEAAaOByTCBxjAdBgNVHQ4EFgQUjKM7QmMBs01R\r\n"
43 "9uQttYN/GDkvt7UwHwYDVR0jBBgwFoAUjKM7QmMBs01R9uQttYN/GDkvt7UwEgYD\r\n"
44 "VR0TAQH/BAgwBgEB/wIBAjALBgNVHQ8EBAMCAQYwHQYDVR0lBBYwFAYIKwYBBQUH\r\n"
45 "AwEGCCsGAQUFBwMCMCEGA1UdEQQaMBiBFmNhQGNyeXB0b2ZyYW1ld29yay5jb20w\r\n"
46 "IQYDVR0SBBowGIEWY2FAY3J5cHRvZnJhbWV3b3JrLmNvbTANBgkqhkiG9w0BAQsF\r\n"
47 "AAOCAQEAh+4RE6cJ62/gLYssLkc7ESg7exKwZlmisHyBicuy/+XagOZ3cTbgQNXl\r\n"
48 "QoZKbw/ks/B/cInbQGYbpAm47Sudo+I/G9xj0X7gQB9wtSrbStOs6SjnLiYU0xFc\r\n"
49 "Fsc0j6k2SrlyiwRQcjS4POKiUS0Cm3F3DHGdj55PlBkXxudXCq2V3J3VwKf2bVjQ\r\n"
50 "bzz2+M/Q1m+P7FhB+JmeO8eemkqMQ0tFMU3EM441NpejC5iFVAGgownC8S0B+fxH\r\n"
51 "9dBJuHM6vpxEWw3ckZFDZQ1kd91YRgr7jY8fc0v/T0tzHWbOEVzklEIBWL1mompL\r\n"
52 "BCwe0/Gw+BO60bfi2MoJw8t2IcB1Qw==\r\n"
53 "-----END CERTIFICATE-----\r\n";
54
55 static bool g_testFlag = true;
56
TestGetEncoded(HcfX509Certificate * x509CertObj)57 static void TestGetEncoded(HcfX509Certificate *x509CertObj)
58 {
59 CfEncodingBlob derBlob = { 0 };
60 CfResult res = x509CertObj->base.getEncoded(&(x509CertObj->base), &derBlob);
61 if (res != CF_SUCCESS) {
62 return;
63 }
64 free(derBlob.data);
65 }
66
TestVerify(HcfX509Certificate * x509CertObj)67 static void TestVerify(HcfX509Certificate *x509CertObj)
68 {
69 HcfPubKey *keyOut = nullptr;
70 CfResult res = x509CertObj->base.getPublicKey(&(x509CertObj->base), (void **)&keyOut);
71 if (res != CF_SUCCESS) {
72 return;
73 }
74 (void)x509CertObj->base.verify(&(x509CertObj->base), keyOut);
75 CfObjDestroy(keyOut);
76
77 const char *date = "231018162433Z";
78 // validatetime :2022/08/19 - 2032/08/16
79 x509CertObj->checkValidityWithDate(x509CertObj, date);
80 }
81
TestQuery(HcfX509Certificate * x509CertObj)82 static void TestQuery(HcfX509Certificate *x509CertObj)
83 {
84 CfBlob sn = { 0 };
85 (void)x509CertObj->getSerialNumber(x509CertObj, &sn);
86 CfBlobDataClearAndFree(&sn);
87
88 CfBlob issuerName = { 0 };
89 (void)x509CertObj->getIssuerName(x509CertObj, &issuerName);
90 CfBlobDataClearAndFree(&issuerName);
91
92 CfBlob subjectName = { 0 };
93 (void)x509CertObj->getSubjectName(x509CertObj, &subjectName);
94 (void)x509CertObj->getSubjectNameEx(x509CertObj, CF_ENCODING_UTF8, &subjectName);
95 CfBlobDataClearAndFree(&subjectName);
96
97 CfBlob notBeforeTime = { 0 };
98 (void)x509CertObj->getNotBeforeTime(x509CertObj, ¬BeforeTime);
99 CfBlobDataClearAndFree(¬BeforeTime);
100
101 CfBlob notAfterTime = { 0 };
102 (void)x509CertObj->getNotAfterTime(x509CertObj, ¬AfterTime);
103 CfBlobDataClearAndFree(¬AfterTime);
104
105 CfBlob sigOut = { 0 };
106 (void)x509CertObj->getSignature(x509CertObj, &sigOut);
107 CfBlobDataClearAndFree(&sigOut);
108
109 CfBlob sigAlgOid = { 0 };
110 (void)x509CertObj->getSignatureAlgOid(x509CertObj, &sigAlgOid);
111 CfBlobDataClearAndFree(&sigAlgOid);
112
113 CfBlob sigAlgParamsOut = { 0 };
114 (void)x509CertObj->getSignatureAlgParams(x509CertObj, &sigAlgParamsOut);
115 CfBlobDataClearAndFree(&sigAlgParamsOut);
116
117 CfBlob sigAlgName = { 0 };
118 (void)x509CertObj->getSignatureAlgName(x509CertObj, &sigAlgName);
119 CfBlobDataClearAndFree(&sigAlgName);
120
121 CfArray keyUsageOut = { 0 };
122 (void)x509CertObj->getExtKeyUsage(x509CertObj, &keyUsageOut);
123 CfArrayDataClearAndFree(&keyUsageOut);
124
125 int32_t pathLen = x509CertObj->getBasicConstraints(x509CertObj);
126 if (pathLen < 0) {
127 return;
128 }
129 CfArray subjectAltName = { 0 };
130 (void)x509CertObj->getSubjectAltNames(x509CertObj, &subjectAltName);
131 CfArrayDataClearAndFree(&subjectAltName);
132
133 CfArray outName = { 0 };
134 (void)x509CertObj->getIssuerAltNames(x509CertObj, &outName);
135 CfArrayDataClearAndFree(&outName);
136
137 CfBlob out = { 0 };
138 (void)x509CertObj->getKeyUsage(x509CertObj, &out);
139 CfBlobDataClearAndFree(&out);
140
141 CfArray outURI = { nullptr, CF_FORMAT_DER, 0 };
142 (void)x509CertObj->getCRLDistributionPointsURI(x509CertObj, &outURI);
143 CfArrayDataClearAndFree(&outURI);
144 }
145
TestQueryName(HcfX509Certificate * x509CertObj)146 static void TestQueryName(HcfX509Certificate *x509CertObj)
147 {
148 CfBlob toStringOut = { 0 };
149 (void)x509CertObj->toString(x509CertObj, &toStringOut);
150 CfBlobDataClearAndFree(&toStringOut);
151
152 CfBlob hashCodeOut = { 0 };
153 (void)x509CertObj->hashCode(x509CertObj, &hashCodeOut);
154 CfBlobDataClearAndFree(&hashCodeOut);
155
156 CfBlob extensionsObjectOut = { 0 };
157 (void)x509CertObj->getExtensionsObject(x509CertObj, &extensionsObjectOut);
158 CfBlobDataClearAndFree(&extensionsObjectOut);
159 }
160
CreateOneCert(void)161 static void CreateOneCert(void)
162 {
163 CfEncodingBlob inStream = { 0 };
164 inStream.data = reinterpret_cast<uint8_t *>(g_fuzzCert);
165 inStream.encodingFormat = CF_FORMAT_PEM;
166 inStream.len = strlen(g_fuzzCert) + 1;
167 HcfX509Certificate *x509CertObj = nullptr;
168 CfResult res = HcfX509CertificateCreate(&inStream, &x509CertObj);
169 if (res != CF_SUCCESS) {
170 return;
171 }
172 TestGetEncoded(x509CertObj);
173 TestVerify(x509CertObj);
174 TestQuery(x509CertObj);
175 TestQueryName(x509CertObj);
176 }
177
X509CertificateFuzzTest(const uint8_t * data,size_t size)178 bool X509CertificateFuzzTest(const uint8_t* data, size_t size)
179 {
180 if (g_testFlag) {
181 CreateOneCert();
182 g_testFlag = false;
183 }
184 if (data == nullptr) {
185 return false;
186 }
187 CfEncodingBlob inStream = { 0 };
188 inStream.data = const_cast<uint8_t *>(data);
189 inStream.encodingFormat = CF_FORMAT_PEM;
190 inStream.len = size;
191 HcfX509Certificate *x509CertObj = nullptr;
192 CfResult res = HcfX509CertificateCreate(&inStream, &x509CertObj);
193 if (res != CF_SUCCESS) {
194 return false;
195 }
196 CfObjDestroy(x509CertObj);
197 return true;
198 }
199 }
200
201 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)202 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
203 {
204 /* Run your code on data */
205 OHOS::X509CertificateFuzzTest(data, size);
206 return 0;
207 }
208