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> ¶ms) {
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