diff --git a/crypto/test/file_test.cc b/crypto/test/file_test.cc index 87a6b96b..5bc5fb46 100644 --- a/crypto/test/file_test.cc +++ b/crypto/test/file_test.cc @@ -30,8 +30,9 @@ #include "../internal.h" -FileTest::FileTest(std::unique_ptr reader) - : reader_(std::move(reader)) {} +FileTest::FileTest(std::unique_ptr reader, + std::function comment_callback) + : reader_(std::move(reader)), comment_callback_(comment_callback) {} FileTest::~FileTest() {} @@ -121,12 +122,15 @@ FileTest::ReadResult FileTest::ReadNext() { // Delimit instruction block from test with a blank line. current_test_ += "\r\n"; } - } else if (buf[0] == '#' || - strcmp("[B.4.2 Key Pair Generation by Testing Candidates]\r\n", + } else if (buf[0] == '#') { + if (comment_callback_) { + comment_callback_(buf.get()); + } + // Otherwise ignore comments. + } else if (strcmp("[B.4.2 Key Pair Generation by Testing Candidates]\r\n", buf.get()) == 0) { - // Ignore comments. The above instruction-like line is treated as a - // comment because the FIPS lab's request files are hopelessly - // inconsistent. + // The above instruction-like line is ignored because the FIPS lab's + // request files are hopelessly inconsistent. } else if (buf[0] == '[') { // Inside an instruction block. is_at_new_instruction_block_ = true; if (start_line_ != 0) { @@ -399,14 +403,26 @@ class FileLineReader : public FileTest::LineReader { FileLineReader &operator=(const FileLineReader &) = delete; }; -int FileTestMainSilent(FileTestFunc run_test, void *arg, const char *path) { - std::unique_ptr reader(new FileLineReader(path)); +int FileTestMain(FileTestFunc run_test, void *arg, const char *path) { + FileTest::Options opts; + opts.callback = run_test; + opts.arg = arg; + opts.path = path; + + return FileTestMain(opts); +} + +int FileTestMain(const FileTest::Options &opts) { + std::unique_ptr reader( + new FileLineReader(opts.path)); if (!reader->is_open()) { - fprintf(stderr, "Could not open file %s: %s.\n", path, strerror(errno)); + fprintf(stderr, "Could not open file %s: %s.\n", opts.path, + strerror(errno)); return 1; } - FileTest t(std::move(reader)); + FileTest t(std::move(reader), opts.comment_callback); + bool failed = false; while (true) { FileTest::ReadResult ret = t.ReadNext(); @@ -416,7 +432,7 @@ int FileTestMainSilent(FileTestFunc run_test, void *arg, const char *path) { break; } - bool result = run_test(&t, arg); + bool result = opts.callback(&t, opts.arg); if (t.HasAttribute("Error")) { if (result) { t.PrintLine("Operation unexpectedly succeeded."); @@ -443,13 +459,9 @@ int FileTestMainSilent(FileTestFunc run_test, void *arg, const char *path) { } } - return failed ? 1 : 0; -} - -int FileTestMain(FileTestFunc run_test, void *arg, const char *path) { - int result = FileTestMainSilent(run_test, arg, path); - if (!result) { + if (!opts.silent && !failed) { printf("PASS\n"); } - return result; + + return failed ? 1 : 0; } diff --git a/crypto/test/file_test.h b/crypto/test/file_test.h index 70629f36..8c476c47 100644 --- a/crypto/test/file_test.h +++ b/crypto/test/file_test.h @@ -84,6 +84,8 @@ OPENSSL_MSVC_PRAGMA(warning(pop)) // consumed. When a test completes, if any attributes or insturctions haven't // been processed, the framework reports an error. +class FileTest; +typedef bool (*FileTestFunc)(FileTest *t, void *arg); class FileTest { public: @@ -99,7 +101,23 @@ class FileTest { virtual ReadResult ReadLine(char *out, size_t len) = 0; }; - explicit FileTest(std::unique_ptr reader); + struct Options { + // path is the path to the input file. + const char *path = nullptr; + // callback is called for each test. It should get the parameters from this + // object and signal any errors by returning false. + FileTestFunc callback = nullptr; + // arg is an opaque pointer that is passed to |callback|. + void *arg = nullptr; + // silent suppressed the "PASS" string that is otherwise printed after + // successful runs. + bool silent = false; + // comment_callback is called after each comment in the input is parsed. + std::function comment_callback; + }; + + explicit FileTest(std::unique_ptr reader, + std::function comment_callback); ~FileTest(); // ReadNext reads the next test from the file. It returns |kReadSuccess| if @@ -197,12 +215,14 @@ class FileTest { bool is_at_new_instruction_block_ = false; + // comment_callback_, if set, is a callback function that is called with the + // contents of each comment as they are parsed. + std::function comment_callback_; + FileTest(const FileTest &) = delete; FileTest &operator=(const FileTest &) = delete; }; -typedef bool (*FileTestFunc)(FileTest *t, void *arg); - // FileTestMain runs a file-based test out of |path| and returns an exit code // suitable to return out of |main|. |run_test| should return true on pass and // false on failure. FileTestMain also implements common handling of the 'Error' @@ -216,9 +236,8 @@ typedef bool (*FileTestFunc)(FileTest *t, void *arg); // subsequent tests. int FileTestMain(FileTestFunc run_test, void *arg, const char *path); -// FileTestMainSilent behaves like FileTestMain but does not print a final -// FAIL/PASS message to stdout. -int FileTestMainSilent(FileTestFunc run_test, void *arg, const char *path); +// FileTestMain accepts a larger number of options via a struct. +int FileTestMain(const FileTest::Options &opts); // FileTestGTest behaves like FileTestMain, but for GTest. |path| must be the // name of a test file embedded in the test binary. diff --git a/crypto/test/file_test_gtest.cc b/crypto/test/file_test_gtest.cc index 90d12bf2..9d3c3e42 100644 --- a/crypto/test/file_test_gtest.cc +++ b/crypto/test/file_test_gtest.cc @@ -66,7 +66,7 @@ class StringLineReader : public FileTest::LineReader { void FileTestGTest(const char *path, std::function run_test) { std::unique_ptr reader( new StringLineReader(GetTestData(path))); - FileTest t(std::move(reader)); + FileTest t(std::move(reader), nullptr); while (true) { switch (t.ReadNext()) { diff --git a/fipstools/cavp_aes_gcm_test.cc b/fipstools/cavp_aes_gcm_test.cc index 21d03bfb..7278ceaf 100644 --- a/fipstools/cavp_aes_gcm_test.cc +++ b/fipstools/cavp_aes_gcm_test.cc @@ -153,11 +153,11 @@ int cavp_aes_gcm_test_main(int argc, char **argv) { TestCtx ctx = {aead}; - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(test_fn, &ctx, argv[3]); + FileTest::Options opts; + opts.path = argv[3]; + opts.callback = test_fn; + opts.arg = &ctx; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_aes_test.cc b/fipstools/cavp_aes_test.cc index ad1d50c1..6c0cf3cf 100644 --- a/fipstools/cavp_aes_test.cc +++ b/fipstools/cavp_aes_test.cc @@ -217,11 +217,11 @@ int cavp_aes_test_main(int argc, char **argv) { TestCtx ctx = {cipher, has_iv, test_mode}; - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestCipher, &ctx, argv[3]); + FileTest::Options opts; + opts.path = argv[3]; + opts.callback = TestCipher; + opts.arg = &ctx; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_ctr_drbg_test.cc b/fipstools/cavp_ctr_drbg_test.cc index b18c437e..30a1a156 100644 --- a/fipstools/cavp_ctr_drbg_test.cc +++ b/fipstools/cavp_ctr_drbg_test.cc @@ -97,11 +97,10 @@ int cavp_ctr_drbg_test_main(int argc, char **argv) { return usage(argv[0]); } - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n# CTR_DRBG options: AES-256 no df\r\n\r\n"); - - return FileTestMainSilent(TestCTRDRBG, nullptr, argv[1]); + FileTest::Options opts; + opts.path = argv[1]; + opts.callback = TestCTRDRBG; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_ecdsa2_keypair_test.cc b/fipstools/cavp_ecdsa2_keypair_test.cc index 5cb0f5bf..d1fceade 100644 --- a/fipstools/cavp_ecdsa2_keypair_test.cc +++ b/fipstools/cavp_ecdsa2_keypair_test.cc @@ -84,11 +84,10 @@ int cavp_ecdsa2_keypair_test_main(int argc, char **argv) { return 1; } - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestECDSA2KeyPair, nullptr, argv[1]); + FileTest::Options opts; + opts.path = argv[1]; + opts.callback = TestECDSA2KeyPair; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_ecdsa2_pkv_test.cc b/fipstools/cavp_ecdsa2_pkv_test.cc index a5c09e73..d823e7af 100644 --- a/fipstools/cavp_ecdsa2_pkv_test.cc +++ b/fipstools/cavp_ecdsa2_pkv_test.cc @@ -57,11 +57,10 @@ int cavp_ecdsa2_pkv_test_main(int argc, char **argv) { return 1; } - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestECDSA2PKV, nullptr, argv[1]); + FileTest::Options opts; + opts.path = argv[1]; + opts.callback = TestECDSA2PKV; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_ecdsa2_siggen_test.cc b/fipstools/cavp_ecdsa2_siggen_test.cc index 2d6c79e8..60c1c87d 100644 --- a/fipstools/cavp_ecdsa2_siggen_test.cc +++ b/fipstools/cavp_ecdsa2_siggen_test.cc @@ -115,11 +115,10 @@ int cavp_ecdsa2_siggen_test_main(int argc, char **argv) { return 1; } - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(test_func, nullptr, argv[2]); + FileTest::Options opts; + opts.path = argv[2]; + opts.callback = test_func; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_ecdsa2_sigver_test.cc b/fipstools/cavp_ecdsa2_sigver_test.cc index ea7649ef..f3fd4b1e 100644 --- a/fipstools/cavp_ecdsa2_sigver_test.cc +++ b/fipstools/cavp_ecdsa2_sigver_test.cc @@ -75,11 +75,10 @@ int cavp_ecdsa2_sigver_test_main(int argc, char **argv) { return 1; } - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestECDSA2SigVer, nullptr, argv[1]); + FileTest::Options opts; + opts.path = argv[1]; + opts.callback = TestECDSA2SigVer; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_hmac_test.cc b/fipstools/cavp_hmac_test.cc index 9c4f221d..59c7e103 100644 --- a/fipstools/cavp_hmac_test.cc +++ b/fipstools/cavp_hmac_test.cc @@ -94,11 +94,10 @@ int cavp_hmac_test_main(int argc, char **argv) { return usage(argv[0]); } - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestHMAC, nullptr, argv[1]); + FileTest::Options opts; + opts.path = argv[1]; + opts.callback = TestHMAC; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_keywrap_test.cc b/fipstools/cavp_keywrap_test.cc index 19f8ba0f..c7270df3 100644 --- a/fipstools/cavp_keywrap_test.cc +++ b/fipstools/cavp_keywrap_test.cc @@ -115,11 +115,11 @@ int cavp_keywrap_test_main(int argc, char **argv) { TestCtx ctx = {encrypt}; - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestCipher, &ctx, argv[3]); + FileTest::Options opts; + opts.path = argv[3]; + opts.callback = TestCipher; + opts.arg = &ctx; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_rsa2_keygen_test.cc b/fipstools/cavp_rsa2_keygen_test.cc index a96404db..fa8d658f 100644 --- a/fipstools/cavp_rsa2_keygen_test.cc +++ b/fipstools/cavp_rsa2_keygen_test.cc @@ -85,11 +85,10 @@ int cavp_rsa2_keygen_test_main(int argc, char **argv) { return 1; } - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestRSA2KeyGen, nullptr, argv[1]); + FileTest::Options opts; + opts.path = argv[1]; + opts.callback = TestRSA2KeyGen; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_rsa2_siggen_test.cc b/fipstools/cavp_rsa2_siggen_test.cc index ad32c68b..063b89d8 100644 --- a/fipstools/cavp_rsa2_siggen_test.cc +++ b/fipstools/cavp_rsa2_siggen_test.cc @@ -119,11 +119,11 @@ int cavp_rsa2_siggen_test_main(int argc, char **argv) { return 1; } - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestRSA2SigGen, &ctx, argv[2]); + FileTest::Options opts; + opts.path = argv[2]; + opts.callback = TestRSA2SigGen; + opts.arg = &ctx; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_rsa2_sigver_test.cc b/fipstools/cavp_rsa2_sigver_test.cc index bf1ea2d7..cbcfc1fc 100644 --- a/fipstools/cavp_rsa2_sigver_test.cc +++ b/fipstools/cavp_rsa2_sigver_test.cc @@ -115,11 +115,11 @@ int cavp_rsa2_sigver_test_main(int argc, char **argv) { return 1; } - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestRSA2SigVer, &ctx, argv[2]); + FileTest::Options opts; + opts.path = argv[2]; + opts.callback = TestRSA2SigVer; + opts.arg = &ctx; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_sha_monte_test.cc b/fipstools/cavp_sha_monte_test.cc index 1609c981..d6f2fb09 100644 --- a/fipstools/cavp_sha_monte_test.cc +++ b/fipstools/cavp_sha_monte_test.cc @@ -92,11 +92,11 @@ int cavp_sha_monte_test_main(int argc, char **argv) { TestCtx ctx = {std::string(argv[1])}; - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestSHAMonte, &ctx, argv[2]); + FileTest::Options opts; + opts.path = argv[2]; + opts.callback = TestSHAMonte; + opts.arg = &ctx; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_sha_test.cc b/fipstools/cavp_sha_test.cc index 131866ab..aae25c1c 100644 --- a/fipstools/cavp_sha_test.cc +++ b/fipstools/cavp_sha_test.cc @@ -86,11 +86,11 @@ int cavp_sha_test_main(int argc, char **argv) { TestCtx ctx = {std::string(argv[1])}; - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - - return FileTestMainSilent(TestSHA, &ctx, argv[2]); + FileTest::Options opts; + opts.path = argv[2]; + opts.callback = TestSHA; + opts.arg = &ctx; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_tdes_test.cc b/fipstools/cavp_tdes_test.cc index ad608de5..d1c10ff9 100644 --- a/fipstools/cavp_tdes_test.cc +++ b/fipstools/cavp_tdes_test.cc @@ -331,12 +331,12 @@ int cavp_tdes_test_main(int argc, char **argv) { bool has_iv = cipher_name != "des-ede" && cipher_name != "des-ede3"; TestCtx ctx = {cipher, has_iv, test_mode}; - printf("# Generated by"); - for (int i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\r\n\r\n"); - FileTestFunc test_fn = test_mode == TestCtx::kKAT ? &TestKAT : &TestMCT; - return FileTestMainSilent(test_fn, &ctx, argv[3]); + FileTest::Options opts; + opts.path = argv[3]; + opts.callback = test_fn; + opts.arg = &ctx; + opts.silent = true; + opts.comment_callback = EchoComment; + return FileTestMain(opts); } diff --git a/fipstools/cavp_test_util.cc b/fipstools/cavp_test_util.cc index 98be3fa9..87a3b921 100644 --- a/fipstools/cavp_test_util.cc +++ b/fipstools/cavp_test_util.cc @@ -225,3 +225,7 @@ const EVP_MD *GetDigestFromInstruction(FileTest *t) { t->PrintLine("No supported digest function specified."); return nullptr; } + +void EchoComment(const std::string& comment) { + fwrite(comment.c_str(), comment.size(), 1, stdout); +} diff --git a/fipstools/cavp_test_util.h b/fipstools/cavp_test_util.h index 54fd57d7..0cbd9a77 100644 --- a/fipstools/cavp_test_util.h +++ b/fipstools/cavp_test_util.h @@ -54,6 +54,8 @@ int GetECGroupNIDFromInstruction(FileTest *t, const char **out_str = nullptr); const EVP_MD *GetDigestFromInstruction(FileTest *t); +void EchoComment(const std::string& comment); + int cavp_aes_gcm_test_main(int argc, char **argv); int cavp_aes_test_main(int argc, char **argv); int cavp_ctr_drbg_test_main(int argc, char **argv);