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 "../bn/internal.h"
32#include "../../test/test_util.h"
33
34
35// kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
36// omitted.
37static const uint8_t kECKeyWithoutPublic[] = {
38  0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0,
39  0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e,
40  0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
41  0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
42};
43
44// kECKeySpecifiedCurve is the above key with P-256's parameters explicitly
45// spelled out rather than using a named curve.
46static const uint8_t kECKeySpecifiedCurve[] = {
47    0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa,
48    0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb,
49    0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc,
50    0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02,
51    0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
52    0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
53    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55    0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
56    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
58    0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
59    0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
60    0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
61    0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
62    0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
63    0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
64    0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
65    0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
66    0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
67    0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
68    0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
69    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
70    0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
71    0x63, 0x25, 0x51, 0x02, 0x01, 0x01,
72};
73
74// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
75// the private key is one. The private key is incorrectly encoded without zero
76// padding.
77static const uint8_t kECKeyMissingZeros[] = {
78  0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a,
79  0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
80  0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
81  0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1,
82  0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f,
83  0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
84  0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
85};
86
87// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
88// the private key is one. The private key is encoded with the required zero
89// padding.
90static const uint8_t kECKeyWithZeros[] = {
91  0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
94  0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1,
95  0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
96  0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d,
97  0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3,
98  0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e,
99  0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
100  0x37, 0xbf, 0x51, 0xf5,
101};
102
103// DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
104// result or nullptr on error.
105static bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in,
106                                                  size_t in_len) {
107  CBS cbs;
108  CBS_init(&cbs, in, in_len);
109  bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL));
110  if (!ret || CBS_len(&cbs) != 0) {
111    return nullptr;
112  }
113  return ret;
114}
115
116// EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
117// returns true on success or false on error.
118static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
119  bssl::ScopedCBB cbb;
120  uint8_t *der;
121  size_t der_len;
122  if (!CBB_init(cbb.get(), 0) ||
123      !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) ||
124      !CBB_finish(cbb.get(), &der, &der_len)) {
125    return false;
126  }
127  out->assign(der, der + der_len);
128  OPENSSL_free(der);
129  return true;
130}
131
132TEST(ECTest, Encoding) {
133  bssl::UniquePtr<EC_KEY> key =
134      DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
135  ASSERT_TRUE(key);
136
137  // Test that the encoding round-trips.
138  std::vector<uint8_t> out;
139  ASSERT_TRUE(EncodeECPrivateKey(&out, key.get()));
140  EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
141
142  const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
143  ASSERT_TRUE(pub_key) << "Public key missing";
144
145  bssl::UniquePtr<BIGNUM> x(BN_new());
146  bssl::UniquePtr<BIGNUM> y(BN_new());
147  ASSERT_TRUE(x);
148  ASSERT_TRUE(y);
149  ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
150      EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL));
151  bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
152  bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
153  ASSERT_TRUE(x_hex);
154  ASSERT_TRUE(y_hex);
155
156  EXPECT_STREQ(
157      "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681",
158      x_hex.get());
159  EXPECT_STREQ(
160      "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88",
161      y_hex.get());
162}
163
164TEST(ECTest, ZeroPadding) {
165  // Check that the correct encoding round-trips.
166  bssl::UniquePtr<EC_KEY> key =
167      DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros));
168  ASSERT_TRUE(key);
169  std::vector<uint8_t> out;
170  EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
171  EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
172
173  // Keys without leading zeros also parse, but they encode correctly.
174  key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
175  ASSERT_TRUE(key);
176  EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
177  EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
178}
179
180TEST(ECTest, SpecifiedCurve) {
181  // Test keys with specified curves may be decoded.
182  bssl::UniquePtr<EC_KEY> key =
183      DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve));
184  ASSERT_TRUE(key);
185
186  // The group should have been interpreted as P-256.
187  EXPECT_EQ(NID_X9_62_prime256v1,
188            EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())));
189
190  // Encoding the key should still use named form.
191  std::vector<uint8_t> out;
192  EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
193  EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
194}
195
196TEST(ECTest, ArbitraryCurve) {
197  // Make a P-256 key and extract the affine coordinates.
198  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
199  ASSERT_TRUE(key);
200  ASSERT_TRUE(EC_KEY_generate_key(key.get()));
201
202  // Make an arbitrary curve which is identical to P-256.
203  static const uint8_t kP[] = {
204      0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
205      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
206      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
207  };
208  static const uint8_t kA[] = {
209      0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
210      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
211      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
212  };
213  static const uint8_t kB[] = {
214      0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
215      0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
216      0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
217  };
218  static const uint8_t kX[] = {
219      0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6,
220      0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb,
221      0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96,
222  };
223  static const uint8_t kY[] = {
224      0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
225      0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
226      0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
227  };
228  static const uint8_t kOrder[] = {
229      0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
230      0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
231      0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
232  };
233  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
234  ASSERT_TRUE(ctx);
235  bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
236  ASSERT_TRUE(p);
237  bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
238  ASSERT_TRUE(a);
239  bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
240  ASSERT_TRUE(b);
241  bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr));
242  ASSERT_TRUE(gx);
243  bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr));
244  ASSERT_TRUE(gy);
245  bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
246  ASSERT_TRUE(order);
247
248  bssl::UniquePtr<EC_GROUP> group(
249      EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
250  ASSERT_TRUE(group);
251  bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
252  ASSERT_TRUE(generator);
253  ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
254      group.get(), generator.get(), gx.get(), gy.get(), ctx.get()));
255  ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
256                                     BN_value_one()));
257
258  // |group| should not have a curve name.
259  EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get()));
260
261  // Copy |key| to |key2| using |group|.
262  bssl::UniquePtr<EC_KEY> key2(EC_KEY_new());
263  ASSERT_TRUE(key2);
264  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
265  ASSERT_TRUE(point);
266  bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
267  ASSERT_TRUE(x);
268  ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get()));
269  ASSERT_TRUE(
270      EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())));
271  ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
272      EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(),
273      y.get(), nullptr));
274  ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(),
275                                                  x.get(), y.get(), nullptr));
276  ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get()));
277
278  // The key must be valid according to the new group too.
279  EXPECT_TRUE(EC_KEY_check_key(key2.get()));
280
281  // Make a second instance of |group|.
282  bssl::UniquePtr<EC_GROUP> group2(
283      EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
284  ASSERT_TRUE(group2);
285  bssl::UniquePtr<EC_POINT> generator2(EC_POINT_new(group2.get()));
286  ASSERT_TRUE(generator2);
287  ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
288      group2.get(), generator2.get(), gx.get(), gy.get(), ctx.get()));
289  ASSERT_TRUE(EC_GROUP_set_generator(group2.get(), generator2.get(),
290                                     order.get(), BN_value_one()));
291
292  EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
293  EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), NULL));
294
295  // group3 uses the wrong generator.
296  bssl::UniquePtr<EC_GROUP> group3(
297      EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
298  ASSERT_TRUE(group3);
299  bssl::UniquePtr<EC_POINT> generator3(EC_POINT_new(group3.get()));
300  ASSERT_TRUE(generator3);
301  ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
302      group3.get(), generator3.get(), x.get(), y.get(), ctx.get()));
303  ASSERT_TRUE(EC_GROUP_set_generator(group3.get(), generator3.get(),
304                                     order.get(), BN_value_one()));
305
306  EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL));
307}
308
309TEST(ECTest, SetKeyWithoutGroup) {
310  bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
311  ASSERT_TRUE(key);
312
313  // Private keys may not be configured without a group.
314  EXPECT_FALSE(EC_KEY_set_private_key(key.get(), BN_value_one()));
315
316  // Public keys may not be configured without a group.
317  bssl::UniquePtr<EC_GROUP> group(
318      EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
319  ASSERT_TRUE(group);
320  EXPECT_FALSE(
321      EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(group.get())));
322}
323
324TEST(ECTest, GroupMismatch) {
325  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
326  ASSERT_TRUE(key);
327  bssl::UniquePtr<EC_GROUP> p256(
328      EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
329  ASSERT_TRUE(p256);
330
331  // Changing a key's group is invalid.
332  EXPECT_FALSE(EC_KEY_set_group(key.get(), p256.get()));
333
334  // Configuring a public key with the wrong group is invalid.
335  EXPECT_FALSE(
336      EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(p256.get())));
337}
338
339class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {};
340
341TEST_P(ECCurveTest, SetAffine) {
342  // Generate an EC_KEY.
343  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
344  ASSERT_TRUE(key);
345  ASSERT_TRUE(EC_KEY_generate_key(key.get()));
346
347  const EC_GROUP *const group = EC_KEY_get0_group(key.get());
348  EXPECT_TRUE(
349      EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()), nullptr));
350
351  // Get the public key's coordinates.
352  bssl::UniquePtr<BIGNUM> x(BN_new());
353  ASSERT_TRUE(x);
354  bssl::UniquePtr<BIGNUM> y(BN_new());
355  ASSERT_TRUE(y);
356  bssl::UniquePtr<BIGNUM> p(BN_new());
357  ASSERT_TRUE(p);
358  EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
359      group, EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
360  EXPECT_TRUE(
361      EC_GROUP_get_curve_GFp(group, p.get(), nullptr, nullptr, nullptr));
362
363  // Points on the curve should be accepted.
364  auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group));
365  ASSERT_TRUE(point);
366  EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(),
367                                                  y.get(), nullptr));
368
369  // Subtract one from |y| to make the point no longer on the curve.
370  EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one()));
371
372  // Points not on the curve should be rejected.
373  bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group));
374  ASSERT_TRUE(invalid_point);
375  EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(),
376                                                   x.get(), y.get(), nullptr));
377
378  // Coordinates out of range should be rejected.
379  EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one()));
380  EXPECT_TRUE(BN_add(y.get(), y.get(), p.get()));
381
382  EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(),
383                                                   x.get(), y.get(), nullptr));
384  EXPECT_FALSE(
385      EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
386}
387
388TEST_P(ECCurveTest, GenerateFIPS) {
389  // Generate an EC_KEY.
390  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
391  ASSERT_TRUE(key);
392  ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()));
393}
394
395TEST_P(ECCurveTest, AddingEqualPoints) {
396  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
397  ASSERT_TRUE(key);
398  ASSERT_TRUE(EC_KEY_generate_key(key.get()));
399
400  const EC_GROUP *const group = EC_KEY_get0_group(key.get());
401
402  bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group));
403  ASSERT_TRUE(p1);
404  ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
405
406  bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group));
407  ASSERT_TRUE(p2);
408  ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
409
410  bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group));
411  ASSERT_TRUE(double_p1);
412  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
413  ASSERT_TRUE(ctx);
414  ASSERT_TRUE(EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()));
415
416  bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group));
417  ASSERT_TRUE(p1_plus_p2);
418  ASSERT_TRUE(
419      EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
420
421  EXPECT_EQ(0,
422            EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()))
423      << "A+A != 2A";
424}
425
426TEST_P(ECCurveTest, MulZero) {
427  bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
428  ASSERT_TRUE(group);
429
430  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
431  ASSERT_TRUE(point);
432  bssl::UniquePtr<BIGNUM> zero(BN_new());
433  ASSERT_TRUE(zero);
434  BN_zero(zero.get());
435  ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), zero.get(), nullptr,
436                           nullptr, nullptr));
437
438  EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
439      << "g * 0 did not return point at infinity.";
440
441  // Test that zero times an arbitrary point is also infinity. The generator is
442  // used as the arbitrary point.
443  bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
444  ASSERT_TRUE(generator);
445  ASSERT_TRUE(EC_POINT_mul(group.get(), generator.get(), BN_value_one(),
446                           nullptr, nullptr, nullptr));
447  ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, generator.get(),
448                           zero.get(), nullptr));
449
450  EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
451      << "p * 0 did not return point at infinity.";
452}
453
454// Test that multiplying by the order produces ∞ and, moreover, that callers may
455// do so. |EC_POINT_mul| is almost exclusively used with reduced scalars, with
456// this exception. This comes from consumers following NIST SP 800-56A section
457// 5.6.2.3.2. (Though all our curves have cofactor one, so this check isn't
458// useful.)
459TEST_P(ECCurveTest, MulOrder) {
460  bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
461  ASSERT_TRUE(group);
462
463  // Test that g × order = ∞.
464  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
465  ASSERT_TRUE(point);
466  ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(),
467                           EC_GROUP_get0_order(group.get()), nullptr, nullptr,
468                           nullptr));
469
470  EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
471      << "g * order did not return point at infinity.";
472
473  // Test that p × order = ∞, for some arbitrary p.
474  bssl::UniquePtr<BIGNUM> forty_two(BN_new());
475  ASSERT_TRUE(forty_two);
476  ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
477  ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr,
478                           nullptr, nullptr));
479  ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, point.get(),
480                           EC_GROUP_get0_order(group.get()), nullptr));
481
482  EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
483      << "p * order did not return point at infinity.";
484}
485
486// Test that |EC_POINT_mul| works with out-of-range scalars. Even beyond the
487// usual |bn_correct_top| disclaimer, we completely disclaim all hope here as a
488// reduction is needed, but we'll compute the right answer.
489TEST_P(ECCurveTest, MulOutOfRange) {
490  bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
491  ASSERT_TRUE(group);
492
493  bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(EC_GROUP_get0_order(group.get())));
494  ASSERT_TRUE(n_minus_one);
495  ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1));
496
497  bssl::UniquePtr<BIGNUM> minus_one(BN_new());
498  ASSERT_TRUE(minus_one);
499  ASSERT_TRUE(BN_one(minus_one.get()));
500  BN_set_negative(minus_one.get(), 1);
501
502  bssl::UniquePtr<BIGNUM> seven(BN_new());
503  ASSERT_TRUE(seven);
504  ASSERT_TRUE(BN_set_word(seven.get(), 7));
505
506  bssl::UniquePtr<BIGNUM> ten_n_plus_seven(
507      BN_dup(EC_GROUP_get0_order(group.get())));
508  ASSERT_TRUE(ten_n_plus_seven);
509  ASSERT_TRUE(BN_mul_word(ten_n_plus_seven.get(), 10));
510  ASSERT_TRUE(BN_add_word(ten_n_plus_seven.get(), 7));
511
512  bssl::UniquePtr<EC_POINT> point1(EC_POINT_new(group.get())),
513      point2(EC_POINT_new(group.get()));
514  ASSERT_TRUE(point1);
515  ASSERT_TRUE(point2);
516
517  ASSERT_TRUE(EC_POINT_mul(group.get(), point1.get(), n_minus_one.get(),
518                           nullptr, nullptr, nullptr));
519  ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), minus_one.get(), nullptr,
520                           nullptr, nullptr));
521  EXPECT_EQ(0, EC_POINT_cmp(group.get(), point1.get(), point2.get(), nullptr))
522      << "-1 * G and (n-1) * G did not give the same result";
523
524  ASSERT_TRUE(EC_POINT_mul(group.get(), point1.get(), seven.get(), nullptr,
525                           nullptr, nullptr));
526  ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), ten_n_plus_seven.get(),
527                           nullptr, nullptr, nullptr));
528  EXPECT_EQ(0, EC_POINT_cmp(group.get(), point1.get(), point2.get(), nullptr))
529      << "7 * G and (10n + 7) * G did not give the same result";
530}
531
532// Test that 10×∞ + G = G.
533TEST_P(ECCurveTest, Mul) {
534  bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
535  ASSERT_TRUE(group);
536  bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
537  ASSERT_TRUE(p);
538  bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group.get()));
539  ASSERT_TRUE(result);
540  bssl::UniquePtr<BIGNUM> n(BN_new());
541  ASSERT_TRUE(n);
542  ASSERT_TRUE(EC_POINT_set_to_infinity(group.get(), p.get()));
543  ASSERT_TRUE(BN_set_word(n.get(), 10));
544
545  // First check that 10×∞ = ∞.
546  ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), nullptr, p.get(), n.get(),
547                           nullptr));
548  EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), result.get()));
549
550  // Now check that 10×∞ + G = G.
551  const EC_POINT *generator = EC_GROUP_get0_generator(group.get());
552  ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), BN_value_one(), p.get(),
553                           n.get(), nullptr));
554  EXPECT_EQ(0, EC_POINT_cmp(group.get(), result.get(), generator, nullptr));
555}
556
557#if !defined(BORINGSSL_SHARED_LIBRARY)
558TEST_P(ECCurveTest, MulNonMinimal) {
559  bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
560  ASSERT_TRUE(group);
561
562  bssl::UniquePtr<BIGNUM> forty_two(BN_new());
563  ASSERT_TRUE(forty_two);
564  ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
565
566  // Compute g × 42.
567  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
568  ASSERT_TRUE(point);
569  ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr,
570                           nullptr, nullptr));
571
572  // Compute it again with a non-minimal 42, much larger than the scalar.
573  ASSERT_TRUE(bn_resize_words(forty_two.get(), 64));
574
575  bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group.get()));
576  ASSERT_TRUE(point2);
577  ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), forty_two.get(), nullptr,
578                           nullptr, nullptr));
579  EXPECT_EQ(0, EC_POINT_cmp(group.get(), point.get(), point2.get(), nullptr));
580}
581#endif  // BORINGSSL_SHARED_LIBRARY
582
583// Test that EC_KEY_set_private_key rejects invalid values.
584TEST_P(ECCurveTest, SetInvalidPrivateKey) {
585  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
586  ASSERT_TRUE(key);
587
588  bssl::UniquePtr<BIGNUM> bn(BN_new());
589  ASSERT_TRUE(BN_one(bn.get()));
590  BN_set_negative(bn.get(), 1);
591  EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
592      << "Unexpectedly set a key of -1";
593  ERR_clear_error();
594
595  ASSERT_TRUE(
596      BN_copy(bn.get(), EC_GROUP_get0_order(EC_KEY_get0_group(key.get()))));
597  EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
598      << "Unexpectedly set a key of the group order.";
599  ERR_clear_error();
600}
601
602TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
603  bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
604  ASSERT_TRUE(group);
605
606  bssl::UniquePtr<BIGNUM> forty_two(BN_new());
607  ASSERT_TRUE(forty_two);
608  ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
609
610  // Compute g × 42.
611  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
612  ASSERT_TRUE(point);
613  ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr,
614                           nullptr, nullptr));
615
616  // Serialize the point.
617  size_t serialized_len =
618      EC_POINT_point2oct(group.get(), point.get(),
619                         POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
620  ASSERT_NE(0u, serialized_len);
621
622  std::vector<uint8_t> serialized(serialized_len);
623  ASSERT_EQ(serialized_len,
624            EC_POINT_point2oct(group.get(), point.get(),
625                               POINT_CONVERSION_UNCOMPRESSED, serialized.data(),
626                               serialized_len, nullptr));
627
628  // Create a serialized point that is not on the curve.
629  serialized[serialized_len - 1]++;
630
631  ASSERT_FALSE(EC_POINT_oct2point(group.get(), point.get(), serialized.data(),
632                                  serialized.size(), nullptr));
633  // After a failure, |point| should have been set to the generator to defend
634  // against code that doesn't check the return value.
635  ASSERT_EQ(0, EC_POINT_cmp(group.get(), point.get(),
636                            EC_GROUP_get0_generator(group.get()), nullptr));
637}
638
639static std::vector<EC_builtin_curve> AllCurves() {
640  const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
641  std::vector<EC_builtin_curve> curves(num_curves);
642  EC_get_builtin_curves(curves.data(), num_curves);
643  return curves;
644}
645
646static std::string CurveToString(
647    const testing::TestParamInfo<EC_builtin_curve> &params) {
648  // The comment field contains characters GTest rejects, so use the OBJ name.
649  return OBJ_nid2sn(params.param.nid);
650}
651
652INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
653                        CurveToString);
654