Coverage Report

Created: 2022-08-24 06:31

/src/cryptofuzz/wycheproof.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <cryptofuzz/wycheproof.h>
2
#include <cryptofuzz/repository.h>
3
#include <cryptofuzz/operations.h>
4
#include <cryptofuzz/util.h>
5
#include <cryptofuzz/crypto.h>
6
#include <stdio.h>
7
#include <fstream>
8
9
namespace cryptofuzz {
10
11
Wycheproof::Wycheproof(const std::string filename, const std::string outDir) :
12
0
    outDir(outDir) {
13
0
    std::ifstream ifs(filename);
14
0
    j = nlohmann::json::parse(ifs);
15
0
}
16
17
0
void Wycheproof::Run(void) {
18
0
    const auto& groups = j["testGroups"];
19
20
0
    if ( j["schema"].get<std::string>() == "ecdsa_verify_schema.json" ) {
21
0
        ECDSA_Verify(groups);
22
0
    } else if ( j["schema"].get<std::string>() == "eddsa_verify_schema.json" ) {
23
0
        EDDSA_Verify(groups);
24
0
    } else if ( j["schema"].get<std::string>() == "ecdh_test_schema.json" ) {
25
0
        ECDH(groups);
26
0
    }
27
0
}
28
29
0
void Wycheproof::write(const uint64_t operation, fuzzing::datasource::Datasource& dsOut2) {
30
0
    fuzzing::datasource::Datasource dsOut(nullptr, 0);
31
32
    /* Operation ID */
33
0
    dsOut.Put<uint64_t>(operation);
34
35
0
    dsOut.PutData(dsOut2.GetOut());
36
37
    /* Modifier */
38
0
    dsOut.PutData(std::vector<uint8_t>(0));
39
40
    /* Module ID */
41
0
    dsOut.Put<uint64_t>(CF_MODULE("OpenSSL"));
42
43
    /* Terminator */
44
0
    dsOut.Put<bool>(false);
45
46
0
    {
47
        //std::string filename = outDir + std::string("/") + std::to_string(counter++);
48
0
        std::string filename = outDir + std::string("/") + util::SHA1(dsOut.GetOut());
49
0
        FILE* fp = fopen(filename.c_str(), "wb");
50
0
        fwrite(dsOut.GetOut().data(), dsOut.GetOut().size(), 1, fp);
51
0
        fclose(fp);
52
0
    }
53
0
}
54
55
0
void Wycheproof::ECDSA_Verify(const nlohmann::json& groups) {
56
0
    for (const auto &group : groups) {
57
0
        for (const auto &test : group["tests"]) {
58
0
            nlohmann::json
59
0
                p_ecdsa_verify,
60
0
                p_ecc_point_add,
61
0
                p_ecc_point_mul_1,
62
0
                p_ecc_point_mul_2,
63
0
                p_ecc_validatepubkey_1,
64
0
                p_ecc_validatepubkey_2;
65
0
            std::string digest;
66
67
0
            {
68
0
                const std::string curve = group["key"]["curve"];
69
0
                auto curveID = repository::ECC_CurveFromString(curve);
70
71
0
                if ( curveID == std::nullopt ) {
72
0
                    if ( curve == "brainpoolP224r1" ) {
73
0
                        curveID = CF_ECC_CURVE("brainpool224r1");
74
0
                    } else if ( curve == "brainpoolP224t1" ) {
75
0
                        curveID = CF_ECC_CURVE("brainpool224t1");
76
0
                    } else if ( curve == "brainpoolP256r1" ) {
77
0
                        curveID = CF_ECC_CURVE("brainpool256r1");
78
0
                    } else if ( curve == "brainpoolP256t1" ) {
79
0
                        curveID = CF_ECC_CURVE("brainpool256t1");
80
0
                    } else if ( curve == "brainpoolP320r1" ) {
81
0
                        curveID = CF_ECC_CURVE("brainpool320r1");
82
0
                    } else if ( curve == "brainpoolP320t1" ) {
83
0
                        curveID = CF_ECC_CURVE("brainpool320t1");
84
0
                    } else if ( curve == "brainpoolP384r1" ) {
85
0
                        curveID = CF_ECC_CURVE("brainpool384r1");
86
0
                    } else if ( curve == "brainpoolP384t1" ) {
87
0
                        curveID = CF_ECC_CURVE("brainpool384t1");
88
0
                    } else if ( curve == "brainpoolP512r1" ) {
89
0
                        curveID = CF_ECC_CURVE("brainpool512r1");
90
0
                    } else if ( curve == "brainpoolP512t1" ) {
91
0
                        curveID = CF_ECC_CURVE("brainpool512t1");
92
0
                    } else {
93
0
                        CF_ASSERT(0, "Curve not recognized");
94
0
                    }
95
0
                }
96
97
0
                p_ecdsa_verify["curveType"] = *curveID;
98
0
                p_ecc_point_add["curveType"] = *curveID;
99
0
                p_ecc_point_mul_1["curveType"] = *curveID;
100
0
                p_ecc_point_mul_2["curveType"] = *curveID;
101
0
                p_ecc_validatepubkey_1["curveType"] = *curveID;
102
0
                p_ecc_validatepubkey_2["curveType"] = *curveID;
103
0
            }
104
105
0
            {
106
0
                digest = group["sha"];
107
108
0
                if ( digest == "SHA-224") {
109
0
                    p_ecdsa_verify["digestType"] = CF_DIGEST("SHA224");
110
0
                } else if ( digest == "SHA-256") {
111
0
                    p_ecdsa_verify["digestType"] = CF_DIGEST("SHA256");
112
0
                } else if ( digest == "SHA-384") {
113
0
                    p_ecdsa_verify["digestType"] = CF_DIGEST("SHA384");
114
0
                } else if ( digest == "SHA-512") {
115
0
                    p_ecdsa_verify["digestType"] = CF_DIGEST("SHA512");
116
0
                } else if ( digest == "SHA3-224") {
117
0
                    p_ecdsa_verify["digestType"] = CF_DIGEST("SHA3-224");
118
0
                } else if ( digest == "SHA3-256") {
119
0
                    p_ecdsa_verify["digestType"] = CF_DIGEST("SHA3-256");
120
0
                } else if ( digest == "SHA3-384") {
121
0
                    p_ecdsa_verify["digestType"] = CF_DIGEST("SHA3-384");
122
0
                } else if ( digest == "SHA3-512") {
123
0
                    p_ecdsa_verify["digestType"] = CF_DIGEST("SHA3-512");
124
0
                } else {
125
0
                    CF_ASSERT(0, "Digest not recognized");
126
0
                }
127
0
            }
128
129
0
            p_ecdsa_verify["signature"]["pub"][0] = util::HexToDec(group["key"]["wx"]);
130
0
            p_ecdsa_verify["signature"]["pub"][1] = util::HexToDec(group["key"]["wy"]);
131
132
0
            p_ecc_point_add["a_x"] = util::HexToDec(group["key"]["wx"]);
133
0
            p_ecc_point_add["a_y"] = util::HexToDec(group["key"]["wy"]);
134
135
0
            p_ecc_point_mul_1["a_x"] = util::HexToDec(group["key"]["wx"]);
136
0
            p_ecc_point_mul_1["a_y"] = util::HexToDec(group["key"]["wy"]);
137
138
0
            p_ecc_validatepubkey_1["pub_x"] = util::HexToDec(group["key"]["wx"]);
139
0
            p_ecc_validatepubkey_1["pub_y"] = util::HexToDec(group["key"]["wy"]);
140
141
0
            {
142
0
                const auto sig = util::SignatureFromDER(test["sig"].get<std::string>());
143
0
                CF_CHECK_NE(sig, std::nullopt);
144
145
0
                p_ecdsa_verify["signature"]["signature"][0] = sig->first;
146
0
                p_ecdsa_verify["signature"]["signature"][1] = sig->second;
147
148
0
                p_ecc_point_add["b_x"] = sig->first;
149
0
                p_ecc_point_add["b_y"] = sig->second;
150
151
0
                p_ecc_point_mul_2["a_x"] = sig->first;
152
0
                p_ecc_point_mul_2["a_y"] = sig->second;
153
154
0
                p_ecc_validatepubkey_2["pub_x"] = sig->first;
155
0
                p_ecc_validatepubkey_2["pub_y"] = sig->second;
156
0
            }
157
158
0
            p_ecdsa_verify["cleartext"] = test["msg"].get<std::string>();
159
160
            /* Construct and write ECDSA_Verify */
161
0
            {
162
0
                p_ecdsa_verify["modifier"] = "";
163
164
0
                fuzzing::datasource::Datasource dsOut2(nullptr, 0);
165
0
                cryptofuzz::operation::ECDSA_Verify op(p_ecdsa_verify);
166
0
                op.Serialize(dsOut2);
167
168
0
                write(CF_OPERATION("ECDSA_Verify"), dsOut2);
169
0
            }
170
171
            /* If digest type is SHA256, compute the SHA256 hash of the message,
172
             * and use this to write an input that uses the NULL digest */
173
0
            if ( digest == "SHA-256" ) {
174
                /* Hex-decode cleartext */
175
0
                std::vector<uint8_t> ct_sha256;
176
0
                boost::algorithm::unhex(
177
0
                        test["msg"].get<std::string>(),
178
0
                        std::back_inserter(ct_sha256));
179
0
                const auto ct = crypto::sha256(ct_sha256);
180
181
0
                std::string ct_hex;
182
0
                boost::algorithm::hex(ct, std::back_inserter(ct_hex));
183
184
0
                p_ecdsa_verify["cleartext"] = ct_hex;
185
0
                p_ecdsa_verify["digestType"] = CF_DIGEST("NULL");
186
187
0
                fuzzing::datasource::Datasource dsOut2(nullptr, 0);
188
0
                cryptofuzz::operation::ECDSA_Verify op(p_ecdsa_verify);
189
0
                op.Serialize(dsOut2);
190
191
0
                write(CF_OPERATION("ECDSA_Verify"), dsOut2);
192
0
            }
193
194
0
            {
195
0
                p_ecc_point_add["modifier"] = "";
196
197
0
                fuzzing::datasource::Datasource dsOut2(nullptr, 0);
198
0
                cryptofuzz::operation::ECC_Point_Add op(p_ecc_point_add);
199
0
                op.Serialize(dsOut2);
200
201
0
                write(CF_OPERATION("ECC_Point_Add"), dsOut2);
202
0
            }
203
204
0
            {
205
0
                p_ecc_point_mul_1["modifier"] = "";
206
0
                p_ecc_point_mul_1["b"] = "1";
207
0
                fuzzing::datasource::Datasource dsOut2(nullptr, 0);
208
0
                cryptofuzz::operation::ECC_Point_Mul op(p_ecc_point_mul_1);
209
0
                op.Serialize(dsOut2);
210
211
0
                write(CF_OPERATION("ECC_Point_Mul"), dsOut2);
212
0
            }
213
214
0
            {
215
0
                p_ecc_point_mul_2["modifier"] = "";
216
0
                p_ecc_point_mul_2["b"] = "1";
217
0
                fuzzing::datasource::Datasource dsOut2(nullptr, 0);
218
0
                cryptofuzz::operation::ECC_Point_Mul op(p_ecc_point_mul_2);
219
0
                op.Serialize(dsOut2);
220
221
0
                write(CF_OPERATION("ECC_Point_Mul"), dsOut2);
222
0
            }
223
224
0
            {
225
0
                p_ecc_validatepubkey_1["modifier"] = "";
226
0
                fuzzing::datasource::Datasource dsOut2(nullptr, 0);
227
0
                cryptofuzz::operation::ECC_ValidatePubkey op(p_ecc_validatepubkey_1);
228
0
                op.Serialize(dsOut2);
229
230
0
                write(CF_OPERATION("ECC_ValidatePubkey"), dsOut2);
231
0
            }
232
233
0
            {
234
0
                p_ecc_validatepubkey_2["modifier"] = "";
235
0
                fuzzing::datasource::Datasource dsOut2(nullptr, 0);
236
0
                cryptofuzz::operation::ECC_ValidatePubkey op(p_ecc_validatepubkey_2);
237
0
                op.Serialize(dsOut2);
238
239
0
                write(CF_OPERATION("ECC_ValidatePubkey"), dsOut2);
240
0
            }
241
242
0
end:
243
0
            (void)1;
244
0
        }
245
0
    }
246
0
}
247
248
0
void Wycheproof::EDDSA_Verify(const nlohmann::json& groups) {
249
0
    for (const auto &group : groups) {
250
0
        for (const auto &test : group["tests"]) {
251
0
            nlohmann::json parameters;
252
253
0
            {
254
0
                const std::string curve = group["key"]["curve"];
255
256
0
                if ( curve == "edwards448" ) {
257
0
                    parameters["curveType"] = CF_ECC_CURVE("ed448");
258
0
                } else {
259
0
                    CF_ASSERT(0, "Curve not recognized");
260
0
                }
261
0
            }
262
263
0
            parameters["digestType"] = CF_DIGEST("NULL");
264
265
0
            parameters["signature"]["pub"][0] = util::HexToDec(group["key"]["pk"]);
266
0
            parameters["signature"]["pub"][1] = "0";
267
268
0
            {
269
0
                const auto sig = test["sig"].get<std::string>();
270
0
                CF_CHECK_EQ(sig.size() % 4, 0);
271
272
0
                const auto R = std::string(sig.data(), sig.data() + (sig.size() / 2));
273
0
                const auto S = std::string(sig.data() + (sig.size() / 2), sig.data() + sig.size());
274
275
0
                parameters["signature"]["signature"][0] = util::HexToDec(R);
276
0
                parameters["signature"]["signature"][1] = util::HexToDec(S);
277
0
            }
278
279
0
            parameters["cleartext"] = test["msg"].get<std::string>();
280
281
0
            parameters["modifier"] = std::string(1000, '0');
282
0
            {
283
0
                fuzzing::datasource::Datasource dsOut2(nullptr, 0);
284
0
                cryptofuzz::operation::ECDSA_Verify op(parameters);
285
0
                op.Serialize(dsOut2);
286
287
0
                write(CF_OPERATION("ECDSA_Verify"), dsOut2);
288
0
            }
289
290
0
end:
291
0
            (void)1;
292
0
        }
293
0
    }
294
0
}
295
296
0
void Wycheproof::ECDH(const nlohmann::json& groups) {
297
0
    for (const auto &group : groups) {
298
0
        for (const auto &test : group["tests"]) {
299
0
            nlohmann::json parameters;
300
301
0
            parameters["modifier"] = "";
302
303
0
            {
304
0
                const std::string curve = group["curve"];
305
0
                auto curveID = repository::ECC_CurveFromString(curve);
306
307
0
                if ( curveID == std::nullopt ) {
308
0
                    if ( curve == "brainpoolP224r1" ) {
309
0
                        curveID = CF_ECC_CURVE("brainpool224r1");
310
0
                    } else if ( curve == "brainpoolP224t1" ) {
311
0
                        curveID = CF_ECC_CURVE("brainpool224t1");
312
0
                    } else if ( curve == "brainpoolP256r1" ) {
313
0
                        curveID = CF_ECC_CURVE("brainpool256r1");
314
0
                    } else if ( curve == "brainpoolP256t1" ) {
315
0
                        curveID = CF_ECC_CURVE("brainpool256t1");
316
0
                    } else if ( curve == "brainpoolP320r1" ) {
317
0
                        curveID = CF_ECC_CURVE("brainpool320r1");
318
0
                    } else if ( curve == "brainpoolP320t1" ) {
319
0
                        curveID = CF_ECC_CURVE("brainpool320t1");
320
0
                    } else if ( curve == "brainpoolP384r1" ) {
321
0
                        curveID = CF_ECC_CURVE("brainpool384r1");
322
0
                    } else if ( curve == "brainpoolP384t1" ) {
323
0
                        curveID = CF_ECC_CURVE("brainpool384t1");
324
0
                    } else if ( curve == "brainpoolP512r1" ) {
325
0
                        curveID = CF_ECC_CURVE("brainpool512r1");
326
0
                    } else if ( curve == "brainpoolP512t1" ) {
327
0
                        curveID = CF_ECC_CURVE("brainpool512t1");
328
0
                    } else {
329
0
                        CF_ASSERT(0, "Curve not recognized");
330
0
                    }
331
0
                }
332
333
0
                parameters["curveType"] = *curveID;
334
335
0
                parameters["priv"] = util::HexToDec(test["private"]);
336
337
0
                {
338
0
                    const auto pub = util::PubkeyFromASN1(*curveID, test["public"].get<std::string>());
339
0
                    CF_CHECK_NE(pub, std::nullopt);
340
341
0
                    parameters["pub_x"] = pub->first;
342
0
                    parameters["pub_y"] = pub->second;
343
0
                }
344
0
            }
345
346
0
            {
347
0
                fuzzing::datasource::Datasource dsOut2(nullptr, 0);
348
0
                cryptofuzz::operation::ECDH_Derive op(parameters);
349
0
                op.Serialize(dsOut2);
350
351
0
                write(CF_OPERATION("ECDH_Derive"), dsOut2);
352
0
            }
353
0
end:
354
0
            (void)1;
355
0
        }
356
0
    }
357
0
}
358
359
} /* namespace cryptofuzz */