Coverage Report

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