Coverage Report

Created: 2024-09-11 06:39

/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
130k
bool EnabledTypes::Have(const uint64_t id) const {
19
130k
    return types.empty() || HaveExplicit(id);
20
130k
}
21
22
246k
bool EnabledTypes::HaveExplicit(const uint64_t id) const {
23
246k
    return types.find(id) != types.end();
24
246k
}
25
26
324
void EnabledTypes::Add(const uint64_t id) {
27
324
    types.insert(id);
28
324
}
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
684
bool EnabledTypes::Empty(void) const {
40
684
    return types.empty();
41
684
}
42
43
7.01k
std::string Options::calcOpToBase(const std::string calcOp) {
44
7.01k
    std::vector<std::string> calcOpParts;
45
7.01k
    boost::split(calcOpParts, calcOp, boost::is_any_of("("));
46
7.01k
    if ( calcOpParts.empty() ) {
47
0
        printf("Cannot parse calcop\n");
48
0
        abort();
49
0
    }
50
7.01k
    return calcOpParts[0];
51
7.01k
}
52
53
6
Options::Options(const int argc, char** argv, const std::vector<std::string> extraArguments) {
54
39
    for (int i = 0; i < argc; i++) {
55
33
        arguments.push_back( std::string(argv[i]) );
56
33
    }
57
58
6
    arguments.insert(arguments.end(), extraArguments.begin(), extraArguments.end());
59
60
75
    for (size_t i = 1; i < arguments.size(); i++) {
61
69
        const auto arg = arguments[i];
62
69
        std::vector<std::string> parts;
63
69
        boost::split(parts, arg, boost::is_any_of("="));
64
65
69
        if ( arg == "--debug" ) {
66
0
            debug = true;
67
69
        } else if ( !parts.empty() && parts[0] == "--operations" ) {
68
6
            if ( parts.size() != 2 ) {
69
0
                std::cout << "Expected argument after --operations=" << std::endl;
70
0
                exit(1);
71
0
            }
72
73
6
            std::vector<std::string> operationStrings;
74
6
            boost::split(operationStrings, parts[1], boost::is_any_of(","));
75
76
108
            for (const auto& curOpStr : operationStrings) {
77
108
                bool found = false;
78
8.67k
                for (size_t i = 0; i < (sizeof(repository::OperationLUT) / sizeof(repository::OperationLUT[0])); i++) {
79
8.67k
                    if ( boost::iequals(curOpStr, std::string(repository::OperationLUT[i].name)) ) {
80
108
                        this->operations.Add(repository::OperationLUT[i].id);
81
108
                        found = true;
82
108
                        break;
83
108
                    }
84
8.67k
                }
85
86
108
                if ( found == false ) {
87
0
                    std::cout << "Undefined operation: " << curOpStr << std::endl;
88
0
                    exit(1);
89
0
                }
90
108
            }
91
63
        } else if ( !parts.empty() && parts[0] == "--ciphers" ) {
92
6
            if ( parts.size() != 2 ) {
93
0
                std::cout << "Expected argument after --ciphers=" << std::endl;
94
0
                exit(1);
95
0
            }
96
97
6
            std::vector<std::string> cipherStrings;
98
6
            boost::split(cipherStrings, parts[1], boost::is_any_of(","));
99
100
12
            for (const auto& curOpStr : cipherStrings) {
101
12
                bool found = false;
102
864
                for (size_t i = 0; i < (sizeof(repository::CipherLUT) / sizeof(repository::CipherLUT[0])); i++) {
103
864
                    if ( boost::iequals(curOpStr, std::string(repository::CipherLUT[i].name)) ) {
104
12
                        this->ciphers.Add(repository::CipherLUT[i].id);
105
12
                        found = true;
106
12
                        break;
107
12
                    }
108
864
                }
109
110
12
                if ( found == false ) {
111
0
                    std::cout << "Undefined cipher: " << curOpStr << std::endl;
112
0
                    exit(1);
113
0
                }
114
12
            }
115
57
        } else if ( !parts.empty() && parts[0] == "--digests" ) {
116
6
            if ( parts.size() != 2 ) {
117
0
                std::cout << "Expected argument after --digests=" << std::endl;
118
0
                exit(1);
119
0
            }
120
121
6
            std::vector<std::string> digestStrings;
122
6
            boost::split(digestStrings, parts[1], boost::is_any_of(","));
123
124
42
            for (const auto& curOpStr : digestStrings) {
125
42
                bool found = false;
126
3.28k
                for (size_t i = 0; i < (sizeof(repository::DigestLUT) / sizeof(repository::DigestLUT[0])); i++) {
127
3.28k
                    if ( boost::iequals(curOpStr, std::string(repository::DigestLUT[i].name)) ) {
128
42
                        this->digests.Add(repository::DigestLUT[i].id);
129
42
                        found = true;
130
42
                        break;
131
42
                    }
132
3.28k
                }
133
134
42
                if ( found == false ) {
135
0
                    std::cout << "Undefined digest: " << curOpStr << std::endl;
136
0
                    exit(1);
137
0
                }
138
42
            }
139
51
        } else if ( !parts.empty() && parts[0] == "--curves" ) {
140
6
            if ( parts.size() != 2 ) {
141
0
                std::cout << "Expected argument after --curves=" << std::endl;
142
0
                exit(1);
143
0
            }
144
145
6
            std::vector<std::string> curveStrings;
146
6
            boost::split(curveStrings, parts[1], boost::is_any_of(","));
147
148
6
            for (const auto& curOpStr : curveStrings) {
149
6
                bool found = false;
150
18
                for (size_t i = 0; i < (sizeof(repository::ECC_CurveLUT) / sizeof(repository::ECC_CurveLUT[0])); i++) {
151
18
                    if ( boost::iequals(curOpStr, std::string(repository::ECC_CurveLUT[i].name)) ) {
152
6
                        this->curves.Add(repository::ECC_CurveLUT[i].id);
153
6
                        found = true;
154
6
                        break;
155
6
                    }
156
18
                }
157
158
6
                if ( found == false ) {
159
0
                    std::cout << "Undefined curve: " << curOpStr << std::endl;
160
0
                    exit(1);
161
0
                }
162
6
            }
163
45
        } 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
45
        } 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
45
        } else if ( !parts.empty() && parts[0] == "--calcops" ) {
212
6
            if ( parts.size() != 2 ) {
213
0
                std::cout << "Expected argument after --calcops=" << std::endl;
214
0
                exit(1);
215
0
            }
216
217
6
            std::vector<std::string> calcOpStrings;
218
6
            boost::split(calcOpStrings, parts[1], boost::is_any_of(","));
219
220
156
            for (const auto& curCalcOpStr : calcOpStrings) {
221
156
                bool found = false;
222
7.01k
                for (size_t i = 0; i < (sizeof(repository::CalcOpLUT) / sizeof(repository::CalcOpLUT[0])); i++) {
223
7.01k
                    if ( boost::iequals(curCalcOpStr, calcOpToBase(repository::CalcOpLUT[i].name)) ) {
224
156
                        this->calcOps.Add(repository::CalcOpLUT[i].id);
225
156
                        found = true;
226
156
                        break;
227
156
                    }
228
7.01k
                }
229
230
156
                if ( found == false ) {
231
0
                    std::cout << "Undefined calc op: " << curCalcOpStr << std::endl;
232
0
                    exit(1);
233
0
                }
234
156
            }
235
39
        } 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
39
        } 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
39
        } 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
39
        } 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
39
        } 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
39
        } 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
39
        } 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
39
        } 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
39
        } 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
39
        } 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
69
    }
416
6
}
417
418
} /* namespace cryptofuzz */