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