/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 */ |