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