#include #include "../lib/helper.h" #include "../lib/io.h" #include "../lib/md2.h" // Returns true when val is approx. equal to exp. static bool runTest(struct configuration* c, const char* message, const char* expectedHash) { uint8_t out[16]; double duration = 0.0; if (c->doBenchmark) { duration = run_benchmark(c->benchmarkingCycles, md2_hash, strlen(message), (uint8_t*)message, out); } else { md2_hash(strlen(message), (uint8_t*)message, out); } char hash[32]; md2_encode_hash(out, hash); bool ok = !strncmp(hash, expectedHash, 32); printf("%s: md2(%s) %s == %s", "not ok" + (4 * ok), message, hash, expectedHash); if (c->doBenchmark) { printf(" took: %f", duration); } printf("\n"); return ok; } unsigned runTests(struct configuration* c) { unsigned failed = 0; // src: https://datatracker.ietf.org/doc/html/rfc1319#appendix-A.5 failed += !runTest(c, "", "8350e5a3e24c153df2275c9f80692773"); failed += !runTest(c, "a", "32ec01ec4a6dac72c0ab96fb34c0b5d1"); failed += !runTest(c, "abc", "da853b0d3f88d99b30283a69e6ded6bb"); failed += !runTest(c, "message digest", "ab4f496bfb2a530b219ff33031fe06b0"); failed += !runTest(c, "jebdjcslfhwfdig", "e1b69085c6f6e36cb8fe8d98ed3f2c35"); failed += !runTest(c, "0123456789abcde", "d95629645108a20ab4d70e8545e0723b"); failed += !runTest(c, "0123456789abcdef", "12c8dfa285f14e1af8c5254e7092d0d3"); failed += !runTest(c, "0123456789abcdefg", "e4d0efded5ef7b6843a5ba47e1171347"); failed += !runTest(c, "abcdefghijklmnopqrstuvwxyz", "4e8ddff3650292ab5a4108c3aa47940b"); failed += !runTest( c, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "da33def2a42df13975352846c30338cd"); failed += !runTest( c, "123456789012345678901234567890123456789012345678901234567890123456789012" "34567890", "d5976f79d83d3a0dc9806c3c66f3efd8"); if (failed) printf("%u tests FAILED\n", failed); else printf("All tests PASSED\n"); return failed; } bool calculate_hash(struct configuration c, char* hash) { size_t len; uint8_t* data; if (c.implementationToUse != 2) { data = read_file(c.filename, &len); } else { data = (uint8_t*)c.filename; len = 0; } if (data == NULL) { printf("Error reading file %s!", c.filename); return false; } uint8_t out[16]; if (c.doBenchmark) { double duration = run_benchmark(c.benchmarkingCycles, md2_hash, len, data, out); printf("Running %d cycles took %f seconds\n", c.benchmarkingCycles, duration); } else { md2_hash(len, data, out); } md2_encode_hash(out, hash); if (c.implementationToUse != 2) free(data); return true; } int main(int argc, char** argv) { struct configuration c; enum argumentParseResult result = parseArguments(argc, argv, &c); switch (result) { case RESULT_EXIT_SUCCESS: return EXIT_SUCCESS; case RESULT_EXIT_FAILURE: return EXIT_FAILURE; default: break; } if (!md2_choose_implementation(c.implementationToUse)) { fprintf(stderr, "%s: invalid argument, implementation '%d' does not exist!\n", argv[0], c.implementationToUse); return EXIT_FAILURE; } printf( "Using implementation: %d, doing benchmark: %d, " "benchmark cycles: %d\n", c.implementationToUse, c.doBenchmark, c.benchmarkingCycles); if (c.runTests && c.implementationToUse == 2) { fprintf(stderr, "Cannot run tests on implementation 2!"); return EXIT_FAILURE; } if (c.runTests) { printf("Running tests...\n\n"); return runTests(&c); } printf("Hashing file %s...\n\n", c.filename); char hash[32]; calculate_hash(c, hash); printf("Hash: %s\n", hash); return 0; }