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 <cstring>
17#include <map>
18#include <securec.h>
19#include <string>
20#include <vector>
21
22#include "net_ssl.h"
23#include "net_ssl_c.h"
24#include "net_ssl_c_type.h"
25#include "net_ssl_type.h"
26#include "net_ssl_verify_cert.h"
27#include "netstack_log.h"
28#include "secure_char.h"
29
30namespace OHOS {
31namespace NetStack {
32namespace Ssl {
33namespace {
34
35const uint8_t *g_baseFuzzData = nullptr;
36size_t g_baseFuzzSize = 0;
37size_t g_baseFuzzPos = 0;
38[[maybe_unused]] constexpr size_t STR_LEN = 255;
39} // namespace
40template <class T> T GetData()
41{
42    T object{};
43    size_t objectSize = sizeof(object);
44    if (g_baseFuzzData == nullptr || g_baseFuzzSize <= g_baseFuzzPos || objectSize > g_baseFuzzSize - g_baseFuzzPos) {
45        return object;
46    }
47    errno_t ret = memcpy_s(&object, objectSize, g_baseFuzzData + g_baseFuzzPos, objectSize);
48    if (ret != EOK) {
49        return object;
50    }
51    g_baseFuzzPos += objectSize;
52    return object;
53}
54
55void SetGlobalFuzzData(const uint8_t *data, size_t size)
56{
57    g_baseFuzzData = data;
58    g_baseFuzzSize = size;
59    g_baseFuzzPos = 0;
60}
61
62std::string GetStringFromData(int strlen)
63{
64    if (strlen < 1) {
65        return "";
66    }
67
68    char cstr[strlen];
69    cstr[strlen - 1] = '\0';
70    for (int i = 0; i < strlen - 1; i++) {
71        cstr[i] = GetData<char>();
72    }
73    std::string str(cstr);
74    return str;
75}
76
77uint8_t *stringToUint8(const std::string &str)
78{
79    uint8_t *data = new uint8_t[str.size() + 1];
80    for (size_t i = 0; i < str.size(); ++i) {
81        data[i] = static_cast<uint8_t>(str[i]);
82    }
83    data[str.size()] = '\0';
84    return data;
85}
86
87void SetNetStackVerifyCertificationTestOne(const uint8_t *data, size_t size)
88{
89    if ((data == nullptr) || (size < 1)) {
90        return;
91    }
92    SetGlobalFuzzData(data, size);
93    std::string str = GetStringFromData(STR_LEN);
94    CertBlob certBlob;
95    certBlob.type = CERT_TYPE_PEM;
96    certBlob.size = str.size();
97    certBlob.data = stringToUint8(str);
98    NetStackVerifyCertification(&certBlob);
99    delete[] certBlob.data;
100    certBlob.data = nullptr;
101}
102
103void SetNetStackVerifyCertificationTestTwo(const uint8_t *data, size_t size)
104{
105    if ((data == nullptr) || (size < 1)) {
106        return;
107    }
108    SetGlobalFuzzData(data, size);
109    std::string str = GetStringFromData(STR_LEN);
110    CertBlob certBlob;
111    certBlob.type = CERT_TYPE_PEM;
112    certBlob.size = str.size();
113    certBlob.data = stringToUint8(str);
114    NetStackVerifyCertification(&certBlob, &certBlob);
115    delete[] certBlob.data;
116    certBlob.data = nullptr;
117}
118
119void SetVerifyCertTestOne(const uint8_t *data, size_t size)
120{
121    if ((data == nullptr) || (size < 1)) {
122        return;
123    }
124    SetGlobalFuzzData(data, size);
125    std::string str = GetStringFromData(STR_LEN);
126    CertBlob certBlob;
127    certBlob.type = CERT_TYPE_PEM;
128    certBlob.size = str.size();
129    certBlob.data = stringToUint8(str);
130    VerifyCert(&certBlob);
131    delete[] certBlob.data;
132    certBlob.data = nullptr;
133}
134
135void SetVerifyCertTestTwo(const uint8_t *data, size_t size)
136{
137    if ((data == nullptr) || (size < 1)) {
138        return;
139    }
140    SetGlobalFuzzData(data, size);
141    std::string str = GetStringFromData(STR_LEN);
142    CertBlob certBlob;
143    certBlob.type = CERT_TYPE_PEM;
144    certBlob.size = str.size();
145    certBlob.data = stringToUint8(str);
146    VerifyCert(&certBlob, &certBlob);
147    delete[] certBlob.data;
148    certBlob.data = nullptr;
149}
150
151void SetFreeResourcesTest(const uint8_t *data, size_t size)
152{
153    if ((data == nullptr) || (size < 1)) {
154        return;
155    }
156    SetGlobalFuzzData(data, size);
157    std::string str = GetStringFromData(STR_LEN);
158    CertBlob certBlob;
159    certBlob.type = CERT_TYPE_PEM;
160    certBlob.size = str.size();
161    certBlob.data = stringToUint8(str);
162    X509 *cert = PemToX509(certBlob.data, certBlob.size);
163    X509_STORE *store = nullptr;
164    X509_STORE_CTX *ctx = nullptr;
165    FreeResources(&cert, &cert, &store, &ctx);
166    delete[] certBlob.data;
167    certBlob.data = nullptr;
168}
169
170void SetPemToX509Test(const uint8_t *data, size_t size)
171{
172    if ((data == nullptr) || (size < 1)) {
173        return;
174    }
175    SetGlobalFuzzData(data, size);
176    std::string str = GetStringFromData(STR_LEN);
177    CertBlob certBlob;
178    certBlob.type = CERT_TYPE_PEM;
179    certBlob.size = str.size();
180    certBlob.data = stringToUint8(str);
181    PemToX509(data, size);
182    delete[] certBlob.data;
183    certBlob.data = nullptr;
184}
185
186void SetDerToX509Test(const uint8_t *data, size_t size)
187{
188    if ((data == nullptr) || (size < 1)) {
189        return;
190    }
191    SetGlobalFuzzData(data, size);
192    std::string str = GetStringFromData(STR_LEN);
193    CertBlob certBlob;
194    certBlob.type = CERT_TYPE_PEM;
195    certBlob.size = str.size();
196    certBlob.data = stringToUint8(str);
197    DerToX509(data, size);
198    delete[] certBlob.data;
199    certBlob.data = nullptr;
200}
201
202void SetCertBlobToX509Test(const uint8_t *data, size_t size)
203{
204    if ((data == nullptr) || (size < 1)) {
205        return;
206    }
207    SetGlobalFuzzData(data, size);
208    std::string str = GetStringFromData(STR_LEN);
209    CertBlob certBlob;
210    certBlob.type = CERT_TYPE_PEM;
211    certBlob.size = str.size();
212    certBlob.data = stringToUint8(str);
213    CertBlobToX509(&certBlob);
214    delete[] certBlob.data;
215    certBlob.data = nullptr;
216}
217
218void SetOHNetStackCertVerificationTest(const uint8_t *data, size_t size)
219{
220    if ((data == nullptr) || (size < 1)) {
221        return;
222    }
223    SetGlobalFuzzData(data, size);
224    std::string str = GetStringFromData(STR_LEN);
225    CertBlob certBlob;
226    certBlob.type = CERT_TYPE_PEM;
227    certBlob.size = str.size();
228    certBlob.data = stringToUint8(str);
229    OH_NetStack_CertVerification((const struct NetStack_CertBlob *)&certBlob,
230                                 (const struct NetStack_CertBlob *)&certBlob);
231    delete[] certBlob.data;
232    certBlob.data = nullptr;
233}
234
235} // namespace Ssl
236} // namespace NetStack
237} // namespace OHOS
238
239/* Fuzzer entry point */
240extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
241{
242    /* Run your code on data */
243    OHOS::NetStack::Ssl::SetNetStackVerifyCertificationTestOne(data, size);
244    OHOS::NetStack::Ssl::SetNetStackVerifyCertificationTestTwo(data, size);
245    OHOS::NetStack::Ssl::SetVerifyCertTestOne(data, size);
246    OHOS::NetStack::Ssl::SetVerifyCertTestTwo(data, size);
247    OHOS::NetStack::Ssl::SetFreeResourcesTest(data, size);
248    OHOS::NetStack::Ssl::SetPemToX509Test(data, size);
249    OHOS::NetStack::Ssl::SetDerToX509Test(data, size);
250    OHOS::NetStack::Ssl::SetCertBlobToX509Test(data, size);
251    OHOS::NetStack::Ssl::SetOHNetStackCertVerificationTest(data, size);
252    return 0;
253}