From 9abf84cc82553c784705001e192678870c652077 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sun, 30 Apr 2017 14:37:16 -0400 Subject: [PATCH] Add tool for ECDSA2 SigGen and SigGenComponent tests. Change-Id: I31f6d463bd924e6766c5d8dd83da693d6d44555a Reviewed-on: https://boringssl-review.googlesource.com/15671 Reviewed-by: Adam Langley --- fipsoracle/CMakeLists.txt | 9 ++ fipsoracle/cavp_ecdsa2_siggen_test.cc | 127 ++++++++++++++++++++++++++ fipsoracle/run_cavp.go | 10 ++ 3 files changed, 146 insertions(+) create mode 100644 fipsoracle/cavp_ecdsa2_siggen_test.cc diff --git a/fipsoracle/CMakeLists.txt b/fipsoracle/CMakeLists.txt index e5352d56..11215e09 100644 --- a/fipsoracle/CMakeLists.txt +++ b/fipsoracle/CMakeLists.txt @@ -25,6 +25,14 @@ if (FIPS) $ ) + add_executable( + cavp_ecdsa2_siggen_test + + cavp_ecdsa2_siggen_test.cc + cavp_test_util.cc + $ + ) + add_executable( cavp_ecdsa2_sigver_test @@ -64,6 +72,7 @@ if (FIPS) target_link_libraries(cavp_aes_gcm_test crypto) target_link_libraries(cavp_ecdsa2_pkv_test crypto) + target_link_libraries(cavp_ecdsa2_siggen_test crypto) target_link_libraries(cavp_ecdsa2_sigver_test crypto) target_link_libraries(cavp_sha_test crypto) diff --git a/fipsoracle/cavp_ecdsa2_siggen_test.cc b/fipsoracle/cavp_ecdsa2_siggen_test.cc new file mode 100644 index 00000000..a1be9aea --- /dev/null +++ b/fipsoracle/cavp_ecdsa2_siggen_test.cc @@ -0,0 +1,127 @@ +/* Copyright (c) 2017, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +// cavp_ecdsa2_siggen_test processes NIST CAVP ECDSA2 SigGen and +// SigGenComponent test vector request files and emits the corresponding +// response. + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../crypto/internal.h" +#include "../crypto/test/file_test.h" +#include "cavp_test_util.h" + + +static bool TestECDSA2SigGenImpl(FileTest *t, bool is_component) { + int nid = GetECGroupNIDFromInstruction(t); + const EVP_MD *md = GetDigestFromInstruction(t); + if (nid == NID_undef || md == nullptr) { + return false; + } + bssl::UniquePtr qx(BN_new()), qy(BN_new()); + bssl::UniquePtr key(EC_KEY_new_by_curve_name(nid)); + std::vector msg; + if (!qx || !qy || !key || + !EC_KEY_generate_key(key.get()) || + !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()), + EC_KEY_get0_public_key(key.get()), + qx.get(), qy.get(), nullptr) || + !t->GetBytes(&msg, "Msg")) { + return false; + } + + uint8_t digest[EVP_MAX_MD_SIZE]; + unsigned digest_len; + if (is_component) { + if (msg.size() != EVP_MD_size(md)) { + t->PrintLine("Bad input length."); + return false; + } + digest_len = EVP_MD_size(md); + OPENSSL_memcpy(digest, msg.data(), msg.size()); + } else if (!EVP_Digest(msg.data(), msg.size(), digest, &digest_len, md, + nullptr)) { + return false; + } + + bssl::UniquePtr sig(ECDSA_do_sign(digest, digest_len, key.get())); + if (!sig) { + return false; + } + + size_t degree_len = + (EC_GROUP_get_degree(EC_KEY_get0_group(key.get())) + 7) / 8; + size_t order_len = + BN_num_bytes(EC_GROUP_get0_order(EC_KEY_get0_group(key.get()))); + std::vector qx_bytes(degree_len), qy_bytes(degree_len); + std::vector r_bytes(order_len), s_bytes(order_len); + if (!BN_bn2bin_padded(qx_bytes.data(), qx_bytes.size(), qx.get()) || + !BN_bn2bin_padded(qy_bytes.data(), qy_bytes.size(), qy.get()) || + !BN_bn2bin_padded(r_bytes.data(), r_bytes.size(), sig->r) || + !BN_bn2bin_padded(s_bytes.data(), s_bytes.size(), sig->s)) { + return false; + } + + printf("%sQx = %s\r\nQy = %s\r\nR = %s\r\nS = %s\r\n\r\n", + t->CurrentTestToString().c_str(), + EncodeHex(qx_bytes.data(), qx_bytes.size()).c_str(), + EncodeHex(qy_bytes.data(), qy_bytes.size()).c_str(), + EncodeHex(r_bytes.data(), r_bytes.size()).c_str(), + EncodeHex(s_bytes.data(), s_bytes.size()).c_str()); + return true; +} + +static bool TestECDSA2SigGen(FileTest *t, void *arg) { + return TestECDSA2SigGenImpl(t, false); +} + +static bool TestECDSA2SigGenComponent(FileTest *t, void *arg) { + return TestECDSA2SigGenImpl(t, true); +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (argc != 3) { + fprintf(stderr, "usage: %s (SigGen|SigGenComponent) \n", + argv[0]); + return 1; + } + + static bool (*test_func)(FileTest *, void *); + if (strcmp(argv[1], "SigGen") == 0) { + test_func = TestECDSA2SigGen; + } else if (strcmp(argv[1], "SigGenComponent") == 0) { + test_func = TestECDSA2SigGenComponent; + } else { + fprintf(stderr, "Unknown test type: %s\n", argv[1]); + 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]); +} diff --git a/fipsoracle/run_cavp.go b/fipsoracle/run_cavp.go index 2db1b0cb..84cdef07 100644 --- a/fipsoracle/run_cavp.go +++ b/fipsoracle/run_cavp.go @@ -105,6 +105,15 @@ var ecdsa2PKVTests = testSuite{ []test{{"PKV", nil, false}}, } +var ecdsa2SigGenTests = testSuite{ + "ECDSA2", + "cavp_ecdsa2_siggen_test", + []test{ + {"SigGen", []string{"SigGen"}, true}, + {"SigGenComponent", []string{"SigGenComponent"}, true}, + }, +} + var ecdsa2SigVerTests = testSuite{ "ECDSA2", "cavp_ecdsa2_sigver_test", @@ -151,6 +160,7 @@ var allTestSuites = []*testSuite{ &aesTests, &ctrDRBGTests, &ecdsa2PKVTests, + &ecdsa2SigGenTests, &ecdsa2SigVerTests, &shaTests, &shaMonteTests,