1f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin/* Copyright (c) 2016, Google Inc. 2f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * 3f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * Permission to use, copy, modify, and/or distribute this software for any 4f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * purpose with or without fee is hereby granted, provided that the above 5f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * copyright notice and this permission notice appear in all copies. 6f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * 7f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 15f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <stdio.h> 16f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 1729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan#include <utility> 18f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <vector> 19f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 208ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan#include <gtest/gtest.h> 218ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan 22f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/bn.h> 23f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/crypto.h> 24f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/ec.h> 25f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/ec_key.h> 26f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/ecdh.h> 2729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan#include <openssl/err.h> 28f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/nid.h> 29f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 30f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include "../test/file_test.h" 318ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan#include "../test/test_util.h" 32f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 33f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 34f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjaminstatic bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) { 35f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin std::string curve_name; 36f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (!t->GetAttribute(&curve_name, key)) { 37f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return nullptr; 38f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 39f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 40f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (curve_name == "P-224") { 41f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp224r1)); 42f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 43f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (curve_name == "P-256") { 44f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name( 45f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin NID_X9_62_prime256v1)); 46f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 47f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (curve_name == "P-384") { 48f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp384r1)); 49f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 50f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (curve_name == "P-521") { 51f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp521r1)); 52f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 53f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 54f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin t->PrintLine("Unknown curve '%s'", curve_name.c_str()); 55f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return nullptr; 56f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin} 57f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 58f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjaminstatic bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) { 59f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin std::vector<uint8_t> bytes; 60f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (!t->GetBytes(&bytes, key)) { 61f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return nullptr; 62f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 63f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 64f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return bssl::UniquePtr<BIGNUM>(BN_bin2bn(bytes.data(), bytes.size(), nullptr)); 65f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin} 66f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 678ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert SloanTEST(ECDHTest, TestVectors) { 688ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan FileTestGTest("crypto/ecdh/ecdh_tests.txt", [](FileTest *t) { 698ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve"); 708ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(group); 718ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan bssl::UniquePtr<BIGNUM> priv_key = GetBIGNUM(t, "Private"); 728ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(priv_key); 738ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X"); 748ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(x); 758ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y"); 768ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(y); 778ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan bssl::UniquePtr<BIGNUM> peer_x = GetBIGNUM(t, "PeerX"); 788ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(peer_x); 798ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan bssl::UniquePtr<BIGNUM> peer_y = GetBIGNUM(t, "PeerY"); 808ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(peer_y); 818ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan std::vector<uint8_t> z; 828ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(t->GetBytes(&z, "Z")); 838ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan 848ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan bssl::UniquePtr<EC_KEY> key(EC_KEY_new()); 858ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(key); 868ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan bssl::UniquePtr<EC_POINT> pub_key(EC_POINT_new(group.get())); 878ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(pub_key); 888ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan bssl::UniquePtr<EC_POINT> peer_pub_key(EC_POINT_new(group.get())); 898ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(peer_pub_key); 908ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(EC_KEY_set_group(key.get(), group.get())); 918ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(EC_KEY_set_private_key(key.get(), priv_key.get())); 928ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), pub_key.get(), 938ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan x.get(), y.get(), nullptr)); 948ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp( 958ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan group.get(), peer_pub_key.get(), peer_x.get(), peer_y.get(), nullptr)); 968ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(EC_KEY_set_public_key(key.get(), pub_key.get())); 978ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(EC_KEY_check_key(key.get())); 988ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan 998ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan std::vector<uint8_t> actual_z; 1008ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan // Make |actual_z| larger than expected to ensure |ECDH_compute_key| returns 1018ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan // the right amount of data. 1028ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan actual_z.resize(z.size() + 1); 1038ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan int ret = ECDH_compute_key(actual_z.data(), actual_z.size(), 1048ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan peer_pub_key.get(), key.get(), nullptr); 1058ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_GE(ret, 0); 1068ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan EXPECT_EQ(Bytes(z), Bytes(actual_z.data(), static_cast<size_t>(ret))); 1078ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan 1088ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan // Test |ECDH_compute_key| truncates. 1098ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan actual_z.resize(z.size() - 1); 1108ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ret = ECDH_compute_key(actual_z.data(), actual_z.size(), peer_pub_key.get(), 1118ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan key.get(), nullptr); 1128ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_GE(ret, 0); 1138ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan EXPECT_EQ(Bytes(z.data(), z.size() - 1), 1148ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan Bytes(actual_z.data(), static_cast<size_t>(ret))); 1158ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan }); 116f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin} 11729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 11829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan// MakeCustomGroup returns an |EC_GROUP| containing a non-standard group. (P-256 11929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan// with the wrong generator.) 12029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloanstatic bssl::UniquePtr<EC_GROUP> MakeCustomGroup() { 12129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan static const uint8_t kP[] = { 12229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 12329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 12429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 12529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan }; 12629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan static const uint8_t kA[] = { 12729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 12829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 12929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 13029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan }; 13129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan static const uint8_t kB[] = { 13229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 13329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 13429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 13529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan }; 13629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan static const uint8_t kX[] = { 13729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0xe6, 0x2b, 0x69, 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f, 0x1e, 13829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x0d, 0x94, 0x8a, 0x4c, 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d, 13929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x46, 0xfb, 0xdd, 0xa9, 0xa9, 0x1e, 0x9d, 0xdc, 0xba, 0x5a, 14029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan }; 14129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan static const uint8_t kY[] = { 14229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x01, 0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18, 0xf9, 0xc3, 0xc4, 0xa3, 14329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x1e, 0x56, 0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16, 0x1a, 0x1c, 0xf5, 14429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x1d, 0x7e, 0xf1, 0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22, 0xc1, 14529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan }; 14629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan static const uint8_t kOrder[] = { 14729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 14829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 14929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, 15029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan }; 15129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 15229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr)); 15329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr)); 15429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr)); 15529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<BIGNUM> x(BN_bin2bn(kX, sizeof(kX), nullptr)); 15629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<BIGNUM> y(BN_bin2bn(kY, sizeof(kY), nullptr)); 15729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr)); 15829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan if (!ctx || !p || !a || !b || !x || !y || !order) { 15929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan return nullptr; 16029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan } 16129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<EC_GROUP> group( 16229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); 16329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan if (!group) { 16429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan return nullptr; 16529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan } 16629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get())); 16729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan if (!generator || 16829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan !EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), 16929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan x.get(), y.get(), ctx.get()) || 17029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan !EC_GROUP_set_generator(group.get(), generator.get(), order.get(), 17129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan BN_value_one())) { 17229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan return nullptr; 17329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan } 17429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan return group; 17529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan} 17629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 17729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert SloanTEST(ECDHTest, GroupMismatch) { 17829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan const size_t num_curves = EC_get_builtin_curves(nullptr, 0); 17929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan std::vector<EC_builtin_curve> curves(num_curves); 18029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan EC_get_builtin_curves(curves.data(), num_curves); 18129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 18229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan // Instantiate all the built-in curves. 18329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan std::vector<bssl::UniquePtr<EC_GROUP>> groups; 18429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan for (const auto &curve : curves) { 18529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan groups.emplace_back(EC_GROUP_new_by_curve_name(curve.nid)); 18629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(groups.back()); 18729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan } 18829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 18929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan // Also create some arbitrary group. (This is P-256 with the wrong generator.) 19029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan groups.push_back(MakeCustomGroup()); 19129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(groups.back()); 19229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 19329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan for (const auto &a : groups) { 19429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan for (const auto &b : groups) { 19529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan if (a.get() == b.get()) { 19629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan continue; 19729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan } 19829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 19929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<EC_KEY> key(EC_KEY_new()); 20029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(EC_KEY_set_group(key.get(), a.get())); 20129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(EC_KEY_generate_key(key.get())); 20229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 20329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan // ECDH across the groups should not work. 20429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan char out[64]; 20529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan const EC_POINT *peer = EC_GROUP_get0_generator(b.get()); 20629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan EXPECT_EQ(-1, 20729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ECDH_compute_key(out, sizeof(out), peer, key.get(), nullptr)); 20829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ERR_clear_error(); 20929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan } 21029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan } 21129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan} 212