• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdlib.h>
17 #include <string.h>
18 
19 #include <vector>
20 
21 #include <gtest/gtest.h>
22 
23 #include <openssl/bn.h>
24 #include <openssl/bytestring.h>
25 #include <openssl/crypto.h>
26 #include <openssl/ec_key.h>
27 #include <openssl/err.h>
28 #include <openssl/mem.h>
29 #include <openssl/nid.h>
30 #include <openssl/obj.h>
31 #include <openssl/span.h>
32 
33 #include "../../ec_extra/internal.h"
34 #include "../../test/file_test.h"
35 #include "../../test/test_util.h"
36 #include "../bn/internal.h"
37 #include "internal.h"
38 
39 
40 // kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
41 // omitted.
42 static const uint8_t kECKeyWithoutPublic[] = {
43   0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0,
44   0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e,
45   0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
46   0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
47 };
48 
49 // kECKeySpecifiedCurve is the above key with P-256's parameters explicitly
50 // spelled out rather than using a named curve.
51 static const uint8_t kECKeySpecifiedCurve[] = {
52     0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa,
53     0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb,
54     0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc,
55     0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02,
56     0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
57     0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
58     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
60     0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
61     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
63     0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
64     0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
65     0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
66     0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
67     0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
68     0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
69     0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
70     0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
71     0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
72     0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
73     0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
74     0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
75     0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
76     0x63, 0x25, 0x51, 0x02, 0x01, 0x01,
77 };
78 
79 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
80 // the private key is one. The private key is incorrectly encoded without zero
81 // padding.
82 static const uint8_t kECKeyMissingZeros[] = {
83   0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a,
84   0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
85   0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
86   0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1,
87   0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f,
88   0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
89   0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
90 };
91 
92 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
93 // the private key is one. The private key is encoded with the required zero
94 // padding.
95 static const uint8_t kECKeyWithZeros[] = {
96   0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
99   0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1,
100   0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
101   0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d,
102   0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3,
103   0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e,
104   0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
105   0x37, 0xbf, 0x51, 0xf5,
106 };
107 
108 // DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
109 // result or nullptr on error.
DecodeECPrivateKey(const uint8_t * in,size_t in_len)110 static bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in,
111                                                   size_t in_len) {
112   CBS cbs;
113   CBS_init(&cbs, in, in_len);
114   bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL));
115   if (!ret || CBS_len(&cbs) != 0) {
116     return nullptr;
117   }
118   return ret;
119 }
120 
121 // EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
122 // returns true on success or false on error.
EncodeECPrivateKey(std::vector<uint8_t> * out,const EC_KEY * key)123 static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
124   bssl::ScopedCBB cbb;
125   uint8_t *der;
126   size_t der_len;
127   if (!CBB_init(cbb.get(), 0) ||
128       !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) ||
129       !CBB_finish(cbb.get(), &der, &der_len)) {
130     return false;
131   }
132   out->assign(der, der + der_len);
133   OPENSSL_free(der);
134   return true;
135 }
136 
EncodeECPoint(std::vector<uint8_t> * out,const EC_GROUP * group,const EC_POINT * p,point_conversion_form_t form)137 static bool EncodeECPoint(std::vector<uint8_t> *out, const EC_GROUP *group,
138                           const EC_POINT *p, point_conversion_form_t form) {
139   size_t len = EC_POINT_point2oct(group, p, form, nullptr, 0, nullptr);
140   if (len == 0) {
141     return false;
142   }
143 
144   out->resize(len);
145   len = EC_POINT_point2oct(group, p, form, out->data(), out->size(), nullptr);
146   if (len != out->size()) {
147     return false;
148   }
149 
150   return true;
151 }
152 
TEST(ECTest,Encoding)153 TEST(ECTest, Encoding) {
154   bssl::UniquePtr<EC_KEY> key =
155       DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
156   ASSERT_TRUE(key);
157 
158   // Test that the encoding round-trips.
159   std::vector<uint8_t> out;
160   ASSERT_TRUE(EncodeECPrivateKey(&out, key.get()));
161   EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
162 
163   const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
164   ASSERT_TRUE(pub_key) << "Public key missing";
165 
166   bssl::UniquePtr<BIGNUM> x(BN_new());
167   bssl::UniquePtr<BIGNUM> y(BN_new());
168   ASSERT_TRUE(x);
169   ASSERT_TRUE(y);
170   ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
171       EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL));
172   bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
173   bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
174   ASSERT_TRUE(x_hex);
175   ASSERT_TRUE(y_hex);
176 
177   EXPECT_STREQ(
178       "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681",
179       x_hex.get());
180   EXPECT_STREQ(
181       "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88",
182       y_hex.get());
183 }
184 
TEST(ECTest,ZeroPadding)185 TEST(ECTest, ZeroPadding) {
186   // Check that the correct encoding round-trips.
187   bssl::UniquePtr<EC_KEY> key =
188       DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros));
189   ASSERT_TRUE(key);
190   std::vector<uint8_t> out;
191   EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
192   EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
193 
194   // Keys without leading zeros also parse, but they encode correctly.
195   key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
196   ASSERT_TRUE(key);
197   EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
198   EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
199 }
200 
TEST(ECTest,SpecifiedCurve)201 TEST(ECTest, SpecifiedCurve) {
202   // Test keys with specified curves may be decoded.
203   bssl::UniquePtr<EC_KEY> key =
204       DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve));
205   ASSERT_TRUE(key);
206 
207   // The group should have been interpreted as P-256.
208   EXPECT_EQ(NID_X9_62_prime256v1,
209             EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())));
210 
211   // Encoding the key should still use named form.
212   std::vector<uint8_t> out;
213   EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
214   EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
215 }
216 
TEST(ECTest,ArbitraryCurve)217 TEST(ECTest, ArbitraryCurve) {
218   // Make a P-256 key and extract the affine coordinates.
219   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
220   ASSERT_TRUE(key);
221   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
222 
223   // Make an arbitrary curve which is identical to P-256.
224   static const uint8_t kP[] = {
225       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
226       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
227       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
228   };
229   static const uint8_t kA[] = {
230       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
231       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
232       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
233   };
234   static const uint8_t kB[] = {
235       0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
236       0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
237       0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
238   };
239   static const uint8_t kX[] = {
240       0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6,
241       0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb,
242       0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96,
243   };
244   static const uint8_t kY[] = {
245       0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
246       0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
247       0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
248   };
249   static const uint8_t kOrder[] = {
250       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
251       0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
252       0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
253   };
254   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
255   ASSERT_TRUE(ctx);
256   bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
257   ASSERT_TRUE(p);
258   bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
259   ASSERT_TRUE(a);
260   bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
261   ASSERT_TRUE(b);
262   bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr));
263   ASSERT_TRUE(gx);
264   bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr));
265   ASSERT_TRUE(gy);
266   bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
267   ASSERT_TRUE(order);
268 
269   bssl::UniquePtr<EC_GROUP> group(
270       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
271   ASSERT_TRUE(group);
272   bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
273   ASSERT_TRUE(generator);
274   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
275       group.get(), generator.get(), gx.get(), gy.get(), ctx.get()));
276   ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
277                                      BN_value_one()));
278 
279   // |group| should not have a curve name.
280   EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get()));
281 
282   // Copy |key| to |key2| using |group|.
283   bssl::UniquePtr<EC_KEY> key2(EC_KEY_new());
284   ASSERT_TRUE(key2);
285   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
286   ASSERT_TRUE(point);
287   bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
288   ASSERT_TRUE(x);
289   ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get()));
290   ASSERT_TRUE(
291       EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())));
292   ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
293       EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(),
294       y.get(), nullptr));
295   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(),
296                                                   x.get(), y.get(), nullptr));
297   ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get()));
298 
299   // The key must be valid according to the new group too.
300   EXPECT_TRUE(EC_KEY_check_key(key2.get()));
301 
302   // Make a second instance of |group|.
303   bssl::UniquePtr<EC_GROUP> group2(
304       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
305   ASSERT_TRUE(group2);
306   bssl::UniquePtr<EC_POINT> generator2(EC_POINT_new(group2.get()));
307   ASSERT_TRUE(generator2);
308   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
309       group2.get(), generator2.get(), gx.get(), gy.get(), ctx.get()));
310   ASSERT_TRUE(EC_GROUP_set_generator(group2.get(), generator2.get(),
311                                      order.get(), BN_value_one()));
312 
313   EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
314   EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), NULL));
315 
316   // group3 uses the wrong generator.
317   bssl::UniquePtr<EC_GROUP> group3(
318       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
319   ASSERT_TRUE(group3);
320   bssl::UniquePtr<EC_POINT> generator3(EC_POINT_new(group3.get()));
321   ASSERT_TRUE(generator3);
322   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
323       group3.get(), generator3.get(), x.get(), y.get(), ctx.get()));
324   ASSERT_TRUE(EC_GROUP_set_generator(group3.get(), generator3.get(),
325                                      order.get(), BN_value_one()));
326 
327   EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL));
328 
329 #if !defined(BORINGSSL_SHARED_LIBRARY)
330   // group4 has non-minimal components that do not fit in |EC_SCALAR| and the
331   // future |EC_FELEM|.
332   ASSERT_TRUE(bn_resize_words(p.get(), 32));
333   ASSERT_TRUE(bn_resize_words(a.get(), 32));
334   ASSERT_TRUE(bn_resize_words(b.get(), 32));
335   ASSERT_TRUE(bn_resize_words(gx.get(), 32));
336   ASSERT_TRUE(bn_resize_words(gy.get(), 32));
337   ASSERT_TRUE(bn_resize_words(order.get(), 32));
338 
339   bssl::UniquePtr<EC_GROUP> group4(
340       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
341   ASSERT_TRUE(group4);
342   bssl::UniquePtr<EC_POINT> generator4(EC_POINT_new(group4.get()));
343   ASSERT_TRUE(generator4);
344   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
345       group4.get(), generator4.get(), gx.get(), gy.get(), ctx.get()));
346   ASSERT_TRUE(EC_GROUP_set_generator(group4.get(), generator4.get(),
347                                      order.get(), BN_value_one()));
348 
349   EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group4.get(), NULL));
350 #endif
351 
352   // group5 is the same group, but the curve coefficients are passed in
353   // unreduced and the caller does not pass in a |BN_CTX|.
354   ASSERT_TRUE(BN_sub(a.get(), a.get(), p.get()));
355   ASSERT_TRUE(BN_add(b.get(), b.get(), p.get()));
356   bssl::UniquePtr<EC_GROUP> group5(
357       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), NULL));
358   ASSERT_TRUE(group5);
359   bssl::UniquePtr<EC_POINT> generator5(EC_POINT_new(group5.get()));
360   ASSERT_TRUE(generator5);
361   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
362       group5.get(), generator5.get(), gx.get(), gy.get(), ctx.get()));
363   ASSERT_TRUE(EC_GROUP_set_generator(group5.get(), generator5.get(),
364                                      order.get(), BN_value_one()));
365 
366   EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
367   EXPECT_EQ(0, EC_GROUP_cmp(group5.get(), group.get(), NULL));
368 }
369 
TEST(ECTest,SetKeyWithoutGroup)370 TEST(ECTest, SetKeyWithoutGroup) {
371   bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
372   ASSERT_TRUE(key);
373 
374   // Private keys may not be configured without a group.
375   EXPECT_FALSE(EC_KEY_set_private_key(key.get(), BN_value_one()));
376 
377   // Public keys may not be configured without a group.
378   bssl::UniquePtr<EC_GROUP> group(
379       EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
380   ASSERT_TRUE(group);
381   EXPECT_FALSE(
382       EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(group.get())));
383 }
384 
TEST(ECTest,SetNULLKey)385 TEST(ECTest, SetNULLKey) {
386   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
387   ASSERT_TRUE(key);
388 
389   EXPECT_TRUE(EC_KEY_set_public_key(
390       key.get(), EC_GROUP_get0_generator(EC_KEY_get0_group(key.get()))));
391   EXPECT_TRUE(EC_KEY_get0_public_key(key.get()));
392 
393   // Setting a NULL public-key should clear the public-key and return zero, in
394   // order to match OpenSSL behaviour exactly.
395   EXPECT_FALSE(EC_KEY_set_public_key(key.get(), nullptr));
396   EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
397 }
398 
TEST(ECTest,GroupMismatch)399 TEST(ECTest, GroupMismatch) {
400   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
401   ASSERT_TRUE(key);
402   bssl::UniquePtr<EC_GROUP> p256(
403       EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
404   ASSERT_TRUE(p256);
405 
406   // Changing a key's group is invalid.
407   EXPECT_FALSE(EC_KEY_set_group(key.get(), p256.get()));
408 
409   // Configuring a public key with the wrong group is invalid.
410   EXPECT_FALSE(
411       EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(p256.get())));
412 }
413 
TEST(ECTest,EmptyKey)414 TEST(ECTest, EmptyKey) {
415   bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
416   ASSERT_TRUE(key);
417   EXPECT_FALSE(EC_KEY_get0_group(key.get()));
418   EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
419   EXPECT_FALSE(EC_KEY_get0_private_key(key.get()));
420 }
421 
HexToBIGNUM(const char * hex)422 static bssl::UniquePtr<BIGNUM> HexToBIGNUM(const char *hex) {
423   BIGNUM *bn = nullptr;
424   BN_hex2bn(&bn, hex);
425   return bssl::UniquePtr<BIGNUM>(bn);
426 }
427 
428 // Test that point arithmetic works with custom curves using an arbitrary |a|,
429 // rather than -3, as is common (and more efficient).
TEST(ECTest,BrainpoolP256r1)430 TEST(ECTest, BrainpoolP256r1) {
431   static const char kP[] =
432       "a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377";
433   static const char kA[] =
434       "7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9";
435   static const char kB[] =
436       "26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6";
437   static const char kX[] =
438       "8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262";
439   static const char kY[] =
440       "547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997";
441   static const char kN[] =
442       "a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7";
443   static const char kD[] =
444       "0da21d76fed40dd82ac3314cce91abb585b5c4246e902b238a839609ea1e7ce1";
445   static const char kQX[] =
446       "3a55e0341cab50452fe27b8a87e4775dec7a9daca94b0d84ad1e9f85b53ea513";
447   static const char kQY[] =
448       "40088146b33bbbe81b092b41146774b35dd478cf056437cfb35ef0df2d269339";
449 
450   bssl::UniquePtr<BIGNUM> p = HexToBIGNUM(kP), a = HexToBIGNUM(kA),
451                           b = HexToBIGNUM(kB), x = HexToBIGNUM(kX),
452                           y = HexToBIGNUM(kY), n = HexToBIGNUM(kN),
453                           d = HexToBIGNUM(kD), qx = HexToBIGNUM(kQX),
454                           qy = HexToBIGNUM(kQY);
455   ASSERT_TRUE(p && a && b && x && y && n && d && qx && qy);
456 
457   bssl::UniquePtr<EC_GROUP> group(
458       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), nullptr));
459   ASSERT_TRUE(group);
460   bssl::UniquePtr<EC_POINT> g(EC_POINT_new(group.get()));
461   ASSERT_TRUE(g);
462   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), g.get(), x.get(),
463                                                   y.get(), nullptr));
464   ASSERT_TRUE(
465       EC_GROUP_set_generator(group.get(), g.get(), n.get(), BN_value_one()));
466 
467   bssl::UniquePtr<EC_POINT> q(EC_POINT_new(group.get()));
468   ASSERT_TRUE(q);
469   ASSERT_TRUE(
470       EC_POINT_mul(group.get(), q.get(), d.get(), nullptr, nullptr, nullptr));
471   ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(group.get(), q.get(), x.get(),
472                                                   y.get(), nullptr));
473   EXPECT_EQ(0, BN_cmp(x.get(), qx.get()));
474   EXPECT_EQ(0, BN_cmp(y.get(), qy.get()));
475 }
476 
477 class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {
478  public:
group() const479   const EC_GROUP *group() const { return group_.get(); }
480 
SetUp()481   void SetUp() override {
482     group_.reset(EC_GROUP_new_by_curve_name(GetParam().nid));
483     ASSERT_TRUE(group_);
484   }
485 
486  private:
487   bssl::UniquePtr<EC_GROUP> group_;
488 };
489 
TEST_P(ECCurveTest,SetAffine)490 TEST_P(ECCurveTest, SetAffine) {
491   // Generate an EC_KEY.
492   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
493   ASSERT_TRUE(key);
494   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
495 
496   // Get the public key's coordinates.
497   bssl::UniquePtr<BIGNUM> x(BN_new());
498   ASSERT_TRUE(x);
499   bssl::UniquePtr<BIGNUM> y(BN_new());
500   ASSERT_TRUE(y);
501   bssl::UniquePtr<BIGNUM> p(BN_new());
502   ASSERT_TRUE(p);
503   EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
504       group(), EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
505   EXPECT_TRUE(
506       EC_GROUP_get_curve_GFp(group(), p.get(), nullptr, nullptr, nullptr));
507 
508   // Points on the curve should be accepted.
509   auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group()));
510   ASSERT_TRUE(point);
511   EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group(), point.get(), x.get(),
512                                                   y.get(), nullptr));
513 
514   // Subtract one from |y| to make the point no longer on the curve.
515   EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one()));
516 
517   // Points not on the curve should be rejected.
518   bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group()));
519   ASSERT_TRUE(invalid_point);
520   EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
521                                                    x.get(), y.get(), nullptr));
522 
523   // Coordinates out of range should be rejected.
524   EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one()));
525   EXPECT_TRUE(BN_add(y.get(), y.get(), p.get()));
526 
527   EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
528                                                    x.get(), y.get(), nullptr));
529   EXPECT_FALSE(
530       EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
531 }
532 
TEST_P(ECCurveTest,IsOnCurve)533 TEST_P(ECCurveTest, IsOnCurve) {
534   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
535   ASSERT_TRUE(key);
536   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
537 
538   // The generated point is on the curve.
539   EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()),
540                                    nullptr));
541 
542   bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
543   ASSERT_TRUE(p);
544   ASSERT_TRUE(EC_POINT_copy(p.get(), EC_KEY_get0_public_key(key.get())));
545 
546   // This should never happen outside of a bug, but |EC_POINT_is_on_curve|
547   // rejects points not on the curve.
548   OPENSSL_memset(&p->raw.X, 0, sizeof(p->raw.X));
549   EXPECT_FALSE(EC_POINT_is_on_curve(group(), p.get(), nullptr));
550 
551   // The point at infinity is always on the curve.
552   ASSERT_TRUE(EC_POINT_copy(p.get(), EC_KEY_get0_public_key(key.get())));
553   OPENSSL_memset(&p->raw.Z, 0, sizeof(p->raw.Z));
554   EXPECT_TRUE(EC_POINT_is_on_curve(group(), p.get(), nullptr));
555 }
556 
TEST_P(ECCurveTest,Compare)557 TEST_P(ECCurveTest, Compare) {
558   bssl::UniquePtr<EC_KEY> key1(EC_KEY_new_by_curve_name(GetParam().nid));
559   ASSERT_TRUE(key1);
560   ASSERT_TRUE(EC_KEY_generate_key(key1.get()));
561   const EC_POINT *pub1 = EC_KEY_get0_public_key(key1.get());
562 
563   bssl::UniquePtr<EC_KEY> key2(EC_KEY_new_by_curve_name(GetParam().nid));
564   ASSERT_TRUE(key2);
565   ASSERT_TRUE(EC_KEY_generate_key(key2.get()));
566   const EC_POINT *pub2 = EC_KEY_get0_public_key(key2.get());
567 
568   // Two different points should not compare as equal.
569   EXPECT_EQ(1, EC_POINT_cmp(group(), pub1, pub2, nullptr));
570 
571   // Serialize |pub1| and parse it back out. This gives a point in affine
572   // coordinates.
573   std::vector<uint8_t> serialized;
574   ASSERT_TRUE(
575       EncodeECPoint(&serialized, group(), pub1, POINT_CONVERSION_UNCOMPRESSED));
576   bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
577   ASSERT_TRUE(p);
578   ASSERT_TRUE(EC_POINT_oct2point(group(), p.get(), serialized.data(),
579                                  serialized.size(), nullptr));
580 
581   // The points should be equal.
582   EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
583 
584   // Add something to the point. It no longer compares as equal.
585   ASSERT_TRUE(EC_POINT_add(group(), p.get(), p.get(), pub2, nullptr));
586   EXPECT_EQ(1, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
587 
588   // Negate |pub2|. It should no longer compare as equal. This tests that we
589   // check both x and y coordinate.
590   bssl::UniquePtr<EC_POINT> q(EC_POINT_new(group()));
591   ASSERT_TRUE(q);
592   ASSERT_TRUE(EC_POINT_copy(q.get(), pub2));
593   ASSERT_TRUE(EC_POINT_invert(group(), q.get(), nullptr));
594   EXPECT_EQ(1, EC_POINT_cmp(group(), q.get(), pub2, nullptr));
595 
596   // Return |p| to the original value. It should be equal to |pub1| again.
597   ASSERT_TRUE(EC_POINT_add(group(), p.get(), p.get(), q.get(), nullptr));
598   EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
599 
600   // Infinity compares as equal to itself, but not other points.
601   bssl::UniquePtr<EC_POINT> inf1(EC_POINT_new(group())),
602       inf2(EC_POINT_new(group()));
603   ASSERT_TRUE(inf1);
604   ASSERT_TRUE(EC_POINT_set_to_infinity(group(), inf1.get()));
605   // |q| is currently -|pub2|.
606   ASSERT_TRUE(EC_POINT_add(group(), inf2.get(), pub2, q.get(), nullptr));
607   EXPECT_EQ(0, EC_POINT_cmp(group(), inf1.get(), inf2.get(), nullptr));
608   EXPECT_EQ(1, EC_POINT_cmp(group(), inf1.get(), p.get(), nullptr));
609 }
610 
TEST_P(ECCurveTest,GenerateFIPS)611 TEST_P(ECCurveTest, GenerateFIPS) {
612   // Generate an EC_KEY.
613   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
614   ASSERT_TRUE(key);
615   ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()));
616 }
617 
TEST_P(ECCurveTest,AddingEqualPoints)618 TEST_P(ECCurveTest, AddingEqualPoints) {
619   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
620   ASSERT_TRUE(key);
621   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
622 
623   bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group()));
624   ASSERT_TRUE(p1);
625   ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
626 
627   bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group()));
628   ASSERT_TRUE(p2);
629   ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
630 
631   bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group()));
632   ASSERT_TRUE(double_p1);
633   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
634   ASSERT_TRUE(ctx);
635   ASSERT_TRUE(EC_POINT_dbl(group(), double_p1.get(), p1.get(), ctx.get()));
636 
637   bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group()));
638   ASSERT_TRUE(p1_plus_p2);
639   ASSERT_TRUE(
640       EC_POINT_add(group(), p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
641 
642   EXPECT_EQ(0,
643             EC_POINT_cmp(group(), double_p1.get(), p1_plus_p2.get(), ctx.get()))
644       << "A+A != 2A";
645 }
646 
TEST_P(ECCurveTest,MulZero)647 TEST_P(ECCurveTest, MulZero) {
648   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
649   ASSERT_TRUE(point);
650   bssl::UniquePtr<BIGNUM> zero(BN_new());
651   ASSERT_TRUE(zero);
652   BN_zero(zero.get());
653   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), zero.get(), nullptr, nullptr,
654                            nullptr));
655 
656   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
657       << "g * 0 did not return point at infinity.";
658 
659   // Test that zero times an arbitrary point is also infinity. The generator is
660   // used as the arbitrary point.
661   bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group()));
662   ASSERT_TRUE(generator);
663   ASSERT_TRUE(EC_POINT_mul(group(), generator.get(), BN_value_one(), nullptr,
664                            nullptr, nullptr));
665   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, generator.get(),
666                            zero.get(), nullptr));
667 
668   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
669       << "p * 0 did not return point at infinity.";
670 }
671 
672 // Test that multiplying by the order produces ∞ and, moreover, that callers may
673 // do so. |EC_POINT_mul| is almost exclusively used with reduced scalars, with
674 // this exception. This comes from consumers following NIST SP 800-56A section
675 // 5.6.2.3.2. (Though all our curves have cofactor one, so this check isn't
676 // useful.)
TEST_P(ECCurveTest,MulOrder)677 TEST_P(ECCurveTest, MulOrder) {
678   // Test that g × order = ∞.
679   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
680   ASSERT_TRUE(point);
681   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), EC_GROUP_get0_order(group()),
682                            nullptr, nullptr, nullptr));
683 
684   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
685       << "g * order did not return point at infinity.";
686 
687   // Test that p × order = ∞, for some arbitrary p.
688   bssl::UniquePtr<BIGNUM> forty_two(BN_new());
689   ASSERT_TRUE(forty_two);
690   ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
691   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
692                            nullptr, nullptr));
693   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, point.get(),
694                            EC_GROUP_get0_order(group()), nullptr));
695 
696   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
697       << "p * order did not return point at infinity.";
698 }
699 
700 // Test that |EC_POINT_mul| works with out-of-range scalars. The operation will
701 // not be constant-time, but we'll compute the right answer.
TEST_P(ECCurveTest,MulOutOfRange)702 TEST_P(ECCurveTest, MulOutOfRange) {
703   bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(EC_GROUP_get0_order(group())));
704   ASSERT_TRUE(n_minus_one);
705   ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1));
706 
707   bssl::UniquePtr<BIGNUM> minus_one(BN_new());
708   ASSERT_TRUE(minus_one);
709   ASSERT_TRUE(BN_one(minus_one.get()));
710   BN_set_negative(minus_one.get(), 1);
711 
712   bssl::UniquePtr<BIGNUM> seven(BN_new());
713   ASSERT_TRUE(seven);
714   ASSERT_TRUE(BN_set_word(seven.get(), 7));
715 
716   bssl::UniquePtr<BIGNUM> ten_n_plus_seven(
717       BN_dup(EC_GROUP_get0_order(group())));
718   ASSERT_TRUE(ten_n_plus_seven);
719   ASSERT_TRUE(BN_mul_word(ten_n_plus_seven.get(), 10));
720   ASSERT_TRUE(BN_add_word(ten_n_plus_seven.get(), 7));
721 
722   bssl::UniquePtr<EC_POINT> point1(EC_POINT_new(group())),
723       point2(EC_POINT_new(group()));
724   ASSERT_TRUE(point1);
725   ASSERT_TRUE(point2);
726 
727   ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), n_minus_one.get(), nullptr,
728                            nullptr, nullptr));
729   ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), minus_one.get(), nullptr,
730                            nullptr, nullptr));
731   EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
732       << "-1 * G and (n-1) * G did not give the same result";
733 
734   ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), seven.get(), nullptr, nullptr,
735                            nullptr));
736   ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), ten_n_plus_seven.get(),
737                            nullptr, nullptr, nullptr));
738   EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
739       << "7 * G and (10n + 7) * G did not give the same result";
740 }
741 
742 // Test that 10×∞ + G = G.
TEST_P(ECCurveTest,Mul)743 TEST_P(ECCurveTest, Mul) {
744   bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
745   ASSERT_TRUE(p);
746   bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group()));
747   ASSERT_TRUE(result);
748   bssl::UniquePtr<BIGNUM> n(BN_new());
749   ASSERT_TRUE(n);
750   ASSERT_TRUE(EC_POINT_set_to_infinity(group(), p.get()));
751   ASSERT_TRUE(BN_set_word(n.get(), 10));
752 
753   // First check that 10×∞ = ∞.
754   ASSERT_TRUE(
755       EC_POINT_mul(group(), result.get(), nullptr, p.get(), n.get(), nullptr));
756   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), result.get()));
757 
758   // Now check that 10×∞ + G = G.
759   const EC_POINT *generator = EC_GROUP_get0_generator(group());
760   ASSERT_TRUE(EC_POINT_mul(group(), result.get(), BN_value_one(), p.get(),
761                            n.get(), nullptr));
762   EXPECT_EQ(0, EC_POINT_cmp(group(), result.get(), generator, nullptr));
763 }
764 
TEST_P(ECCurveTest,MulNonMinimal)765 TEST_P(ECCurveTest, MulNonMinimal) {
766   bssl::UniquePtr<BIGNUM> forty_two(BN_new());
767   ASSERT_TRUE(forty_two);
768   ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
769 
770   // Compute g × 42.
771   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
772   ASSERT_TRUE(point);
773   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
774                            nullptr, nullptr));
775 
776   // Compute it again with a non-minimal 42, much larger than the scalar.
777   ASSERT_TRUE(bn_resize_words(forty_two.get(), 64));
778 
779   bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group()));
780   ASSERT_TRUE(point2);
781   ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), forty_two.get(), nullptr,
782                            nullptr, nullptr));
783   EXPECT_EQ(0, EC_POINT_cmp(group(), point.get(), point2.get(), nullptr));
784 }
785 
786 // Test that EC_KEY_set_private_key rejects invalid values.
TEST_P(ECCurveTest,SetInvalidPrivateKey)787 TEST_P(ECCurveTest, SetInvalidPrivateKey) {
788   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
789   ASSERT_TRUE(key);
790 
791   bssl::UniquePtr<BIGNUM> bn(BN_new());
792   ASSERT_TRUE(BN_one(bn.get()));
793   BN_set_negative(bn.get(), 1);
794   EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
795       << "Unexpectedly set a key of -1";
796   ERR_clear_error();
797 
798   ASSERT_TRUE(
799       BN_copy(bn.get(), EC_GROUP_get0_order(EC_KEY_get0_group(key.get()))));
800   EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
801       << "Unexpectedly set a key of the group order.";
802   ERR_clear_error();
803 }
804 
TEST_P(ECCurveTest,IgnoreOct2PointReturnValue)805 TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
806   bssl::UniquePtr<BIGNUM> forty_two(BN_new());
807   ASSERT_TRUE(forty_two);
808   ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
809 
810   // Compute g × 42.
811   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
812   ASSERT_TRUE(point);
813   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
814                            nullptr, nullptr));
815 
816   // Serialize the point.
817   std::vector<uint8_t> serialized;
818   ASSERT_TRUE(EncodeECPoint(&serialized, group(), point.get(),
819                             POINT_CONVERSION_UNCOMPRESSED));
820 
821   // Create a serialized point that is not on the curve.
822   serialized[serialized.size() - 1]++;
823 
824   ASSERT_FALSE(EC_POINT_oct2point(group(), point.get(), serialized.data(),
825                                   serialized.size(), nullptr));
826   // After a failure, |point| should have been set to the generator to defend
827   // against code that doesn't check the return value.
828   ASSERT_EQ(0, EC_POINT_cmp(group(), point.get(),
829                             EC_GROUP_get0_generator(group()), nullptr));
830 }
831 
TEST_P(ECCurveTest,DoubleSpecialCase)832 TEST_P(ECCurveTest, DoubleSpecialCase) {
833   const EC_POINT *g = EC_GROUP_get0_generator(group());
834 
835   bssl::UniquePtr<EC_POINT> two_g(EC_POINT_new(group()));
836   ASSERT_TRUE(two_g);
837   ASSERT_TRUE(EC_POINT_dbl(group(), two_g.get(), g, nullptr));
838 
839   bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
840   ASSERT_TRUE(p);
841   ASSERT_TRUE(EC_POINT_mul(group(), p.get(), BN_value_one(), g, BN_value_one(),
842                            nullptr));
843   EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
844 
845   EC_SCALAR one;
846   ASSERT_TRUE(ec_bignum_to_scalar(group(), &one, BN_value_one()));
847   ASSERT_TRUE(
848       ec_point_mul_scalar_public(group(), &p->raw, &one, &g->raw, &one));
849   EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
850 }
851 
852 // This a regression test for a P-224 bug, but we may as well run it for all
853 // curves.
TEST_P(ECCurveTest,P224Bug)854 TEST_P(ECCurveTest, P224Bug) {
855   // P = -G
856   const EC_POINT *g = EC_GROUP_get0_generator(group());
857   bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group()));
858   ASSERT_TRUE(p);
859   ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr));
860 
861   // Compute 31 * P + 32 * G = G
862   bssl::UniquePtr<EC_POINT> ret(EC_POINT_new(group()));
863   ASSERT_TRUE(ret);
864   bssl::UniquePtr<BIGNUM> bn31(BN_new()), bn32(BN_new());
865   ASSERT_TRUE(bn31);
866   ASSERT_TRUE(bn32);
867   ASSERT_TRUE(BN_set_word(bn31.get(), 31));
868   ASSERT_TRUE(BN_set_word(bn32.get(), 32));
869   ASSERT_TRUE(EC_POINT_mul(group(), ret.get(), bn32.get(), p.get(), bn31.get(),
870                            nullptr));
871   EXPECT_EQ(0, EC_POINT_cmp(group(), ret.get(), g, nullptr));
872 
873   // Repeat the computation with |ec_point_mul_scalar_public|, which ties the
874   // additions together.
875   EC_SCALAR sc31, sc32;
876   ASSERT_TRUE(ec_bignum_to_scalar(group(), &sc31, bn31.get()));
877   ASSERT_TRUE(ec_bignum_to_scalar(group(), &sc32, bn32.get()));
878   ASSERT_TRUE(
879       ec_point_mul_scalar_public(group(), &ret->raw, &sc32, &p->raw, &sc31));
880   EXPECT_EQ(0, EC_POINT_cmp(group(), ret.get(), g, nullptr));
881 }
882 
TEST_P(ECCurveTest,GPlusMinusG)883 TEST_P(ECCurveTest, GPlusMinusG) {
884   const EC_POINT *g = EC_GROUP_get0_generator(group());
885   bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group()));
886   ASSERT_TRUE(p);
887   ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr));
888   bssl::UniquePtr<EC_POINT> sum(EC_POINT_new(group()));
889 
890   ASSERT_TRUE(EC_POINT_add(group(), sum.get(), g, p.get(), nullptr));
891   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), sum.get()));
892 }
893 
AllCurves()894 static std::vector<EC_builtin_curve> AllCurves() {
895   const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
896   std::vector<EC_builtin_curve> curves(num_curves);
897   EC_get_builtin_curves(curves.data(), num_curves);
898   return curves;
899 }
900 
CurveToString(const testing::TestParamInfo<EC_builtin_curve> & params)901 static std::string CurveToString(
902     const testing::TestParamInfo<EC_builtin_curve> &params) {
903   // The comment field contains characters GTest rejects, so use the OBJ name.
904   return OBJ_nid2sn(params.param.nid);
905 }
906 
907 INSTANTIATE_TEST_SUITE_P(All, ECCurveTest, testing::ValuesIn(AllCurves()),
908                          CurveToString);
909 
GetCurve(FileTest * t,const char * key)910 static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) {
911   std::string curve_name;
912   if (!t->GetAttribute(&curve_name, key)) {
913     return nullptr;
914   }
915 
916   if (curve_name == "P-224") {
917     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp224r1));
918   }
919   if (curve_name == "P-256") {
920     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(
921         NID_X9_62_prime256v1));
922   }
923   if (curve_name == "P-384") {
924     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp384r1));
925   }
926   if (curve_name == "P-521") {
927     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp521r1));
928   }
929 
930   t->PrintLine("Unknown curve '%s'", curve_name.c_str());
931   return nullptr;
932 }
933 
GetBIGNUM(FileTest * t,const char * key)934 static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) {
935   std::vector<uint8_t> bytes;
936   if (!t->GetBytes(&bytes, key)) {
937     return nullptr;
938   }
939 
940   return bssl::UniquePtr<BIGNUM>(
941       BN_bin2bn(bytes.data(), bytes.size(), nullptr));
942 }
943 
TEST(ECTest,ScalarBaseMultVectors)944 TEST(ECTest, ScalarBaseMultVectors) {
945   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
946   ASSERT_TRUE(ctx);
947 
948   FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
949                 [&](FileTest *t) {
950     bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
951     ASSERT_TRUE(group);
952     bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N");
953     ASSERT_TRUE(n);
954     bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
955     ASSERT_TRUE(x);
956     bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
957     ASSERT_TRUE(y);
958     bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get());
959 
960     bssl::UniquePtr<BIGNUM> px(BN_new());
961     ASSERT_TRUE(px);
962     bssl::UniquePtr<BIGNUM> py(BN_new());
963     ASSERT_TRUE(py);
964     auto check_point = [&](const EC_POINT *p) {
965       if (is_infinity) {
966         EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), p));
967       } else {
968         ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
969             group.get(), p, px.get(), py.get(), ctx.get()));
970         EXPECT_EQ(0, BN_cmp(x.get(), px.get()));
971         EXPECT_EQ(0, BN_cmp(y.get(), py.get()));
972       }
973     };
974 
975     const EC_POINT *g = EC_GROUP_get0_generator(group.get());
976     bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
977     ASSERT_TRUE(p);
978     // Test single-point multiplication.
979     ASSERT_TRUE(EC_POINT_mul(group.get(), p.get(), n.get(), nullptr, nullptr,
980                              ctx.get()));
981     check_point(p.get());
982 
983     ASSERT_TRUE(
984         EC_POINT_mul(group.get(), p.get(), nullptr, g, n.get(), ctx.get()));
985     check_point(p.get());
986   });
987 }
988 
989 // These tests take a very long time, but are worth running when we make
990 // non-trivial changes to the EC code.
TEST(ECTest,DISABLED_ScalarBaseMultVectorsTwoPoint)991 TEST(ECTest, DISABLED_ScalarBaseMultVectorsTwoPoint) {
992   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
993   ASSERT_TRUE(ctx);
994 
995   FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
996                 [&](FileTest *t) {
997     bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
998     ASSERT_TRUE(group);
999     bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N");
1000     ASSERT_TRUE(n);
1001     bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
1002     ASSERT_TRUE(x);
1003     bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
1004     ASSERT_TRUE(y);
1005     bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get());
1006 
1007     bssl::UniquePtr<BIGNUM> px(BN_new());
1008     ASSERT_TRUE(px);
1009     bssl::UniquePtr<BIGNUM> py(BN_new());
1010     ASSERT_TRUE(py);
1011     auto check_point = [&](const EC_POINT *p) {
1012       if (is_infinity) {
1013         EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), p));
1014       } else {
1015         ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
1016             group.get(), p, px.get(), py.get(), ctx.get()));
1017         EXPECT_EQ(0, BN_cmp(x.get(), px.get()));
1018         EXPECT_EQ(0, BN_cmp(y.get(), py.get()));
1019       }
1020     };
1021 
1022     const EC_POINT *g = EC_GROUP_get0_generator(group.get());
1023     bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
1024     ASSERT_TRUE(p);
1025     bssl::UniquePtr<BIGNUM> a(BN_new()), b(BN_new());
1026     for (int i = -64; i < 64; i++) {
1027       SCOPED_TRACE(i);
1028       ASSERT_TRUE(BN_set_word(a.get(), abs(i)));
1029       if (i < 0) {
1030         ASSERT_TRUE(BN_sub(a.get(), EC_GROUP_get0_order(group.get()), a.get()));
1031       }
1032 
1033       ASSERT_TRUE(BN_copy(b.get(), n.get()));
1034       ASSERT_TRUE(BN_sub(b.get(), b.get(), a.get()));
1035       if (BN_is_negative(b.get())) {
1036         ASSERT_TRUE(BN_add(b.get(), b.get(), EC_GROUP_get0_order(group.get())));
1037       }
1038 
1039       ASSERT_TRUE(
1040           EC_POINT_mul(group.get(), p.get(), a.get(), g, b.get(), ctx.get()));
1041       check_point(p.get());
1042 
1043       EC_SCALAR a_scalar, b_scalar;
1044       ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &a_scalar, a.get()));
1045       ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &b_scalar, b.get()));
1046       ASSERT_TRUE(ec_point_mul_scalar_public(group.get(), &p->raw, &a_scalar,
1047                                              &g->raw, &b_scalar));
1048       check_point(p.get());
1049     }
1050   });
1051 }
1052 
HexToBytes(const char * str)1053 static std::vector<uint8_t> HexToBytes(const char *str) {
1054   std::vector<uint8_t> ret;
1055   if (!DecodeHex(&ret, str)) {
1056     abort();
1057   }
1058   return ret;
1059 }
1060 
TEST(ECTest,DeriveFromSecret)1061 TEST(ECTest, DeriveFromSecret) {
1062   struct DeriveTest {
1063     int curve;
1064     std::vector<uint8_t> secret;
1065     std::vector<uint8_t> expected_priv;
1066     std::vector<uint8_t> expected_pub;
1067   };
1068   const DeriveTest kDeriveTests[] = {
1069       {NID_X9_62_prime256v1, HexToBytes(""),
1070        HexToBytes(
1071            "b98a86a71efb51ebdac4759937b977e9b0c05224675bb2b6a58ba306e237f4b8"),
1072        HexToBytes(
1073            "04fbe6cab439918e00231a2ff073cdc25823998864a9eb36f809095a1a919ece875"
1074            "a145803fbe89a6cde53936e3c6d9c253ed3d38f5f58cae455c27e95645ceda9")},
1075       {NID_X9_62_prime256v1, HexToBytes("123456"),
1076        HexToBytes(
1077            "44a72bc62087b88e5ab7126766177ed0d8f1ed09ad066cd746527fc201105a7e"),
1078        HexToBytes(
1079            "04ec0555cd76e991fef7f5504343937d0f38696db3360a4854052cb0d84a377a5a0"
1080            "ff64c352755c28692b4ae085c2b817db9a1eddbd22e9cf39c12751e0870791b")},
1081       {NID_X9_62_prime256v1, HexToBytes("00000000000000000000000000000000"),
1082        HexToBytes(
1083            "7ca1e2c83e6a5f2c1b3e7d58180226f269930c4b9fbe2a275096079630b7c57d"),
1084        HexToBytes(
1085            "0442ef70c8fc0fbe383ed0a0da36f39f9a590f3feebc07863cc858c9a8ef0465731"
1086            "0408c249bd4d61929c54b71ffe056e6b4fa1eb537039b43d1c175f0ceab0f89")},
1087       {NID_X9_62_prime256v1,
1088        HexToBytes(
1089            "de9c9b35543aaa0fba039e34e8ca9695da3225c7161c9e3a8c70356cac28c780"),
1090        HexToBytes(
1091            "659f5abf3b62b9931c29d6ed0722efd2349fa56f54e708cf3272f620f1bc44d0"),
1092        HexToBytes(
1093            "046741f806b593bf3a3d4a9d76bdcb9b0d7874633cbea8f42c05e78561f7e8ec362"
1094            "b9b6f1913ded796fbdafe7f210cea897ac22a4e580c06a60f2659fd09f1830f")},
1095       {NID_secp384r1, HexToBytes("123456"),
1096        HexToBytes("95cd90d548997de090c7622708eccb7edc1b1bd78d2422235ad97406dada"
1097                   "076555309da200096f6e4b36c46002beee89"),
1098        HexToBytes(
1099            "04007b2d026aa7636fa912c3f970d62bb6c10fa81c8f3290ed90b2d701696d1c6b9"
1100            "5af88ce13e962996a7ac37e16527cb5d69bd081b8641d07634cf84b438600ec9434"
1101            "15ac6bd7a0236f7ab0ea31ece67df03fa11646ea2b75e73d1b5e45b75c18")},
1102   };
1103 
1104   for (const auto &test : kDeriveTests) {
1105     SCOPED_TRACE(Bytes(test.secret));
1106     bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(test.curve));
1107     ASSERT_TRUE(group);
1108     bssl::UniquePtr<EC_KEY> key(EC_KEY_derive_from_secret(
1109         group.get(), test.secret.data(), test.secret.size()));
1110     ASSERT_TRUE(key);
1111 
1112     std::vector<uint8_t> priv(BN_num_bytes(EC_GROUP_get0_order(group.get())));
1113     ASSERT_TRUE(BN_bn2bin_padded(priv.data(), priv.size(),
1114                                  EC_KEY_get0_private_key(key.get())));
1115     EXPECT_EQ(Bytes(priv), Bytes(test.expected_priv));
1116 
1117     uint8_t *pub = nullptr;
1118     size_t pub_len =
1119         EC_KEY_key2buf(key.get(), POINT_CONVERSION_UNCOMPRESSED, &pub, nullptr);
1120     bssl::UniquePtr<uint8_t> free_pub(pub);
1121     EXPECT_NE(pub_len, 0u);
1122     EXPECT_EQ(Bytes(pub, pub_len), Bytes(test.expected_pub));
1123   }
1124 }
1125 
TEST(ECTest,HashToCurve)1126 TEST(ECTest, HashToCurve) {
1127   struct HashToCurveTest {
1128     int (*hash_to_curve)(const EC_GROUP *group, EC_RAW_POINT *out,
1129                          const uint8_t *dst, size_t dst_len, const uint8_t *msg,
1130                          size_t msg_len);
1131     int curve_nid;
1132     const char *dst;
1133     const char *msg;
1134     const char *x_hex;
1135     const char *y_hex;
1136   };
1137   static const HashToCurveTest kTests[] = {
1138       // See draft-irtf-cfrg-hash-to-curve-07, appendix G.2.1.
1139       {&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
1140        "P384_XMD:SHA-512_SSWU_RO_TESTGEN", "",
1141        "2fc0b9efdd63a8e43b4db88dc12f03c798f6fd91bccac0c9096185"
1142        "4386e58fdc54fc2a01f0f358759054ce1f9b762025",
1143        "949b936fabb72cdb02cd7980b86cb6a3adf286658e81301648851d"
1144        "b8a49d9bec00ccb57698d559fc5960fa5030a8e54b"},
1145       {&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
1146        "P384_XMD:SHA-512_SSWU_RO_TESTGEN", "abc",
1147        "4f3338035391e8ce8ce40c974136f0edc97f392ffd44a643338741"
1148        "8ed1b8c2603487e1688ec151f048fbc6b2c138c92f",
1149        "152b90aef6558be328a3168855fb1906452e7167b0f7c8a56ff9d4"
1150        "fa87d6fb522cdf8e409db54418b2c764fd26260757"},
1151       {&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
1152        "P384_XMD:SHA-512_SSWU_RO_TESTGEN", "abcdef0123456789",
1153        "e9e5d7ac397e123d060ad44301cbc8eb972f6e64ebcff29dcc9b9a"
1154        "10357902aace2240c580fec85e5b427d98b4e80703",
1155        "916cb8963521ad75105be43cc4148e5a5bbb4fcf107f1577e4f7fa"
1156        "3ca58cd786aa76890c8e687d2353393bc16c78ec4d"},
1157       {&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
1158        "P384_XMD:SHA-512_SSWU_RO_TESTGEN",
1159        "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1160        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1161        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1162        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1163        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1164        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1165        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1166        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1167        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1168        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1169        "41941db59a7b8b633bd5bfa462f1e29a9f18e5a341445d90fc6eb9"
1170        "37f2913224287b9dfb64742851f760eb14ca115ff9",
1171        "1510e764f1be968d661b7aaecb26a6d38c98e5205ca150f0ae426d"
1172        "2c3983c68e3a9ffb283c6ae4891d891b5705500475"},
1173   };
1174 
1175   for (const auto &test : kTests) {
1176     SCOPED_TRACE(test.dst);
1177     SCOPED_TRACE(test.msg);
1178 
1179     bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(test.curve_nid));
1180     ASSERT_TRUE(group);
1181     bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
1182     ASSERT_TRUE(p);
1183     ASSERT_TRUE(test.hash_to_curve(
1184         group.get(), &p->raw, reinterpret_cast<const uint8_t *>(test.dst),
1185         strlen(test.dst), reinterpret_cast<const uint8_t *>(test.msg),
1186         strlen(test.msg)));
1187 
1188     std::vector<uint8_t> buf;
1189     ASSERT_TRUE(EncodeECPoint(&buf, group.get(), p.get(),
1190                               POINT_CONVERSION_UNCOMPRESSED));
1191     size_t field_len = (buf.size() - 1) / 2;
1192     EXPECT_EQ(test.x_hex,
1193               EncodeHex(bssl::MakeConstSpan(buf).subspan(1, field_len)));
1194     EXPECT_EQ(test.y_hex, EncodeHex(bssl::MakeConstSpan(buf).subspan(
1195                               1 + field_len, field_len)));
1196   }
1197 
1198   // hash-to-curve functions should check for the wrong group.
1199   bssl::UniquePtr<EC_GROUP> p224(EC_GROUP_new_by_curve_name(NID_secp224r1));
1200   ASSERT_TRUE(p224);
1201   EC_RAW_POINT p;
1202   static const uint8_t kDST[] = {0, 1, 2, 3};
1203   static const uint8_t kMessage[] = {4, 5, 6, 7};
1204   EXPECT_FALSE(ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
1205       p224.get(), &p, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
1206 }
1207 
TEST(ECTest,HashToScalar)1208 TEST(ECTest, HashToScalar) {
1209   struct HashToScalarTest {
1210     int (*hash_to_scalar)(const EC_GROUP *group, EC_SCALAR *out,
1211                           const uint8_t *dst, size_t dst_len,
1212                           const uint8_t *msg, size_t msg_len);
1213     int curve_nid;
1214     const char *dst;
1215     const char *msg;
1216     const char *result_hex;
1217   };
1218   static const HashToScalarTest kTests[] = {
1219       {&ec_hash_to_scalar_p384_xmd_sha512_draft07, NID_secp384r1,
1220        "P384_XMD:SHA-512_SCALAR_TEST", "",
1221        "9687acc2de56c3cf94c0e05b6811a21aa480092254ec0532bdce63"
1222        "140ecd340f09dc2d45d77e21fb0aa76f7707b8a676"},
1223       {&ec_hash_to_scalar_p384_xmd_sha512_draft07, NID_secp384r1,
1224        "P384_XMD:SHA-512_SCALAR_TEST", "abcdef0123456789",
1225        "8f8076022a68233cbcecaceae68c2068f132724f001caa78619eff"
1226        "1ffc58fa871db73fe9034fc9cf853c384ed34b5666"},
1227       {&ec_hash_to_scalar_p384_xmd_sha512_draft07, NID_secp384r1,
1228        "P384_XMD:SHA-512_SCALAR_TEST",
1229        "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1230        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1231        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1232        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1233        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1234        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1235        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1236        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1237        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1238        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1239        "750f2fae7d2b2f41ac737d180c1d4363d85a1504798b4976d40921"
1240        "1ddb3651c13a5b4daba9975cdfce18336791131915"},
1241   };
1242 
1243   for (const auto &test : kTests) {
1244     SCOPED_TRACE(test.dst);
1245     SCOPED_TRACE(test.msg);
1246 
1247     bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(test.curve_nid));
1248     ASSERT_TRUE(group);
1249     EC_SCALAR scalar;
1250     ASSERT_TRUE(test.hash_to_scalar(
1251         group.get(), &scalar, reinterpret_cast<const uint8_t *>(test.dst),
1252         strlen(test.dst), reinterpret_cast<const uint8_t *>(test.msg),
1253         strlen(test.msg)));
1254     uint8_t buf[EC_MAX_BYTES];
1255     size_t len;
1256     ec_scalar_to_bytes(group.get(), buf, &len, &scalar);
1257     EXPECT_EQ(test.result_hex, EncodeHex(bssl::MakeConstSpan(buf, len)));
1258   }
1259 
1260   // hash-to-scalar functions should check for the wrong group.
1261   bssl::UniquePtr<EC_GROUP> p224(EC_GROUP_new_by_curve_name(NID_secp224r1));
1262   ASSERT_TRUE(p224);
1263   EC_SCALAR scalar;
1264   static const uint8_t kDST[] = {0, 1, 2, 3};
1265   static const uint8_t kMessage[] = {4, 5, 6, 7};
1266   EXPECT_FALSE(ec_hash_to_scalar_p384_xmd_sha512_draft07(
1267       p224.get(), &scalar, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
1268 }
1269