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> ¶ms) {
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