1 /* Copyright (c) 2017, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15 // cavp_ecdsa2_siggen_test processes NIST CAVP ECDSA2 SigGen and 16 // SigGenComponent test vector request files and emits the corresponding 17 // response. 18 19 #include <vector> 20 21 #include <openssl/bn.h> 22 #include <openssl/crypto.h> 23 #include <openssl/digest.h> 24 #include <openssl/ec_key.h> 25 #include <openssl/ecdsa.h> 26 #include <openssl/err.h> 27 #include <openssl/nid.h> 28 29 #include "../crypto/internal.h" 30 #include "../crypto/test/file_test.h" 31 #include "cavp_test_util.h" 32 33 34 static bool TestECDSA2SigGenImpl(FileTest *t, bool is_component) { 35 int nid = GetECGroupNIDFromInstruction(t); 36 const EVP_MD *md = GetDigestFromInstruction(t); 37 if (nid == NID_undef || md == nullptr) { 38 return false; 39 } 40 bssl::UniquePtr<BIGNUM> qx(BN_new()), qy(BN_new()); 41 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid)); 42 std::vector<uint8_t> msg; 43 if (!qx || !qy || !key || 44 !EC_KEY_generate_key_fips(key.get()) || 45 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()), 46 EC_KEY_get0_public_key(key.get()), 47 qx.get(), qy.get(), nullptr) || 48 !t->GetBytes(&msg, "Msg")) { 49 return false; 50 } 51 52 uint8_t digest[EVP_MAX_MD_SIZE]; 53 unsigned digest_len; 54 if (is_component) { 55 if (msg.size() != EVP_MD_size(md)) { 56 t->PrintLine("Bad input length."); 57 return false; 58 } 59 digest_len = EVP_MD_size(md); 60 OPENSSL_memcpy(digest, msg.data(), msg.size()); 61 } else if (!EVP_Digest(msg.data(), msg.size(), digest, &digest_len, md, 62 nullptr)) { 63 return false; 64 } 65 66 bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, key.get())); 67 if (!sig) { 68 return false; 69 } 70 71 size_t degree_len = 72 (EC_GROUP_get_degree(EC_KEY_get0_group(key.get())) + 7) / 8; 73 size_t order_len = 74 BN_num_bytes(EC_GROUP_get0_order(EC_KEY_get0_group(key.get()))); 75 std::vector<uint8_t> qx_bytes(degree_len), qy_bytes(degree_len); 76 std::vector<uint8_t> r_bytes(order_len), s_bytes(order_len); 77 if (!BN_bn2bin_padded(qx_bytes.data(), qx_bytes.size(), qx.get()) || 78 !BN_bn2bin_padded(qy_bytes.data(), qy_bytes.size(), qy.get()) || 79 !BN_bn2bin_padded(r_bytes.data(), r_bytes.size(), sig->r) || 80 !BN_bn2bin_padded(s_bytes.data(), s_bytes.size(), sig->s)) { 81 return false; 82 } 83 84 printf("%sQx = %s\r\nQy = %s\r\nR = %s\r\nS = %s\r\n\r\n", 85 t->CurrentTestToString().c_str(), 86 EncodeHex(qx_bytes.data(), qx_bytes.size()).c_str(), 87 EncodeHex(qy_bytes.data(), qy_bytes.size()).c_str(), 88 EncodeHex(r_bytes.data(), r_bytes.size()).c_str(), 89 EncodeHex(s_bytes.data(), s_bytes.size()).c_str()); 90 return true; 91 } 92 93 static bool TestECDSA2SigGen(FileTest *t, void *arg) { 94 return TestECDSA2SigGenImpl(t, false); 95 } 96 97 static bool TestECDSA2SigGenComponent(FileTest *t, void *arg) { 98 return TestECDSA2SigGenImpl(t, true); 99 } 100 101 int cavp_ecdsa2_siggen_test_main(int argc, char **argv) { 102 if (argc != 3) { 103 fprintf(stderr, "usage: %s (SigGen|SigGenComponent) <test file>\n", 104 argv[0]); 105 return 1; 106 } 107 108 static bool (*test_func)(FileTest *, void *); 109 if (strcmp(argv[1], "SigGen") == 0) { 110 test_func = TestECDSA2SigGen; 111 } else if (strcmp(argv[1], "SigGenComponent") == 0) { 112 test_func = TestECDSA2SigGenComponent; 113 } else { 114 fprintf(stderr, "Unknown test type: %s\n", argv[1]); 115 return 1; 116 } 117 118 FileTest::Options opts; 119 opts.path = argv[2]; 120 opts.callback = test_func; 121 opts.silent = true; 122 opts.comment_callback = EchoComment; 123 return FileTestMain(opts); 124 } 125