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