1 /* Copyright (c) 2014, 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 #include <stdio.h> 16 #include <string.h> 17 18 #include <vector> 19 20 #include <gtest/gtest.h> 21 22 #include <openssl/bn.h> 23 #include <openssl/bytestring.h> 24 #include <openssl/crypto.h> 25 #include <openssl/ec_key.h> 26 #include <openssl/err.h> 27 #include <openssl/mem.h> 28 #include <openssl/nid.h> 29 #include <openssl/obj.h> 30 31 #include "../../test/test_util.h" 32 33 34 // kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field 35 // omitted. 36 static const uint8_t kECKeyWithoutPublic[] = { 37 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0, 38 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e, 39 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77, 40 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 41 }; 42 43 // kECKeySpecifiedCurve is the above key with P-256's parameters explicitly 44 // spelled out rather than using a named curve. 45 static const uint8_t kECKeySpecifiedCurve[] = { 46 0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 47 0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 48 0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 49 0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02, 50 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 51 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 54 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 57 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 58 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 59 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, 60 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, 61 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, 62 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 63 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 64 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 65 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 66 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 67 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 68 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 69 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 70 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 71 }; 72 73 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where 74 // the private key is one. The private key is incorrectly encoded without zero 75 // padding. 76 static const uint8_t kECKeyMissingZeros[] = { 77 0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 78 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 79 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 80 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 81 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 82 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 83 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, 84 }; 85 86 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where 87 // the private key is one. The private key is encoded with the required zero 88 // padding. 89 static const uint8_t kECKeyWithZeros[] = { 90 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 93 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 94 0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 95 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 96 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 97 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 98 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 99 0x37, 0xbf, 0x51, 0xf5, 100 }; 101 102 // DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the 103 // result or nullptr on error. 104 static bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in, 105 size_t in_len) { 106 CBS cbs; 107 CBS_init(&cbs, in, in_len); 108 bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL)); 109 if (!ret || CBS_len(&cbs) != 0) { 110 return nullptr; 111 } 112 return ret; 113 } 114 115 // EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It 116 // returns true on success or false on error. 117 static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) { 118 bssl::ScopedCBB cbb; 119 uint8_t *der; 120 size_t der_len; 121 if (!CBB_init(cbb.get(), 0) || 122 !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) || 123 !CBB_finish(cbb.get(), &der, &der_len)) { 124 return false; 125 } 126 out->assign(der, der + der_len); 127 OPENSSL_free(der); 128 return true; 129 } 130 131 TEST(ECTest, Encoding) { 132 bssl::UniquePtr<EC_KEY> key = 133 DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic)); 134 ASSERT_TRUE(key); 135 136 // Test that the encoding round-trips. 137 std::vector<uint8_t> out; 138 ASSERT_TRUE(EncodeECPrivateKey(&out, key.get())); 139 EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size())); 140 141 const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get()); 142 ASSERT_TRUE(pub_key) << "Public key missing"; 143 144 bssl::UniquePtr<BIGNUM> x(BN_new()); 145 bssl::UniquePtr<BIGNUM> y(BN_new()); 146 ASSERT_TRUE(x); 147 ASSERT_TRUE(y); 148 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp( 149 EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL)); 150 bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get())); 151 bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get())); 152 ASSERT_TRUE(x_hex); 153 ASSERT_TRUE(y_hex); 154 155 EXPECT_STREQ( 156 "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681", 157 x_hex.get()); 158 EXPECT_STREQ( 159 "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88", 160 y_hex.get()); 161 } 162 163 TEST(ECTest, ZeroPadding) { 164 // Check that the correct encoding round-trips. 165 bssl::UniquePtr<EC_KEY> key = 166 DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros)); 167 ASSERT_TRUE(key); 168 std::vector<uint8_t> out; 169 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 170 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size())); 171 172 // Keys without leading zeros also parse, but they encode correctly. 173 key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros)); 174 ASSERT_TRUE(key); 175 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 176 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size())); 177 } 178 179 TEST(ECTest, SpecifiedCurve) { 180 // Test keys with specified curves may be decoded. 181 bssl::UniquePtr<EC_KEY> key = 182 DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve)); 183 ASSERT_TRUE(key); 184 185 // The group should have been interpreted as P-256. 186 EXPECT_EQ(NID_X9_62_prime256v1, 187 EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get()))); 188 189 // Encoding the key should still use named form. 190 std::vector<uint8_t> out; 191 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 192 EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size())); 193 } 194 195 TEST(ECTest, ArbitraryCurve) { 196 // Make a P-256 key and extract the affine coordinates. 197 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); 198 ASSERT_TRUE(key); 199 ASSERT_TRUE(EC_KEY_generate_key(key.get())); 200 201 // Make an arbitrary curve which is identical to P-256. 202 static const uint8_t kP[] = { 203 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 205 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 206 }; 207 static const uint8_t kA[] = { 208 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 210 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 211 }; 212 static const uint8_t kB[] = { 213 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 214 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 215 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 216 }; 217 static const uint8_t kX[] = { 218 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 219 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 220 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 221 }; 222 static const uint8_t kY[] = { 223 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 224 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 225 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, 226 }; 227 static const uint8_t kOrder[] = { 228 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 229 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 230 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, 231 }; 232 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 233 ASSERT_TRUE(ctx); 234 bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr)); 235 ASSERT_TRUE(p); 236 bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr)); 237 ASSERT_TRUE(a); 238 bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr)); 239 ASSERT_TRUE(b); 240 bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr)); 241 ASSERT_TRUE(gx); 242 bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr)); 243 ASSERT_TRUE(gy); 244 bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr)); 245 ASSERT_TRUE(order); 246 247 bssl::UniquePtr<EC_GROUP> group( 248 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); 249 ASSERT_TRUE(group); 250 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get())); 251 ASSERT_TRUE(generator); 252 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp( 253 group.get(), generator.get(), gx.get(), gy.get(), ctx.get())); 254 ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(), 255 BN_value_one())); 256 257 // |group| should not have a curve name. 258 EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get())); 259 260 // Copy |key| to |key2| using |group|. 261 bssl::UniquePtr<EC_KEY> key2(EC_KEY_new()); 262 ASSERT_TRUE(key2); 263 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 264 ASSERT_TRUE(point); 265 bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new()); 266 ASSERT_TRUE(x); 267 ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get())); 268 ASSERT_TRUE( 269 EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get()))); 270 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp( 271 EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(), 272 y.get(), nullptr)); 273 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), 274 x.get(), y.get(), nullptr)); 275 ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get())); 276 277 // The key must be valid according to the new group too. 278 EXPECT_TRUE(EC_KEY_check_key(key2.get())); 279 } 280 281 class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {}; 282 283 TEST_P(ECCurveTest, SetAffine) { 284 // Generate an EC_KEY. 285 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 286 ASSERT_TRUE(key); 287 ASSERT_TRUE(EC_KEY_generate_key(key.get())); 288 289 const EC_GROUP *const group = EC_KEY_get0_group(key.get()); 290 EXPECT_TRUE( 291 EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()), nullptr)); 292 293 // Get the public key's coordinates. 294 bssl::UniquePtr<BIGNUM> x(BN_new()); 295 ASSERT_TRUE(x); 296 bssl::UniquePtr<BIGNUM> y(BN_new()); 297 ASSERT_TRUE(y); 298 EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp( 299 group, EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr)); 300 301 // Points on the curve should be accepted. 302 auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group)); 303 ASSERT_TRUE(point); 304 EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(), 305 y.get(), nullptr)); 306 307 // Subtract one from |y| to make the point no longer on the curve. 308 EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one())); 309 310 // Points not on the curve should be rejected. 311 bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group)); 312 ASSERT_TRUE(invalid_point); 313 EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(), 314 x.get(), y.get(), nullptr)); 315 } 316 317 TEST_P(ECCurveTest, GenerateFIPS) { 318 // Generate an EC_KEY. 319 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 320 ASSERT_TRUE(key); 321 ASSERT_TRUE(EC_KEY_generate_key_fips(key.get())); 322 } 323 324 TEST_P(ECCurveTest, AddingEqualPoints) { 325 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 326 ASSERT_TRUE(key); 327 ASSERT_TRUE(EC_KEY_generate_key(key.get())); 328 329 const EC_GROUP *const group = EC_KEY_get0_group(key.get()); 330 331 bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group)); 332 ASSERT_TRUE(p1); 333 ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get()))); 334 335 bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group)); 336 ASSERT_TRUE(p2); 337 ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get()))); 338 339 bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group)); 340 ASSERT_TRUE(double_p1); 341 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 342 ASSERT_TRUE(ctx); 343 ASSERT_TRUE(EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get())); 344 345 bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group)); 346 ASSERT_TRUE(p1_plus_p2); 347 ASSERT_TRUE( 348 EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get())); 349 350 EXPECT_EQ(0, 351 EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get())) 352 << "A+A != 2A"; 353 } 354 355 TEST_P(ECCurveTest, MulZero) { 356 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); 357 ASSERT_TRUE(group); 358 359 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 360 ASSERT_TRUE(point); 361 bssl::UniquePtr<BIGNUM> zero(BN_new()); 362 ASSERT_TRUE(zero); 363 BN_zero(zero.get()); 364 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), zero.get(), nullptr, 365 nullptr, nullptr)); 366 367 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get())) 368 << "g * 0 did not return point at infinity."; 369 370 // Test that zero times an arbitrary point is also infinity. The generator is 371 // used as the arbitrary point. 372 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get())); 373 ASSERT_TRUE(generator); 374 ASSERT_TRUE(EC_POINT_mul(group.get(), generator.get(), BN_value_one(), 375 nullptr, nullptr, nullptr)); 376 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, generator.get(), 377 zero.get(), nullptr)); 378 379 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get())) 380 << "p * 0 did not return point at infinity."; 381 } 382 383 // Test that 10 + G = G. 384 TEST_P(ECCurveTest, Mul) { 385 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); 386 ASSERT_TRUE(group); 387 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get())); 388 ASSERT_TRUE(p); 389 bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group.get())); 390 ASSERT_TRUE(result); 391 bssl::UniquePtr<BIGNUM> n(BN_new()); 392 ASSERT_TRUE(n); 393 ASSERT_TRUE(EC_POINT_set_to_infinity(group.get(), p.get())); 394 ASSERT_TRUE(BN_set_word(n.get(), 10)); 395 396 // First check that 10 = . 397 ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), nullptr, p.get(), n.get(), 398 nullptr)); 399 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), result.get())); 400 401 // Now check that 10 + G = G. 402 const EC_POINT *generator = EC_GROUP_get0_generator(group.get()); 403 ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), BN_value_one(), p.get(), 404 n.get(), nullptr)); 405 EXPECT_EQ(0, EC_POINT_cmp(group.get(), result.get(), generator, nullptr)); 406 } 407 408 static std::vector<EC_builtin_curve> AllCurves() { 409 const size_t num_curves = EC_get_builtin_curves(nullptr, 0); 410 std::vector<EC_builtin_curve> curves(num_curves); 411 EC_get_builtin_curves(curves.data(), num_curves); 412 return curves; 413 } 414 415 static std::string CurveToString( 416 const testing::TestParamInfo<EC_builtin_curve> ¶ms) { 417 // The comment field contains characters GTest rejects, so use the OBJ name. 418 return OBJ_nid2sn(params.param.nid); 419 } 420 421 INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()), 422 CurveToString); 423