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.
DecodeECPrivateKey(const uint8_t * in,size_t in_len)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.
EncodeECPrivateKey(std::vector<uint8_t> * out,const EC_KEY * key)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 
TEST(ECTest,Encoding)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 
TEST(ECTest,ZeroPadding)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 
TEST(ECTest,SpecifiedCurve)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 
TEST(ECTest,ArbitraryCurve)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 
TEST_P(ECCurveTest,SetAffine)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 
TEST_P(ECCurveTest,AddingEqualPoints)317 TEST_P(ECCurveTest, AddingEqualPoints) {
318   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
319   ASSERT_TRUE(key);
320   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
321 
322   const EC_GROUP *const group = EC_KEY_get0_group(key.get());
323 
324   bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group));
325   ASSERT_TRUE(p1);
326   ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
327 
328   bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group));
329   ASSERT_TRUE(p2);
330   ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
331 
332   bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group));
333   ASSERT_TRUE(double_p1);
334   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
335   ASSERT_TRUE(ctx);
336   ASSERT_TRUE(EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()));
337 
338   bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group));
339   ASSERT_TRUE(p1_plus_p2);
340   ASSERT_TRUE(
341       EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
342 
343   EXPECT_EQ(0,
344             EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()))
345       << "A+A != 2A";
346 }
347 
TEST_P(ECCurveTest,MulZero)348 TEST_P(ECCurveTest, MulZero) {
349   bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
350   ASSERT_TRUE(group);
351 
352   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
353   ASSERT_TRUE(point);
354   bssl::UniquePtr<BIGNUM> zero(BN_new());
355   ASSERT_TRUE(zero);
356   BN_zero(zero.get());
357   ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), zero.get(), nullptr,
358                            nullptr, nullptr));
359 
360   EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
361       << "g * 0 did not return point at infinity.";
362 
363   // Test that zero times an arbitrary point is also infinity. The generator is
364   // used as the arbitrary point.
365   bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
366   ASSERT_TRUE(generator);
367   ASSERT_TRUE(EC_POINT_mul(group.get(), generator.get(), BN_value_one(),
368                            nullptr, nullptr, nullptr));
369   ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, generator.get(),
370                            zero.get(), nullptr));
371 
372   EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
373       << "p * 0 did not return point at infinity.";
374 }
375 
AllCurves()376 static std::vector<EC_builtin_curve> AllCurves() {
377   const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
378   std::vector<EC_builtin_curve> curves(num_curves);
379   EC_get_builtin_curves(curves.data(), num_curves);
380   return curves;
381 }
382 
CurveToString(const testing::TestParamInfo<EC_builtin_curve> & params)383 static std::string CurveToString(
384     const testing::TestParamInfo<EC_builtin_curve> &params) {
385   // The comment field contains characters GTest rejects, so use the OBJ name.
386   return OBJ_nid2sn(params.param.nid);
387 }
388 
389 INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
390                         CurveToString);
391