Echo CAVP comments in the output.

Comments in CAVP are semantically important and we need to copy them
from the input to the output.

Change-Id: Ib798c4ad79de924487d0c4a0f8fc16b757e766d8
Reviewed-on: https://boringssl-review.googlesource.com/16725
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
Adam Langley 2017-05-30 15:37:27 -07:00 committed by CQ bot account: commit-bot@chromium.org
parent 563924bebd
commit d79bc9d397
20 changed files with 161 additions and 131 deletions

View File

@ -30,8 +30,9 @@
#include "../internal.h"
FileTest::FileTest(std::unique_ptr<FileTest::LineReader> reader)
: reader_(std::move(reader)) {}
FileTest::FileTest(std::unique_ptr<FileTest::LineReader> reader,
std::function<void(const std::string &)> 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<FileLineReader> 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<FileLineReader> 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;
}

View File

@ -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<LineReader> 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<void(const std::string&)> comment_callback;
};
explicit FileTest(std::unique_ptr<LineReader> reader,
std::function<void(const std::string &)> 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<void(const std::string&)> 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.

View File

@ -66,7 +66,7 @@ class StringLineReader : public FileTest::LineReader {
void FileTestGTest(const char *path, std::function<void(FileTest *)> run_test) {
std::unique_ptr<StringLineReader> reader(
new StringLineReader(GetTestData(path)));
FileTest t(std::move(reader));
FileTest t(std::move(reader), nullptr);
while (true) {
switch (t.ReadNext()) {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);