Home | History | Annotate | Download | only in ec
      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> &params) {
    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