Coverage Report

Created: 2024-02-25 06:16

/src/cryptofuzz/options.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <cryptofuzz/options.h>
2
#include <boost/algorithm/string.hpp>
3
#include <boost/algorithm/string/predicate.hpp>
4
#include <iostream>
5
#include <stdlib.h>
6
#include <cryptofuzz/repository.h>
7
#include <cryptofuzz/wycheproof.h>
8
#include <cryptofuzz/ecc_diff_fuzzer_importer.h>
9
#include <cryptofuzz/ecc_diff_fuzzer_exporter.h>
10
#include <cryptofuzz/botan_importer.h>
11
#include <cryptofuzz/openssl_importer.h>
12
#include <cryptofuzz/builtin_tests_importer.h>
13
#include <cryptofuzz/bignum_fuzzer_importer.h>
14
#include <cryptofuzz/util.h>
15
16
namespace cryptofuzz {
17
18
240k
bool EnabledTypes::Have(const uint64_t id) const {
19
240k
    return types.empty() || HaveExplicit(id);
20
240k
}
21
22
565k
bool EnabledTypes::HaveExplicit(const uint64_t id) const {
23
565k
    return types.find(id) != types.end();
24
565k
}
25
26
0
void EnabledTypes::Add(const uint64_t id) {
27
0
    types.insert(id);
28
0
}
29
30
0
uint64_t EnabledTypes::At(const size_t index) const {
31
0
    CF_ASSERT(!Empty(), "Calling At on empty container");
32
33
0
    std::set<uint64_t>::const_iterator it = types.begin();
34
0
    std::advance(it, index % types.size());
35
36
0
    return *it;
37
0
}
38
39
456
bool EnabledTypes::Empty(void) const {
40
456
    return types.empty();
41
456
}
42
43
0
std::string Options::calcOpToBase(const std::string calcOp) {
44
0
    std::vector<std::string> calcOpParts;
45
0
    boost::split(calcOpParts, calcOp, boost::is_any_of("("));
46
0
    if ( calcOpParts.empty() ) {
47
0
        printf("Cannot parse calcop\n");
48
0
        abort();
49
0
    }
50
0
    return calcOpParts[0];
51
0
}
52
53
4
Options::Options(const int argc, char** argv, const std::vector<std::string> extraArguments) {
54
26
    for (int i = 0; i < argc; i++) {
55
22
        arguments.push_back( std::string(argv[i]) );
56
22
    }
57
58
4
    arguments.insert(arguments.end(), extraArguments.begin(), extraArguments.end());
59
60
26
    for (size_t i = 1; i < arguments.size(); i++) {
61
22
        const auto arg = arguments[i];
62
22
        std::vector<std::string> parts;
63
22
        boost::split(parts, arg, boost::is_any_of("="));
64
65
22
        if ( arg == "--debug" ) {
66
0
            debug = true;
67
22
        } else if ( !parts.empty() && parts[0] == "--operations" ) {
68
0
            if ( parts.size() != 2 ) {
69
0
                std::cout << "Expected argument after --operations=" << std::endl;
70
0
                exit(1);
71
0
            }
72
73
0
            std::vector<std::string> operationStrings;
74
0
            boost::split(operationStrings, parts[1], boost::is_any_of(","));
75
76
0
            for (const auto& curOpStr : operationStrings) {
77
0
                bool found = false;
78
0
                for (size_t i = 0; i < (sizeof(repository::OperationLUT) / sizeof(repository::OperationLUT[0])); i++) {
79
0
                    if ( boost::iequals(curOpStr, std::string(repository::OperationLUT[i].name)) ) {
80
0
                        this->operations.Add(repository::OperationLUT[i].id);
81
0
                        found = true;
82
0
                        break;
83
0
                    }
84
0
                }
85
86
0
                if ( found == false ) {
87
0
                    std::cout << "Undefined operation: " << curOpStr << std::endl;
88
0
                    exit(1);
89
0
                }
90
0
            }
91
22
        } else if ( !parts.empty() && parts[0] == "--ciphers" ) {
92
0
            if ( parts.size() != 2 ) {
93
0
                std::cout << "Expected argument after --ciphers=" << std::endl;
94
0
                exit(1);
95
0
            }
96
97
0
            std::vector<std::string> cipherStrings;
98
0
            boost::split(cipherStrings, parts[1], boost::is_any_of(","));
99
100
0
            for (const auto& curOpStr : cipherStrings) {
101
0
                bool found = false;
102
0
                for (size_t i = 0; i < (sizeof(repository::CipherLUT) / sizeof(repository::CipherLUT[0])); i++) {
103
0
                    if ( boost::iequals(curOpStr, std::string(repository::CipherLUT[i].name)) ) {
104
0
                        this->ciphers.Add(repository::CipherLUT[i].id);
105
0
                        found = true;
106
0
                        break;
107
0
                    }
108
0
                }
109
110
0
                if ( found == false ) {
111
0
                    std::cout << "Undefined cipher: " << curOpStr << std::endl;
112
0
                    exit(1);
113
0
                }
114
0
            }
115
22
        } else if ( !parts.empty() && parts[0] == "--digests" ) {
116
0
            if ( parts.size() != 2 ) {
117
0
                std::cout << "Expected argument after --digests=" << std::endl;
118
0
                exit(1);
119
0
            }
120
121
0
            std::vector<std::string> digestStrings;
122
0
            boost::split(digestStrings, parts[1], boost::is_any_of(","));
123
124
0
            for (const auto& curOpStr : digestStrings) {
125
0
                bool found = false;
126
0
                for (size_t i = 0; i < (sizeof(repository::DigestLUT) / sizeof(repository::DigestLUT[0])); i++) {
127
0
                    if ( boost::iequals(curOpStr, std::string(repository::DigestLUT[i].name)) ) {
128
0
                        this->digests.Add(repository::DigestLUT[i].id);
129
0
                        found = true;
130
0
                        break;
131
0
                    }
132
0
                }
133
134
0
                if ( found == false ) {
135
0
                    std::cout << "Undefined digest: " << curOpStr << std::endl;
136
0
                    exit(1);
137
0
                }
138
0
            }
139
22
        } else if ( !parts.empty() && parts[0] == "--curves" ) {
140
0
            if ( parts.size() != 2 ) {
141
0
                std::cout << "Expected argument after --curves=" << std::endl;
142
0
                exit(1);
143
0
            }
144
145
0
            std::vector<std::string> curveStrings;
146
0
            boost::split(curveStrings, parts[1], boost::is_any_of(","));
147
148
0
            for (const auto& curOpStr : curveStrings) {
149
0
                bool found = false;
150
0
                for (size_t i = 0; i < (sizeof(repository::ECC_CurveLUT) / sizeof(repository::ECC_CurveLUT[0])); i++) {
151
0
                    if ( boost::iequals(curOpStr, std::string(repository::ECC_CurveLUT[i].name)) ) {
152
0
                        this->curves.Add(repository::ECC_CurveLUT[i].id);
153
0
                        found = true;
154
0
                        break;
155
0
                    }
156
0
                }
157
158
0
                if ( found == false ) {
159
0
                    std::cout << "Undefined curve: " << curOpStr << std::endl;
160
0
                    exit(1);
161
0
                }
162
0
            }
163
22
        } else if ( !parts.empty() && parts[0] == "--force-module" ) {
164
0
            if ( parts.size() != 2 ) {
165
0
                std::cout << "Expected argument after --force-module=" << std::endl;
166
0
                exit(1);
167
0
            }
168
169
0
            const auto& moduleStr = parts[1];
170
171
0
            bool found = false;
172
0
            uint64_t forceModule;
173
0
            for (size_t i = 0; i < (sizeof(repository::ModuleLUT) / sizeof(repository::ModuleLUT[0])); i++) {
174
0
                if ( boost::iequals(moduleStr, std::string(repository::ModuleLUT[i].name)) ) {
175
0
                    forceModule = repository::ModuleLUT[i].id;
176
0
                    found = true;
177
0
                    break;
178
0
                }
179
0
            }
180
181
0
            if ( found == false ) {
182
0
                std::cout << "Undefined module: " << moduleStr << std::endl;
183
0
                exit(1);
184
0
            }
185
186
0
            this->forceModule = forceModule;
187
22
        } else if ( !parts.empty() && parts[0] == "--disable-modules" ) {
188
0
            if ( parts.size() != 2 ) {
189
0
                std::cout << "Expected argument after --disable-modules=" << std::endl;
190
0
                exit(1);
191
0
            }
192
193
0
            std::vector<std::string> moduleStrings;
194
0
            boost::split(moduleStrings, parts[1], boost::is_any_of(","));
195
196
0
            for (const auto& curModStr : moduleStrings) {
197
0
                bool found = false;
198
0
                for (size_t i = 0; i < (sizeof(repository::ModuleLUT) / sizeof(repository::ModuleLUT[0])); i++) {
199
0
                    if ( boost::iequals(curModStr, std::string(repository::ModuleLUT[i].name)) ) {
200
0
                        this->disableModules.Add(repository::ModuleLUT[i].id);
201
0
                        found = true;
202
0
                        break;
203
0
                    }
204
0
                }
205
206
0
                if ( found == false ) {
207
0
                    std::cout << "Undefined module: " << curModStr << std::endl;
208
0
                    exit(1);
209
0
                }
210
0
            }
211
22
        } else if ( !parts.empty() && parts[0] == "--calcops" ) {
212
0
            if ( parts.size() != 2 ) {
213
0
                std::cout << "Expected argument after --calcops=" << std::endl;
214
0
                exit(1);
215
0
            }
216
217
0
            std::vector<std::string> calcOpStrings;
218
0
            boost::split(calcOpStrings, parts[1], boost::is_any_of(","));
219
220
0
            for (const auto& curCalcOpStr : calcOpStrings) {
221
0
                bool found = false;
222
0
                for (size_t i = 0; i < (sizeof(repository::CalcOpLUT) / sizeof(repository::CalcOpLUT[0])); i++) {
223
0
                    if ( boost::iequals(curCalcOpStr, calcOpToBase(repository::CalcOpLUT[i].name)) ) {
224
0
                        this->calcOps.Add(repository::CalcOpLUT[i].id);
225
0
                        found = true;
226
0
                        break;
227
0
                    }
228
0
                }
229
230
0
                if ( found == false ) {
231
0
                    std::cout << "Undefined calc op: " << curCalcOpStr << std::endl;
232
0
                    exit(1);
233
0
                }
234
0
            }
235
22
        } else if ( !parts.empty() && parts[0] == "--min-modules" ) {
236
0
            if ( parts.size() != 2 ) {
237
0
                std::cout << "Expected argument after --min-modules=" << std::endl;
238
0
                exit(1);
239
0
            }
240
241
0
            const auto& moduleStr = parts[1];
242
0
            const int minModules = stoi(moduleStr);
243
0
            if ( minModules < 1 ) {
244
0
                std::cout << "min-modules must be >= 1" << std::endl;
245
0
                exit(1);
246
0
            }
247
248
0
            this->minModules = static_cast<size_t>(minModules);
249
22
        } else if ( !parts.empty() && parts[0] == "--disable-tests" ) {
250
0
            if ( parts.size() != 1 ) {
251
0
                std::cout << "Expected no argument after --disable-tests=" << std::endl;
252
0
                exit(1);
253
0
            }
254
0
            this->disableTests = true;
255
22
        } else if ( !parts.empty() && parts[0] == "--no-decrypt" ) {
256
0
            if ( parts.size() != 1 ) {
257
0
                std::cout << "Expected no argument after --no-decrypt=" << std::endl;
258
0
                exit(1);
259
0
            }
260
0
            this->noDecrypt = true;
261
22
        } else if ( !parts.empty() && parts[0] == "--no-compare" ) {
262
0
            if ( parts.size() != 1 ) {
263
0
                std::cout << "Expected no argument after --no-compare=" << std::endl;
264
0
                exit(1);
265
0
            }
266
0
            this->noCompare = true;
267
22
        } else if ( !parts.empty() && parts[0] == "--dump-json" ) {
268
0
            if ( parts.size() != 2 ) {
269
0
                std::cout << "Expected argument after --dump-json=" << std::endl;
270
0
                exit(1);
271
0
            }
272
273
0
            const auto jsonPath = parts[1];
274
275
0
            FILE* fp = fopen(jsonPath.c_str(), "wb");
276
0
            if ( fp == nullptr ) {
277
0
                std::cout << "Cannot open file " << jsonPath << std::endl;
278
0
                exit(1);
279
0
            }
280
0
            this->jsonDumpFP = fp;
281
22
        } else if ( !parts.empty() && parts[0] == "--from-wycheproof" ) {
282
0
            if ( parts.size() != 2 ) {
283
0
                std::cout << "Expected argument after --from-wycheproof=" << std::endl;
284
0
                exit(1);
285
0
            }
286
287
0
            std::vector<std::string> wycheproofArgs;
288
0
            boost::split(wycheproofArgs, parts[1], boost::is_any_of(","));
289
290
0
            if ( wycheproofArgs.size() != 2 ) {
291
0
                std::cout << "Expected 2 arguments after --from-wycheproof=" << std::endl;
292
0
                exit(1);
293
0
            }
294
295
0
            Wycheproof wp(wycheproofArgs[0], wycheproofArgs[1]);
296
0
            wp.Run();
297
298
0
            exit(0);
299
#if defined(CRYPTOFUZZ_IMPORT_ECC_DIFF_FUZZER)
300
        } else if ( !parts.empty() && parts[0] == "--from-ecc-diff-fuzzer" ) {
301
            if ( parts.size() != 2 ) {
302
                std::cout << "Expected argument after --from-ecc-diff-fuzzer=" << std::endl;
303
                exit(1);
304
            }
305
306
            std::vector<std::string> args;
307
            boost::split(args, parts[1], boost::is_any_of(","));
308
309
            if ( args.size() != 2 ) {
310
                std::cout << "Expected 2 arguments after --from-ecc-diff-fuzzer=" << std::endl;
311
                exit(1);
312
            }
313
314
            ECC_Diff_Fuzzer_Importer importer(args[0], args[1]);
315
            importer.Run();
316
317
            exit(0);
318
#endif
319
#if defined(CRYPTOFUZZ_EXPORT_ECC_DIFF_FUZZER)
320
        } else if ( !parts.empty() && parts[0] == "--to-ecc-diff-fuzzer" ) {
321
            if ( parts.size() != 2 ) {
322
                std::cout << "Expected argument after --to-ecc-diff-fuzzer=" << std::endl;
323
                exit(1);
324
            }
325
326
            std::vector<std::string> args;
327
            boost::split(args, parts[1], boost::is_any_of(","));
328
329
            if ( args.size() != 2 ) {
330
                std::cout << "Expected 2 arguments after --to-ecc-diff-fuzzer=" << std::endl;
331
                exit(1);
332
            }
333
334
            ECC_Diff_Fuzzer_Exporter exporter(args[0], args[1]);
335
            exporter.Run();
336
337
            exit(0);
338
#endif
339
22
        } else if ( !parts.empty() && parts[0] == "--from-botan" ) {
340
0
            if ( parts.size() != 2 ) {
341
0
                std::cout << "Expected argument after --from-botan=" << std::endl;
342
0
                exit(1);
343
0
            }
344
345
0
            std::vector<std::string> args;
346
0
            boost::split(args, parts[1], boost::is_any_of(","));
347
348
0
            if ( args.size() != 3 ) {
349
0
                std::cout << "Expected 3 arguments after --from-botan=" << std::endl;
350
0
                exit(1);
351
0
            }
352
353
0
            const auto curveID = repository::ECC_CurveFromString(args[2]);
354
0
            CF_ASSERT(curveID != std::nullopt, "Unknown curve");
355
356
0
            Botan_Importer importer(args[0], args[1], *curveID);
357
0
            importer.Run();
358
359
0
            exit(0);
360
22
        } else if ( !parts.empty() && parts[0] == "--from-openssl-expmod" ) {
361
0
            if ( parts.size() != 2 ) {
362
0
                std::cout << "Expected argument after --from-openssl-expmod=" << std::endl;
363
0
                exit(1);
364
0
            }
365
366
0
            std::vector<std::string> args;
367
0
            boost::split(args, parts[1], boost::is_any_of(","));
368
369
0
            if ( args.size() != 2 ) {
370
0
                std::cout << "Expected 2 arguments after --from-openssl-expmod=" << std::endl;
371
0
                exit(1);
372
0
            }
373
374
0
            OpenSSL_Importer importer(args[0], args[1], OpenSSL_Importer::type::ExpMod);
375
0
            importer.Run();
376
377
0
            exit(0);
378
22
        } else if ( !parts.empty() && parts[0] == "--from-builtin-tests" ) {
379
0
            if ( parts.size() != 2 ) {
380
0
                std::cout << "Expected argument after --from-builtin-tests=" << std::endl;
381
0
                exit(1);
382
0
            }
383
384
0
            std::vector<std::string> args;
385
0
            boost::split(args, parts[1], boost::is_any_of(","));
386
387
0
            if ( args.size() != 1 ) {
388
0
                std::cout << "Expected 2 arguments after --from-builtin-tests=" << std::endl;
389
0
                exit(1);
390
0
            }
391
392
0
            Builtin_tests_importer importer(args[0]);
393
0
            importer.Run();
394
395
0
            exit(0);
396
22
        } else if ( !parts.empty() && parts[0] == "--from-bignum-fuzzer" ) {
397
0
            if ( parts.size() != 2 ) {
398
0
                std::cout << "Expected argument after --from-bignum-fuzzer=" << std::endl;
399
0
                exit(1);
400
0
            }
401
402
0
            std::vector<std::string> args;
403
0
            boost::split(args, parts[1], boost::is_any_of(","));
404
405
0
            if ( args.size() != 2 ) {
406
0
                std::cout << "Expected 2 arguments after --from-bignum-fuzzer=" << std::endl;
407
0
                exit(1);
408
0
            }
409
410
0
            Bignum_Fuzzer_Importer importer(args[0], args[1]);
411
0
            importer.Run();
412
413
0
            exit(0);
414
0
        }
415
22
    }
416
4
}
417
418
} /* namespace cryptofuzz */