1 /* Copyright (c) 2018, 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_kas_test processes NIST CAVP ECC KAS test vector request files and 16 // emits the corresponding response. 17 18 #include <vector> 19 20 #include <openssl/bn.h> 21 #include <openssl/crypto.h> 22 #include <openssl/digest.h> 23 #include <openssl/ecdh.h> 24 #include <openssl/ecdsa.h> 25 #include <openssl/ec_key.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 TestKAS(FileTest *t, void *arg) { 35 const bool validate = *reinterpret_cast<bool *>(arg); 36 37 int nid = NID_undef; 38 const EVP_MD *md = nullptr; 39 40 if (t->HasInstruction("EB - SHA224")) { 41 nid = NID_secp224r1; 42 md = EVP_sha224(); 43 } else if (t->HasInstruction("EC - SHA256")) { 44 nid = NID_X9_62_prime256v1; 45 md = EVP_sha256(); 46 } else if (t->HasInstruction("ED - SHA384")) { 47 nid = NID_secp384r1; 48 md = EVP_sha384(); 49 } else if (t->HasInstruction("EE - SHA512")) { 50 nid = NID_secp521r1; 51 md = EVP_sha512(); 52 } else { 53 return false; 54 } 55 56 if (!t->HasAttribute("COUNT")) { 57 return false; 58 } 59 60 bssl::UniquePtr<BIGNUM> their_x(GetBIGNUM(t, "QeCAVSx")); 61 bssl::UniquePtr<BIGNUM> their_y(GetBIGNUM(t, "QeCAVSy")); 62 bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(nid)); 63 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 64 if (!their_x || !their_y || !ec_key || !ctx) { 65 return false; 66 } 67 68 const EC_GROUP *const group = EC_KEY_get0_group(ec_key.get()); 69 bssl::UniquePtr<EC_POINT> their_point(EC_POINT_new(group)); 70 if (!their_point || 71 !EC_POINT_set_affine_coordinates_GFp( 72 group, their_point.get(), their_x.get(), their_y.get(), ctx.get())) { 73 return false; 74 } 75 76 if (validate) { 77 bssl::UniquePtr<BIGNUM> our_k(GetBIGNUM(t, "deIUT")); 78 if (!our_k || 79 !EC_KEY_set_private_key(ec_key.get(), our_k.get()) || 80 // These attributes are ignored. 81 !t->HasAttribute("QeIUTx") || 82 !t->HasAttribute("QeIUTy")) { 83 return false; 84 } 85 } else if (!EC_KEY_generate_key(ec_key.get())) { 86 return false; 87 } 88 89 constexpr size_t kMaxCurveFieldBits = 521; 90 uint8_t shared_bytes[(kMaxCurveFieldBits + 7)/8]; 91 const int shared_bytes_len = 92 ECDH_compute_key(shared_bytes, sizeof(shared_bytes), their_point.get(), 93 ec_key.get(), nullptr); 94 95 uint8_t digest[EVP_MAX_MD_SIZE]; 96 unsigned digest_len; 97 if (shared_bytes_len < 0 || 98 !EVP_Digest(shared_bytes, shared_bytes_len, digest, &digest_len, md, 99 nullptr)) { 100 return false; 101 } 102 103 if (validate) { 104 std::vector<uint8_t> expected_shared_bytes; 105 if (!t->GetBytes(&expected_shared_bytes, "CAVSHashZZ")) { 106 return false; 107 } 108 const bool ok = 109 digest_len == expected_shared_bytes.size() && 110 OPENSSL_memcmp(digest, expected_shared_bytes.data(), digest_len) == 0; 111 112 printf("%sIUTHashZZ = %s\r\nResult = %c\r\n\r\n\r\n", 113 t->CurrentTestToString().c_str(), 114 EncodeHex(digest, digest_len).c_str(), ok ? 'P' : 'F'); 115 } else { 116 const EC_POINT *pub = EC_KEY_get0_public_key(ec_key.get()); 117 bssl::UniquePtr<BIGNUM> x(BN_new()); 118 bssl::UniquePtr<BIGNUM> y(BN_new()); 119 if (!x || !y || 120 !EC_POINT_get_affine_coordinates_GFp(group, pub, x.get(), y.get(), 121 ctx.get())) { 122 return false; 123 } 124 bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get())); 125 bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get())); 126 127 printf("%sQeIUTx = %s\r\nQeIUTy = %s\r\nHashZZ = %s\r\n", 128 t->CurrentTestToString().c_str(), x_hex.get(), y_hex.get(), 129 EncodeHex(digest, digest_len).c_str()); 130 } 131 132 return true; 133 } 134 135 int cavp_kas_test_main(int argc, char **argv) { 136 if (argc != 3) { 137 fprintf(stderr, "usage: %s (validity|function) <test file>\n", 138 argv[0]); 139 return 1; 140 } 141 142 bool validity; 143 if (strcmp(argv[1], "validity") == 0) { 144 validity = true; 145 } else if (strcmp(argv[1], "function") == 0) { 146 validity = false; 147 } else { 148 fprintf(stderr, "Unknown test type: %s\n", argv[1]); 149 return 1; 150 } 151 152 FileTest::Options opts; 153 opts.path = argv[2]; 154 opts.arg = &validity; 155 opts.callback = TestKAS; 156 opts.silent = true; 157 opts.comment_callback = EchoComment; 158 opts.is_kas_test = true; 159 return FileTestMain(opts); 160 } 161