• 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 
32 #include "../../test/file_test.h"
33 #include "../../test/test_util.h"
34 #include "../bn/internal.h"
35 #include "internal.h"
36 
37 
38 // kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
39 // omitted.
40 static const uint8_t kECKeyWithoutPublic[] = {
41   0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0,
42   0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e,
43   0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
44   0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
45 };
46 
47 // kECKeySpecifiedCurve is the above key with P-256's parameters explicitly
48 // spelled out rather than using a named curve.
49 static const uint8_t kECKeySpecifiedCurve[] = {
50     0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa,
51     0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb,
52     0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc,
53     0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02,
54     0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
55     0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
56     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
58     0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
59     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
61     0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
62     0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
63     0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
64     0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
65     0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
66     0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
67     0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
68     0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
69     0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
70     0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
71     0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
72     0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
73     0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
74     0x63, 0x25, 0x51, 0x02, 0x01, 0x01,
75 };
76 
77 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
78 // the private key is one. The private key is incorrectly encoded without zero
79 // padding.
80 static const uint8_t kECKeyMissingZeros[] = {
81   0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a,
82   0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
83   0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
84   0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1,
85   0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f,
86   0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
87   0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
88 };
89 
90 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
91 // the private key is one. The private key is encoded with the required zero
92 // padding.
93 static const uint8_t kECKeyWithZeros[] = {
94   0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
97   0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1,
98   0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
99   0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d,
100   0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3,
101   0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e,
102   0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
103   0x37, 0xbf, 0x51, 0xf5,
104 };
105 
106 // DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
107 // result or nullptr on error.
DecodeECPrivateKey(const uint8_t * in,size_t in_len)108 static bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in,
109                                                   size_t in_len) {
110   CBS cbs;
111   CBS_init(&cbs, in, in_len);
112   bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL));
113   if (!ret || CBS_len(&cbs) != 0) {
114     return nullptr;
115   }
116   return ret;
117 }
118 
119 // EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
120 // returns true on success or false on error.
EncodeECPrivateKey(std::vector<uint8_t> * out,const EC_KEY * key)121 static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
122   bssl::ScopedCBB cbb;
123   uint8_t *der;
124   size_t der_len;
125   if (!CBB_init(cbb.get(), 0) ||
126       !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) ||
127       !CBB_finish(cbb.get(), &der, &der_len)) {
128     return false;
129   }
130   out->assign(der, der + der_len);
131   OPENSSL_free(der);
132   return true;
133 }
134 
TEST(ECTest,Encoding)135 TEST(ECTest, Encoding) {
136   bssl::UniquePtr<EC_KEY> key =
137       DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
138   ASSERT_TRUE(key);
139 
140   // Test that the encoding round-trips.
141   std::vector<uint8_t> out;
142   ASSERT_TRUE(EncodeECPrivateKey(&out, key.get()));
143   EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
144 
145   const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
146   ASSERT_TRUE(pub_key) << "Public key missing";
147 
148   bssl::UniquePtr<BIGNUM> x(BN_new());
149   bssl::UniquePtr<BIGNUM> y(BN_new());
150   ASSERT_TRUE(x);
151   ASSERT_TRUE(y);
152   ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
153       EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL));
154   bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
155   bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
156   ASSERT_TRUE(x_hex);
157   ASSERT_TRUE(y_hex);
158 
159   EXPECT_STREQ(
160       "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681",
161       x_hex.get());
162   EXPECT_STREQ(
163       "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88",
164       y_hex.get());
165 }
166 
TEST(ECTest,ZeroPadding)167 TEST(ECTest, ZeroPadding) {
168   // Check that the correct encoding round-trips.
169   bssl::UniquePtr<EC_KEY> key =
170       DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros));
171   ASSERT_TRUE(key);
172   std::vector<uint8_t> out;
173   EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
174   EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
175 
176   // Keys without leading zeros also parse, but they encode correctly.
177   key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
178   ASSERT_TRUE(key);
179   EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
180   EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
181 }
182 
TEST(ECTest,SpecifiedCurve)183 TEST(ECTest, SpecifiedCurve) {
184   // Test keys with specified curves may be decoded.
185   bssl::UniquePtr<EC_KEY> key =
186       DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve));
187   ASSERT_TRUE(key);
188 
189   // The group should have been interpreted as P-256.
190   EXPECT_EQ(NID_X9_62_prime256v1,
191             EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())));
192 
193   // Encoding the key should still use named form.
194   std::vector<uint8_t> out;
195   EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
196   EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
197 }
198 
TEST(ECTest,ArbitraryCurve)199 TEST(ECTest, ArbitraryCurve) {
200   // Make a P-256 key and extract the affine coordinates.
201   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
202   ASSERT_TRUE(key);
203   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
204 
205   // Make an arbitrary curve which is identical to P-256.
206   static const uint8_t kP[] = {
207       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
208       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
209       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
210   };
211   static const uint8_t kA[] = {
212       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
213       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
214       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
215   };
216   static const uint8_t kB[] = {
217       0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
218       0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
219       0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
220   };
221   static const uint8_t kX[] = {
222       0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6,
223       0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb,
224       0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96,
225   };
226   static const uint8_t kY[] = {
227       0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
228       0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
229       0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
230   };
231   static const uint8_t kOrder[] = {
232       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
233       0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
234       0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
235   };
236   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
237   ASSERT_TRUE(ctx);
238   bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
239   ASSERT_TRUE(p);
240   bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
241   ASSERT_TRUE(a);
242   bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
243   ASSERT_TRUE(b);
244   bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr));
245   ASSERT_TRUE(gx);
246   bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr));
247   ASSERT_TRUE(gy);
248   bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
249   ASSERT_TRUE(order);
250 
251   bssl::UniquePtr<EC_GROUP> group(
252       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
253   ASSERT_TRUE(group);
254   bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
255   ASSERT_TRUE(generator);
256   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
257       group.get(), generator.get(), gx.get(), gy.get(), ctx.get()));
258   ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
259                                      BN_value_one()));
260 
261   // |group| should not have a curve name.
262   EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get()));
263 
264   // Copy |key| to |key2| using |group|.
265   bssl::UniquePtr<EC_KEY> key2(EC_KEY_new());
266   ASSERT_TRUE(key2);
267   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
268   ASSERT_TRUE(point);
269   bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
270   ASSERT_TRUE(x);
271   ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get()));
272   ASSERT_TRUE(
273       EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())));
274   ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
275       EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(),
276       y.get(), nullptr));
277   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(),
278                                                   x.get(), y.get(), nullptr));
279   ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get()));
280 
281   // The key must be valid according to the new group too.
282   EXPECT_TRUE(EC_KEY_check_key(key2.get()));
283 
284   // Make a second instance of |group|.
285   bssl::UniquePtr<EC_GROUP> group2(
286       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
287   ASSERT_TRUE(group2);
288   bssl::UniquePtr<EC_POINT> generator2(EC_POINT_new(group2.get()));
289   ASSERT_TRUE(generator2);
290   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
291       group2.get(), generator2.get(), gx.get(), gy.get(), ctx.get()));
292   ASSERT_TRUE(EC_GROUP_set_generator(group2.get(), generator2.get(),
293                                      order.get(), BN_value_one()));
294 
295   EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
296   EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), NULL));
297 
298   // group3 uses the wrong generator.
299   bssl::UniquePtr<EC_GROUP> group3(
300       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
301   ASSERT_TRUE(group3);
302   bssl::UniquePtr<EC_POINT> generator3(EC_POINT_new(group3.get()));
303   ASSERT_TRUE(generator3);
304   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
305       group3.get(), generator3.get(), x.get(), y.get(), ctx.get()));
306   ASSERT_TRUE(EC_GROUP_set_generator(group3.get(), generator3.get(),
307                                      order.get(), BN_value_one()));
308 
309   EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL));
310 
311 #if !defined(BORINGSSL_SHARED_LIBRARY)
312   // group4 has non-minimal components that do not fit in |EC_SCALAR| and the
313   // future |EC_FELEM|.
314   ASSERT_TRUE(bn_resize_words(p.get(), 32));
315   ASSERT_TRUE(bn_resize_words(a.get(), 32));
316   ASSERT_TRUE(bn_resize_words(b.get(), 32));
317   ASSERT_TRUE(bn_resize_words(gx.get(), 32));
318   ASSERT_TRUE(bn_resize_words(gy.get(), 32));
319   ASSERT_TRUE(bn_resize_words(order.get(), 32));
320 
321   bssl::UniquePtr<EC_GROUP> group4(
322       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
323   ASSERT_TRUE(group4);
324   bssl::UniquePtr<EC_POINT> generator4(EC_POINT_new(group4.get()));
325   ASSERT_TRUE(generator4);
326   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
327       group4.get(), generator4.get(), gx.get(), gy.get(), ctx.get()));
328   ASSERT_TRUE(EC_GROUP_set_generator(group4.get(), generator4.get(),
329                                      order.get(), BN_value_one()));
330 
331   EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group4.get(), NULL));
332 #endif
333 }
334 
TEST(ECTest,SetKeyWithoutGroup)335 TEST(ECTest, SetKeyWithoutGroup) {
336   bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
337   ASSERT_TRUE(key);
338 
339   // Private keys may not be configured without a group.
340   EXPECT_FALSE(EC_KEY_set_private_key(key.get(), BN_value_one()));
341 
342   // Public keys may not be configured without a group.
343   bssl::UniquePtr<EC_GROUP> group(
344       EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
345   ASSERT_TRUE(group);
346   EXPECT_FALSE(
347       EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(group.get())));
348 }
349 
TEST(ECTest,SetNULLKey)350 TEST(ECTest, SetNULLKey) {
351   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
352   ASSERT_TRUE(key);
353 
354   EXPECT_TRUE(EC_KEY_set_public_key(
355       key.get(), EC_GROUP_get0_generator(EC_KEY_get0_group(key.get()))));
356   EXPECT_TRUE(EC_KEY_get0_public_key(key.get()));
357 
358   // Setting a NULL public-key should clear the public-key and return zero, in
359   // order to match OpenSSL behaviour exactly.
360   EXPECT_FALSE(EC_KEY_set_public_key(key.get(), nullptr));
361   EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
362 }
363 
TEST(ECTest,GroupMismatch)364 TEST(ECTest, GroupMismatch) {
365   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
366   ASSERT_TRUE(key);
367   bssl::UniquePtr<EC_GROUP> p256(
368       EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
369   ASSERT_TRUE(p256);
370 
371   // Changing a key's group is invalid.
372   EXPECT_FALSE(EC_KEY_set_group(key.get(), p256.get()));
373 
374   // Configuring a public key with the wrong group is invalid.
375   EXPECT_FALSE(
376       EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(p256.get())));
377 }
378 
TEST(ECTest,EmptyKey)379 TEST(ECTest, EmptyKey) {
380   bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
381   ASSERT_TRUE(key);
382   EXPECT_FALSE(EC_KEY_get0_group(key.get()));
383   EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
384   EXPECT_FALSE(EC_KEY_get0_private_key(key.get()));
385 }
386 
HexToBIGNUM(const char * hex)387 static bssl::UniquePtr<BIGNUM> HexToBIGNUM(const char *hex) {
388   BIGNUM *bn = nullptr;
389   BN_hex2bn(&bn, hex);
390   return bssl::UniquePtr<BIGNUM>(bn);
391 }
392 
393 // Test that point arithmetic works with custom curves using an arbitrary |a|,
394 // rather than -3, as is common (and more efficient).
TEST(ECTest,BrainpoolP256r1)395 TEST(ECTest, BrainpoolP256r1) {
396   static const char kP[] =
397       "a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377";
398   static const char kA[] =
399       "7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9";
400   static const char kB[] =
401       "26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6";
402   static const char kX[] =
403       "8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262";
404   static const char kY[] =
405       "547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997";
406   static const char kN[] =
407       "a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7";
408   static const char kD[] =
409       "0da21d76fed40dd82ac3314cce91abb585b5c4246e902b238a839609ea1e7ce1";
410   static const char kQX[] =
411       "3a55e0341cab50452fe27b8a87e4775dec7a9daca94b0d84ad1e9f85b53ea513";
412   static const char kQY[] =
413       "40088146b33bbbe81b092b41146774b35dd478cf056437cfb35ef0df2d269339";
414 
415   bssl::UniquePtr<BIGNUM> p = HexToBIGNUM(kP), a = HexToBIGNUM(kA),
416                           b = HexToBIGNUM(kB), x = HexToBIGNUM(kX),
417                           y = HexToBIGNUM(kY), n = HexToBIGNUM(kN),
418                           d = HexToBIGNUM(kD), qx = HexToBIGNUM(kQX),
419                           qy = HexToBIGNUM(kQY);
420   ASSERT_TRUE(p && a && b && x && y && n && d && qx && qy);
421 
422   bssl::UniquePtr<EC_GROUP> group(
423       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), nullptr));
424   ASSERT_TRUE(group);
425   bssl::UniquePtr<EC_POINT> g(EC_POINT_new(group.get()));
426   ASSERT_TRUE(g);
427   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), g.get(), x.get(),
428                                                   y.get(), nullptr));
429   ASSERT_TRUE(
430       EC_GROUP_set_generator(group.get(), g.get(), n.get(), BN_value_one()));
431 
432   bssl::UniquePtr<EC_POINT> q(EC_POINT_new(group.get()));
433   ASSERT_TRUE(q);
434   ASSERT_TRUE(
435       EC_POINT_mul(group.get(), q.get(), d.get(), nullptr, nullptr, nullptr));
436   ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(group.get(), q.get(), x.get(),
437                                                   y.get(), nullptr));
438   EXPECT_EQ(0, BN_cmp(x.get(), qx.get()));
439   EXPECT_EQ(0, BN_cmp(y.get(), qy.get()));
440 }
441 
442 class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {
443  public:
group() const444   const EC_GROUP *group() const { return group_.get(); }
445 
SetUp()446   void SetUp() override {
447     group_.reset(EC_GROUP_new_by_curve_name(GetParam().nid));
448     ASSERT_TRUE(group_);
449   }
450 
451  private:
452   bssl::UniquePtr<EC_GROUP> group_;
453 };
454 
TEST_P(ECCurveTest,SetAffine)455 TEST_P(ECCurveTest, SetAffine) {
456   // Generate an EC_KEY.
457   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
458   ASSERT_TRUE(key);
459   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
460 
461   EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()),
462                                    nullptr));
463 
464   // Get the public key's coordinates.
465   bssl::UniquePtr<BIGNUM> x(BN_new());
466   ASSERT_TRUE(x);
467   bssl::UniquePtr<BIGNUM> y(BN_new());
468   ASSERT_TRUE(y);
469   bssl::UniquePtr<BIGNUM> p(BN_new());
470   ASSERT_TRUE(p);
471   EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
472       group(), EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
473   EXPECT_TRUE(
474       EC_GROUP_get_curve_GFp(group(), p.get(), nullptr, nullptr, nullptr));
475 
476   // Points on the curve should be accepted.
477   auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group()));
478   ASSERT_TRUE(point);
479   EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group(), point.get(), x.get(),
480                                                   y.get(), nullptr));
481 
482   // Subtract one from |y| to make the point no longer on the curve.
483   EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one()));
484 
485   // Points not on the curve should be rejected.
486   bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group()));
487   ASSERT_TRUE(invalid_point);
488   EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
489                                                    x.get(), y.get(), nullptr));
490 
491   // Coordinates out of range should be rejected.
492   EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one()));
493   EXPECT_TRUE(BN_add(y.get(), y.get(), p.get()));
494 
495   EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
496                                                    x.get(), y.get(), nullptr));
497   EXPECT_FALSE(
498       EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
499 }
500 
TEST_P(ECCurveTest,GenerateFIPS)501 TEST_P(ECCurveTest, GenerateFIPS) {
502   // Generate an EC_KEY.
503   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
504   ASSERT_TRUE(key);
505   ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()));
506 }
507 
TEST_P(ECCurveTest,AddingEqualPoints)508 TEST_P(ECCurveTest, AddingEqualPoints) {
509   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
510   ASSERT_TRUE(key);
511   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
512 
513   bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group()));
514   ASSERT_TRUE(p1);
515   ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
516 
517   bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group()));
518   ASSERT_TRUE(p2);
519   ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
520 
521   bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group()));
522   ASSERT_TRUE(double_p1);
523   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
524   ASSERT_TRUE(ctx);
525   ASSERT_TRUE(EC_POINT_dbl(group(), double_p1.get(), p1.get(), ctx.get()));
526 
527   bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group()));
528   ASSERT_TRUE(p1_plus_p2);
529   ASSERT_TRUE(
530       EC_POINT_add(group(), p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
531 
532   EXPECT_EQ(0,
533             EC_POINT_cmp(group(), double_p1.get(), p1_plus_p2.get(), ctx.get()))
534       << "A+A != 2A";
535 }
536 
TEST_P(ECCurveTest,MulZero)537 TEST_P(ECCurveTest, MulZero) {
538   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
539   ASSERT_TRUE(point);
540   bssl::UniquePtr<BIGNUM> zero(BN_new());
541   ASSERT_TRUE(zero);
542   BN_zero(zero.get());
543   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), zero.get(), nullptr, nullptr,
544                            nullptr));
545 
546   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
547       << "g * 0 did not return point at infinity.";
548 
549   // Test that zero times an arbitrary point is also infinity. The generator is
550   // used as the arbitrary point.
551   bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group()));
552   ASSERT_TRUE(generator);
553   ASSERT_TRUE(EC_POINT_mul(group(), generator.get(), BN_value_one(), nullptr,
554                            nullptr, nullptr));
555   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, generator.get(),
556                            zero.get(), nullptr));
557 
558   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
559       << "p * 0 did not return point at infinity.";
560 }
561 
562 // Test that multiplying by the order produces ∞ and, moreover, that callers may
563 // do so. |EC_POINT_mul| is almost exclusively used with reduced scalars, with
564 // this exception. This comes from consumers following NIST SP 800-56A section
565 // 5.6.2.3.2. (Though all our curves have cofactor one, so this check isn't
566 // useful.)
TEST_P(ECCurveTest,MulOrder)567 TEST_P(ECCurveTest, MulOrder) {
568   // Test that g × order = ∞.
569   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
570   ASSERT_TRUE(point);
571   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), EC_GROUP_get0_order(group()),
572                            nullptr, nullptr, nullptr));
573 
574   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
575       << "g * order did not return point at infinity.";
576 
577   // Test that p × order = ∞, for some arbitrary p.
578   bssl::UniquePtr<BIGNUM> forty_two(BN_new());
579   ASSERT_TRUE(forty_two);
580   ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
581   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
582                            nullptr, nullptr));
583   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, point.get(),
584                            EC_GROUP_get0_order(group()), nullptr));
585 
586   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
587       << "p * order did not return point at infinity.";
588 }
589 
590 // Test that |EC_POINT_mul| works with out-of-range scalars. The operation will
591 // not be constant-time, but we'll compute the right answer.
TEST_P(ECCurveTest,MulOutOfRange)592 TEST_P(ECCurveTest, MulOutOfRange) {
593   bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(EC_GROUP_get0_order(group())));
594   ASSERT_TRUE(n_minus_one);
595   ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1));
596 
597   bssl::UniquePtr<BIGNUM> minus_one(BN_new());
598   ASSERT_TRUE(minus_one);
599   ASSERT_TRUE(BN_one(minus_one.get()));
600   BN_set_negative(minus_one.get(), 1);
601 
602   bssl::UniquePtr<BIGNUM> seven(BN_new());
603   ASSERT_TRUE(seven);
604   ASSERT_TRUE(BN_set_word(seven.get(), 7));
605 
606   bssl::UniquePtr<BIGNUM> ten_n_plus_seven(
607       BN_dup(EC_GROUP_get0_order(group())));
608   ASSERT_TRUE(ten_n_plus_seven);
609   ASSERT_TRUE(BN_mul_word(ten_n_plus_seven.get(), 10));
610   ASSERT_TRUE(BN_add_word(ten_n_plus_seven.get(), 7));
611 
612   bssl::UniquePtr<EC_POINT> point1(EC_POINT_new(group())),
613       point2(EC_POINT_new(group()));
614   ASSERT_TRUE(point1);
615   ASSERT_TRUE(point2);
616 
617   ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), n_minus_one.get(), nullptr,
618                            nullptr, nullptr));
619   ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), minus_one.get(), nullptr,
620                            nullptr, nullptr));
621   EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
622       << "-1 * G and (n-1) * G did not give the same result";
623 
624   ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), seven.get(), nullptr, nullptr,
625                            nullptr));
626   ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), ten_n_plus_seven.get(),
627                            nullptr, nullptr, nullptr));
628   EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
629       << "7 * G and (10n + 7) * G did not give the same result";
630 }
631 
632 // Test that 10×∞ + G = G.
TEST_P(ECCurveTest,Mul)633 TEST_P(ECCurveTest, Mul) {
634   bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
635   ASSERT_TRUE(p);
636   bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group()));
637   ASSERT_TRUE(result);
638   bssl::UniquePtr<BIGNUM> n(BN_new());
639   ASSERT_TRUE(n);
640   ASSERT_TRUE(EC_POINT_set_to_infinity(group(), p.get()));
641   ASSERT_TRUE(BN_set_word(n.get(), 10));
642 
643   // First check that 10×∞ = ∞.
644   ASSERT_TRUE(
645       EC_POINT_mul(group(), result.get(), nullptr, p.get(), n.get(), nullptr));
646   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), result.get()));
647 
648   // Now check that 10×∞ + G = G.
649   const EC_POINT *generator = EC_GROUP_get0_generator(group());
650   ASSERT_TRUE(EC_POINT_mul(group(), result.get(), BN_value_one(), p.get(),
651                            n.get(), nullptr));
652   EXPECT_EQ(0, EC_POINT_cmp(group(), result.get(), generator, nullptr));
653 }
654 
TEST_P(ECCurveTest,MulNonMinimal)655 TEST_P(ECCurveTest, MulNonMinimal) {
656   bssl::UniquePtr<BIGNUM> forty_two(BN_new());
657   ASSERT_TRUE(forty_two);
658   ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
659 
660   // Compute g × 42.
661   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
662   ASSERT_TRUE(point);
663   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
664                            nullptr, nullptr));
665 
666   // Compute it again with a non-minimal 42, much larger than the scalar.
667   ASSERT_TRUE(bn_resize_words(forty_two.get(), 64));
668 
669   bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group()));
670   ASSERT_TRUE(point2);
671   ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), forty_two.get(), nullptr,
672                            nullptr, nullptr));
673   EXPECT_EQ(0, EC_POINT_cmp(group(), point.get(), point2.get(), nullptr));
674 }
675 
676 // Test that EC_KEY_set_private_key rejects invalid values.
TEST_P(ECCurveTest,SetInvalidPrivateKey)677 TEST_P(ECCurveTest, SetInvalidPrivateKey) {
678   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
679   ASSERT_TRUE(key);
680 
681   bssl::UniquePtr<BIGNUM> bn(BN_new());
682   ASSERT_TRUE(BN_one(bn.get()));
683   BN_set_negative(bn.get(), 1);
684   EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
685       << "Unexpectedly set a key of -1";
686   ERR_clear_error();
687 
688   ASSERT_TRUE(
689       BN_copy(bn.get(), EC_GROUP_get0_order(EC_KEY_get0_group(key.get()))));
690   EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
691       << "Unexpectedly set a key of the group order.";
692   ERR_clear_error();
693 }
694 
TEST_P(ECCurveTest,IgnoreOct2PointReturnValue)695 TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
696   bssl::UniquePtr<BIGNUM> forty_two(BN_new());
697   ASSERT_TRUE(forty_two);
698   ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
699 
700   // Compute g × 42.
701   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
702   ASSERT_TRUE(point);
703   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
704                            nullptr, nullptr));
705 
706   // Serialize the point.
707   size_t serialized_len = EC_POINT_point2oct(
708       group(), point.get(), POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
709   ASSERT_NE(0u, serialized_len);
710 
711   std::vector<uint8_t> serialized(serialized_len);
712   ASSERT_EQ(
713       serialized_len,
714       EC_POINT_point2oct(group(), point.get(), POINT_CONVERSION_UNCOMPRESSED,
715                          serialized.data(), serialized_len, nullptr));
716 
717   // Create a serialized point that is not on the curve.
718   serialized[serialized_len - 1]++;
719 
720   ASSERT_FALSE(EC_POINT_oct2point(group(), point.get(), serialized.data(),
721                                   serialized.size(), nullptr));
722   // After a failure, |point| should have been set to the generator to defend
723   // against code that doesn't check the return value.
724   ASSERT_EQ(0, EC_POINT_cmp(group(), point.get(),
725                             EC_GROUP_get0_generator(group()), nullptr));
726 }
727 
TEST_P(ECCurveTest,DoubleSpecialCase)728 TEST_P(ECCurveTest, DoubleSpecialCase) {
729   const EC_POINT *g = EC_GROUP_get0_generator(group());
730 
731   bssl::UniquePtr<EC_POINT> two_g(EC_POINT_new(group()));
732   ASSERT_TRUE(two_g);
733   ASSERT_TRUE(EC_POINT_dbl(group(), two_g.get(), g, nullptr));
734 
735   bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
736   ASSERT_TRUE(p);
737   ASSERT_TRUE(EC_POINT_mul(group(), p.get(), BN_value_one(), g, BN_value_one(),
738                            nullptr));
739   EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
740 
741   EC_SCALAR one;
742   ASSERT_TRUE(ec_bignum_to_scalar(group(), &one, BN_value_one()));
743   ASSERT_TRUE(
744       ec_point_mul_scalar_public(group(), &p->raw, &one, &g->raw, &one));
745   EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
746 }
747 
748 // This a regression test for a P-224 bug, but we may as well run it for all
749 // curves.
TEST_P(ECCurveTest,P224Bug)750 TEST_P(ECCurveTest, P224Bug) {
751   // P = -G
752   const EC_POINT *g = EC_GROUP_get0_generator(group());
753   bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group()));
754   ASSERT_TRUE(p);
755   ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr));
756 
757   // Compute 31 * P + 32 * G = G
758   bssl::UniquePtr<EC_POINT> ret(EC_POINT_new(group()));
759   ASSERT_TRUE(ret);
760   bssl::UniquePtr<BIGNUM> bn31(BN_new()), bn32(BN_new());
761   ASSERT_TRUE(bn31);
762   ASSERT_TRUE(bn32);
763   ASSERT_TRUE(BN_set_word(bn31.get(), 31));
764   ASSERT_TRUE(BN_set_word(bn32.get(), 32));
765   ASSERT_TRUE(EC_POINT_mul(group(), ret.get(), bn32.get(), p.get(), bn31.get(),
766                            nullptr));
767 
768   EXPECT_EQ(0, EC_POINT_cmp(group(), ret.get(), g, nullptr));
769 }
770 
TEST_P(ECCurveTest,GPlusMinusG)771 TEST_P(ECCurveTest, GPlusMinusG) {
772   const EC_POINT *g = EC_GROUP_get0_generator(group());
773   bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group()));
774   ASSERT_TRUE(p);
775   ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr));
776   bssl::UniquePtr<EC_POINT> sum(EC_POINT_new(group()));
777 
778   ASSERT_TRUE(EC_POINT_add(group(), sum.get(), g, p.get(), nullptr));
779   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), sum.get()));
780 }
781 
AllCurves()782 static std::vector<EC_builtin_curve> AllCurves() {
783   const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
784   std::vector<EC_builtin_curve> curves(num_curves);
785   EC_get_builtin_curves(curves.data(), num_curves);
786   return curves;
787 }
788 
CurveToString(const testing::TestParamInfo<EC_builtin_curve> & params)789 static std::string CurveToString(
790     const testing::TestParamInfo<EC_builtin_curve> &params) {
791   // The comment field contains characters GTest rejects, so use the OBJ name.
792   return OBJ_nid2sn(params.param.nid);
793 }
794 
795 INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
796                         CurveToString);
797 
GetCurve(FileTest * t,const char * key)798 static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) {
799   std::string curve_name;
800   if (!t->GetAttribute(&curve_name, key)) {
801     return nullptr;
802   }
803 
804   if (curve_name == "P-224") {
805     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp224r1));
806   }
807   if (curve_name == "P-256") {
808     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(
809         NID_X9_62_prime256v1));
810   }
811   if (curve_name == "P-384") {
812     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp384r1));
813   }
814   if (curve_name == "P-521") {
815     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp521r1));
816   }
817 
818   t->PrintLine("Unknown curve '%s'", curve_name.c_str());
819   return nullptr;
820 }
821 
GetBIGNUM(FileTest * t,const char * key)822 static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) {
823   std::vector<uint8_t> bytes;
824   if (!t->GetBytes(&bytes, key)) {
825     return nullptr;
826   }
827 
828   return bssl::UniquePtr<BIGNUM>(
829       BN_bin2bn(bytes.data(), bytes.size(), nullptr));
830 }
831 
TEST(ECTest,ScalarBaseMultVectors)832 TEST(ECTest, ScalarBaseMultVectors) {
833   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
834   ASSERT_TRUE(ctx);
835 
836   FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
837                 [&](FileTest *t) {
838     bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
839     ASSERT_TRUE(group);
840     bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N");
841     ASSERT_TRUE(n);
842     bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
843     ASSERT_TRUE(x);
844     bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
845     ASSERT_TRUE(y);
846     bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get());
847 
848     bssl::UniquePtr<BIGNUM> px(BN_new());
849     ASSERT_TRUE(px);
850     bssl::UniquePtr<BIGNUM> py(BN_new());
851     ASSERT_TRUE(py);
852     auto check_point = [&](const EC_POINT *p) {
853       if (is_infinity) {
854         EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), p));
855       } else {
856         ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
857             group.get(), p, px.get(), py.get(), ctx.get()));
858         EXPECT_EQ(0, BN_cmp(x.get(), px.get()));
859         EXPECT_EQ(0, BN_cmp(y.get(), py.get()));
860       }
861     };
862 
863     const EC_POINT *g = EC_GROUP_get0_generator(group.get());
864     bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
865     ASSERT_TRUE(p);
866     // Test single-point multiplication.
867     ASSERT_TRUE(EC_POINT_mul(group.get(), p.get(), n.get(), nullptr, nullptr,
868                              ctx.get()));
869     check_point(p.get());
870 
871     ASSERT_TRUE(
872         EC_POINT_mul(group.get(), p.get(), nullptr, g, n.get(), ctx.get()));
873     check_point(p.get());
874 
875     // These tests take a very long time, but are worth running when we make
876     // non-trivial changes to the EC code.
877 #if 0
878     // Test two-point multiplication.
879     bssl::UniquePtr<BIGNUM> a(BN_new()), b(BN_new());
880     for (int i = -64; i < 64; i++) {
881       SCOPED_TRACE(i);
882       ASSERT_TRUE(BN_set_word(a.get(), abs(i)));
883       if (i < 0) {
884         ASSERT_TRUE(BN_sub(a.get(), EC_GROUP_get0_order(group.get()), a.get()));
885       }
886 
887       ASSERT_TRUE(BN_copy(b.get(), n.get()));
888       ASSERT_TRUE(BN_sub(b.get(), b.get(), a.get()));
889       if (BN_is_negative(b.get())) {
890         ASSERT_TRUE(BN_add(b.get(), b.get(), EC_GROUP_get0_order(group.get())));
891       }
892 
893       ASSERT_TRUE(
894           EC_POINT_mul(group.get(), p.get(), a.get(), g, b.get(), ctx.get()));
895       check_point(p.get());
896 
897       EC_SCALAR a_scalar, b_scalar;
898       ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &a_scalar, a.get()));
899       ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &b_scalar, b.get()));
900       ASSERT_TRUE(ec_point_mul_scalar_public(group.get(), &p->raw, &a_scalar, &g->raw,
901                                              &b_scalar));
902       check_point(p.get());
903     }
904 #endif
905   });
906 }
907