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, &notBeforeTime);
99         CfBlobDataClearAndFree(&notBeforeTime);
100 
101         CfBlob notAfterTime = { 0 };
102         (void)x509CertObj->getNotAfterTime(x509CertObj, &notAfterTime);
103         CfBlobDataClearAndFree(&notAfterTime);
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