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 EXPECT_FALSE(EC_KEY_set_public_key(key.get(),
434 EC_GROUP_get0_generator(EC_group_p256())));
435 }
436
TEST(ECTest,SetNULLKey)437 TEST(ECTest, SetNULLKey) {
438 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
439 ASSERT_TRUE(key);
440
441 EXPECT_TRUE(EC_KEY_set_public_key(
442 key.get(), EC_GROUP_get0_generator(EC_KEY_get0_group(key.get()))));
443 EXPECT_TRUE(EC_KEY_get0_public_key(key.get()));
444
445 // Setting a NULL public-key should clear the public-key and return zero, in
446 // order to match OpenSSL behaviour exactly.
447 EXPECT_FALSE(EC_KEY_set_public_key(key.get(), nullptr));
448 EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
449 }
450
TEST(ECTest,GroupMismatch)451 TEST(ECTest, GroupMismatch) {
452 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
453 ASSERT_TRUE(key);
454
455 // Changing a key's group is invalid.
456 EXPECT_FALSE(EC_KEY_set_group(key.get(), EC_group_p256()));
457
458 // Configuring a public key with the wrong group is invalid.
459 EXPECT_FALSE(EC_KEY_set_public_key(key.get(),
460 EC_GROUP_get0_generator(EC_group_p256())));
461 }
462
TEST(ECTest,EmptyKey)463 TEST(ECTest, EmptyKey) {
464 bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
465 ASSERT_TRUE(key);
466 EXPECT_FALSE(EC_KEY_get0_group(key.get()));
467 EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
468 EXPECT_FALSE(EC_KEY_get0_private_key(key.get()));
469 }
470
HexToBIGNUM(const char * hex)471 static bssl::UniquePtr<BIGNUM> HexToBIGNUM(const char *hex) {
472 BIGNUM *bn = nullptr;
473 BN_hex2bn(&bn, hex);
474 return bssl::UniquePtr<BIGNUM>(bn);
475 }
476
477 // Test that point arithmetic works with custom curves using an arbitrary |a|,
478 // rather than -3, as is common (and more efficient).
TEST(ECTest,BrainpoolP256r1)479 TEST(ECTest, BrainpoolP256r1) {
480 static const char kP[] =
481 "a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377";
482 static const char kA[] =
483 "7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9";
484 static const char kB[] =
485 "26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6";
486 static const char kX[] =
487 "8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262";
488 static const char kY[] =
489 "547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997";
490 static const char kN[] =
491 "a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7";
492 static const char kD[] =
493 "0da21d76fed40dd82ac3314cce91abb585b5c4246e902b238a839609ea1e7ce1";
494 static const char kQX[] =
495 "3a55e0341cab50452fe27b8a87e4775dec7a9daca94b0d84ad1e9f85b53ea513";
496 static const char kQY[] =
497 "40088146b33bbbe81b092b41146774b35dd478cf056437cfb35ef0df2d269339";
498
499 bssl::UniquePtr<BIGNUM> p = HexToBIGNUM(kP), a = HexToBIGNUM(kA),
500 b = HexToBIGNUM(kB), x = HexToBIGNUM(kX),
501 y = HexToBIGNUM(kY), n = HexToBIGNUM(kN),
502 d = HexToBIGNUM(kD), qx = HexToBIGNUM(kQX),
503 qy = HexToBIGNUM(kQY);
504 ASSERT_TRUE(p && a && b && x && y && n && d && qx && qy);
505
506 bssl::UniquePtr<EC_GROUP> group(
507 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), nullptr));
508 ASSERT_TRUE(group);
509 bssl::UniquePtr<EC_POINT> g(EC_POINT_new(group.get()));
510 ASSERT_TRUE(g);
511 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), g.get(), x.get(),
512 y.get(), nullptr));
513 ASSERT_TRUE(
514 EC_GROUP_set_generator(group.get(), g.get(), n.get(), BN_value_one()));
515
516 bssl::UniquePtr<EC_POINT> q(EC_POINT_new(group.get()));
517 ASSERT_TRUE(q);
518 ASSERT_TRUE(
519 EC_POINT_mul(group.get(), q.get(), d.get(), nullptr, nullptr, nullptr));
520 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(group.get(), q.get(), x.get(),
521 y.get(), nullptr));
522 EXPECT_EQ(0, BN_cmp(x.get(), qx.get()));
523 EXPECT_EQ(0, BN_cmp(y.get(), qy.get()));
524 }
525
526 class ECCurveTest : public testing::TestWithParam<int> {
527 public:
group() const528 const EC_GROUP *group() const { return group_; }
529
SetUp()530 void SetUp() override {
531 group_ = EC_GROUP_new_by_curve_name(GetParam());
532 ASSERT_TRUE(group_);
533 }
534
535 private:
536 const EC_GROUP *group_;
537 };
538
TEST_P(ECCurveTest,SetAffine)539 TEST_P(ECCurveTest, SetAffine) {
540 // Generate an EC_KEY.
541 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam()));
542 ASSERT_TRUE(key);
543 ASSERT_TRUE(EC_KEY_generate_key(key.get()));
544
545 // Get the public key's coordinates.
546 bssl::UniquePtr<BIGNUM> x(BN_new());
547 ASSERT_TRUE(x);
548 bssl::UniquePtr<BIGNUM> y(BN_new());
549 ASSERT_TRUE(y);
550 bssl::UniquePtr<BIGNUM> p(BN_new());
551 ASSERT_TRUE(p);
552 EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
553 group(), EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
554 EXPECT_TRUE(
555 EC_GROUP_get_curve_GFp(group(), p.get(), nullptr, nullptr, nullptr));
556
557 // Points on the curve should be accepted.
558 auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group()));
559 ASSERT_TRUE(point);
560 EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group(), point.get(), x.get(),
561 y.get(), nullptr));
562
563 // Subtract one from |y| to make the point no longer on the curve.
564 EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one()));
565
566 // Points not on the curve should be rejected.
567 bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group()));
568 ASSERT_TRUE(invalid_point);
569 EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
570 x.get(), y.get(), nullptr));
571
572 // Coordinates out of range should be rejected.
573 EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one()));
574 EXPECT_TRUE(BN_add(y.get(), y.get(), p.get()));
575
576 EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
577 x.get(), y.get(), nullptr));
578 EXPECT_FALSE(
579 EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
580 }
581
TEST_P(ECCurveTest,IsOnCurve)582 TEST_P(ECCurveTest, IsOnCurve) {
583 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam()));
584 ASSERT_TRUE(key);
585 ASSERT_TRUE(EC_KEY_generate_key(key.get()));
586
587 // The generated point is on the curve.
588 EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()),
589 nullptr));
590
591 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
592 ASSERT_TRUE(p);
593 ASSERT_TRUE(EC_POINT_copy(p.get(), EC_KEY_get0_public_key(key.get())));
594
595 // This should never happen outside of a bug, but |EC_POINT_is_on_curve|
596 // rejects points not on the curve.
597 OPENSSL_memset(&p->raw.X, 0, sizeof(p->raw.X));
598 EXPECT_FALSE(EC_POINT_is_on_curve(group(), p.get(), nullptr));
599
600 // The point at infinity is always on the curve.
601 ASSERT_TRUE(EC_POINT_copy(p.get(), EC_KEY_get0_public_key(key.get())));
602 OPENSSL_memset(&p->raw.Z, 0, sizeof(p->raw.Z));
603 EXPECT_TRUE(EC_POINT_is_on_curve(group(), p.get(), nullptr));
604 }
605
TEST_P(ECCurveTest,Compare)606 TEST_P(ECCurveTest, Compare) {
607 bssl::UniquePtr<EC_KEY> key1(EC_KEY_new_by_curve_name(GetParam()));
608 ASSERT_TRUE(key1);
609 ASSERT_TRUE(EC_KEY_generate_key(key1.get()));
610 const EC_POINT *pub1 = EC_KEY_get0_public_key(key1.get());
611
612 bssl::UniquePtr<EC_KEY> key2(EC_KEY_new_by_curve_name(GetParam()));
613 ASSERT_TRUE(key2);
614 ASSERT_TRUE(EC_KEY_generate_key(key2.get()));
615 const EC_POINT *pub2 = EC_KEY_get0_public_key(key2.get());
616
617 // Two different points should not compare as equal.
618 EXPECT_EQ(1, EC_POINT_cmp(group(), pub1, pub2, nullptr));
619
620 // Serialize |pub1| and parse it back out. This gives a point in affine
621 // coordinates.
622 std::vector<uint8_t> serialized;
623 ASSERT_TRUE(
624 EncodeECPoint(&serialized, group(), pub1, POINT_CONVERSION_UNCOMPRESSED));
625 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
626 ASSERT_TRUE(p);
627 ASSERT_TRUE(EC_POINT_oct2point(group(), p.get(), serialized.data(),
628 serialized.size(), nullptr));
629
630 // The points should be equal.
631 EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
632
633 // Add something to the point. It no longer compares as equal.
634 ASSERT_TRUE(EC_POINT_add(group(), p.get(), p.get(), pub2, nullptr));
635 EXPECT_EQ(1, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
636
637 // Negate |pub2|. It should no longer compare as equal. This tests that we
638 // check both x and y coordinate.
639 bssl::UniquePtr<EC_POINT> q(EC_POINT_new(group()));
640 ASSERT_TRUE(q);
641 ASSERT_TRUE(EC_POINT_copy(q.get(), pub2));
642 ASSERT_TRUE(EC_POINT_invert(group(), q.get(), nullptr));
643 EXPECT_EQ(1, EC_POINT_cmp(group(), q.get(), pub2, nullptr));
644
645 // Return |p| to the original value. It should be equal to |pub1| again.
646 ASSERT_TRUE(EC_POINT_add(group(), p.get(), p.get(), q.get(), nullptr));
647 EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
648
649 // Infinity compares as equal to itself, but not other points.
650 bssl::UniquePtr<EC_POINT> inf1(EC_POINT_new(group())),
651 inf2(EC_POINT_new(group()));
652 ASSERT_TRUE(inf1);
653 ASSERT_TRUE(inf2);
654 ASSERT_TRUE(EC_POINT_set_to_infinity(group(), inf1.get()));
655 // |q| is currently -|pub2|.
656 ASSERT_TRUE(EC_POINT_add(group(), inf2.get(), pub2, q.get(), nullptr));
657 EXPECT_EQ(0, EC_POINT_cmp(group(), inf1.get(), inf2.get(), nullptr));
658 EXPECT_EQ(1, EC_POINT_cmp(group(), inf1.get(), p.get(), nullptr));
659 }
660
TEST_P(ECCurveTest,GenerateFIPS)661 TEST_P(ECCurveTest, GenerateFIPS) {
662 // Generate an EC_KEY.
663 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam()));
664 ASSERT_TRUE(key);
665 ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()));
666 }
667
TEST_P(ECCurveTest,AddingEqualPoints)668 TEST_P(ECCurveTest, AddingEqualPoints) {
669 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam()));
670 ASSERT_TRUE(key);
671 ASSERT_TRUE(EC_KEY_generate_key(key.get()));
672
673 bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group()));
674 ASSERT_TRUE(p1);
675 ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
676
677 bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group()));
678 ASSERT_TRUE(p2);
679 ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
680
681 bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group()));
682 ASSERT_TRUE(double_p1);
683 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
684 ASSERT_TRUE(ctx);
685 ASSERT_TRUE(EC_POINT_dbl(group(), double_p1.get(), p1.get(), ctx.get()));
686
687 bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group()));
688 ASSERT_TRUE(p1_plus_p2);
689 ASSERT_TRUE(
690 EC_POINT_add(group(), p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
691
692 EXPECT_EQ(0,
693 EC_POINT_cmp(group(), double_p1.get(), p1_plus_p2.get(), ctx.get()))
694 << "A+A != 2A";
695 }
696
TEST_P(ECCurveTest,MulZero)697 TEST_P(ECCurveTest, MulZero) {
698 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
699 ASSERT_TRUE(point);
700 bssl::UniquePtr<BIGNUM> zero(BN_new());
701 ASSERT_TRUE(zero);
702 BN_zero(zero.get());
703 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), zero.get(), nullptr, nullptr,
704 nullptr));
705
706 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
707 << "g * 0 did not return point at infinity.";
708
709 // Test that zero times an arbitrary point is also infinity. The generator is
710 // used as the arbitrary point.
711 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group()));
712 ASSERT_TRUE(generator);
713 ASSERT_TRUE(EC_POINT_mul(group(), generator.get(), BN_value_one(), nullptr,
714 nullptr, nullptr));
715 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, generator.get(),
716 zero.get(), nullptr));
717
718 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
719 << "p * 0 did not return point at infinity.";
720 }
721
722 // Test that multiplying by the order produces ∞ and, moreover, that callers may
723 // do so. |EC_POINT_mul| is almost exclusively used with reduced scalars, with
724 // this exception. This comes from consumers following NIST SP 800-56A section
725 // 5.6.2.3.2. (Though all our curves have cofactor one, so this check isn't
726 // useful.)
TEST_P(ECCurveTest,MulOrder)727 TEST_P(ECCurveTest, MulOrder) {
728 // Test that g × order = ∞.
729 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
730 ASSERT_TRUE(point);
731 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), EC_GROUP_get0_order(group()),
732 nullptr, nullptr, nullptr));
733
734 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
735 << "g * order did not return point at infinity.";
736
737 // Test that p × order = ∞, for some arbitrary p.
738 bssl::UniquePtr<BIGNUM> forty_two(BN_new());
739 ASSERT_TRUE(forty_two);
740 ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
741 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
742 nullptr, nullptr));
743 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, point.get(),
744 EC_GROUP_get0_order(group()), nullptr));
745
746 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
747 << "p * order did not return point at infinity.";
748 }
749
750 // Test that |EC_POINT_mul| works with out-of-range scalars. The operation will
751 // not be constant-time, but we'll compute the right answer.
TEST_P(ECCurveTest,MulOutOfRange)752 TEST_P(ECCurveTest, MulOutOfRange) {
753 bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(EC_GROUP_get0_order(group())));
754 ASSERT_TRUE(n_minus_one);
755 ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1));
756
757 bssl::UniquePtr<BIGNUM> minus_one(BN_new());
758 ASSERT_TRUE(minus_one);
759 ASSERT_TRUE(BN_one(minus_one.get()));
760 BN_set_negative(minus_one.get(), 1);
761
762 bssl::UniquePtr<BIGNUM> seven(BN_new());
763 ASSERT_TRUE(seven);
764 ASSERT_TRUE(BN_set_word(seven.get(), 7));
765
766 bssl::UniquePtr<BIGNUM> ten_n_plus_seven(
767 BN_dup(EC_GROUP_get0_order(group())));
768 ASSERT_TRUE(ten_n_plus_seven);
769 ASSERT_TRUE(BN_mul_word(ten_n_plus_seven.get(), 10));
770 ASSERT_TRUE(BN_add_word(ten_n_plus_seven.get(), 7));
771
772 bssl::UniquePtr<EC_POINT> point1(EC_POINT_new(group())),
773 point2(EC_POINT_new(group()));
774 ASSERT_TRUE(point1);
775 ASSERT_TRUE(point2);
776
777 ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), n_minus_one.get(), nullptr,
778 nullptr, nullptr));
779 ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), minus_one.get(), nullptr,
780 nullptr, nullptr));
781 EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
782 << "-1 * G and (n-1) * G did not give the same result";
783
784 ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), seven.get(), nullptr, nullptr,
785 nullptr));
786 ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), ten_n_plus_seven.get(),
787 nullptr, nullptr, nullptr));
788 EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
789 << "7 * G and (10n + 7) * G did not give the same result";
790 }
791
792 // Test that 10×∞ + G = G.
TEST_P(ECCurveTest,Mul)793 TEST_P(ECCurveTest, Mul) {
794 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
795 ASSERT_TRUE(p);
796 bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group()));
797 ASSERT_TRUE(result);
798 bssl::UniquePtr<BIGNUM> n(BN_new());
799 ASSERT_TRUE(n);
800 ASSERT_TRUE(EC_POINT_set_to_infinity(group(), p.get()));
801 ASSERT_TRUE(BN_set_word(n.get(), 10));
802
803 // First check that 10×∞ = ∞.
804 ASSERT_TRUE(
805 EC_POINT_mul(group(), result.get(), nullptr, p.get(), n.get(), nullptr));
806 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), result.get()));
807
808 // Now check that 10×∞ + G = G.
809 const EC_POINT *generator = EC_GROUP_get0_generator(group());
810 ASSERT_TRUE(EC_POINT_mul(group(), result.get(), BN_value_one(), p.get(),
811 n.get(), nullptr));
812 EXPECT_EQ(0, EC_POINT_cmp(group(), result.get(), generator, nullptr));
813 }
814
TEST_P(ECCurveTest,MulNonMinimal)815 TEST_P(ECCurveTest, MulNonMinimal) {
816 bssl::UniquePtr<BIGNUM> forty_two(BN_new());
817 ASSERT_TRUE(forty_two);
818 ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
819
820 // Compute g × 42.
821 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
822 ASSERT_TRUE(point);
823 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
824 nullptr, nullptr));
825
826 // Compute it again with a non-minimal 42, much larger than the scalar.
827 ASSERT_TRUE(bn_resize_words(forty_two.get(), 64));
828
829 bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group()));
830 ASSERT_TRUE(point2);
831 ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), forty_two.get(), nullptr,
832 nullptr, nullptr));
833 EXPECT_EQ(0, EC_POINT_cmp(group(), point.get(), point2.get(), nullptr));
834 }
835
836 // Test that EC_KEY_set_private_key rejects invalid values.
TEST_P(ECCurveTest,SetInvalidPrivateKey)837 TEST_P(ECCurveTest, SetInvalidPrivateKey) {
838 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam()));
839 ASSERT_TRUE(key);
840
841 bssl::UniquePtr<BIGNUM> bn(BN_dup(BN_value_one()));
842 ASSERT_TRUE(bn);
843 BN_set_negative(bn.get(), 1);
844 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
845 << "Unexpectedly set a key of -1";
846 ERR_clear_error();
847
848 ASSERT_TRUE(
849 BN_copy(bn.get(), EC_GROUP_get0_order(EC_KEY_get0_group(key.get()))));
850 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
851 << "Unexpectedly set a key of the group order.";
852 ERR_clear_error();
853
854 BN_zero(bn.get());
855 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
856 << "Unexpectedly set a key of 0";
857 ERR_clear_error();
858 }
859
TEST_P(ECCurveTest,IgnoreOct2PointReturnValue)860 TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
861 bssl::UniquePtr<BIGNUM> forty_two(BN_new());
862 ASSERT_TRUE(forty_two);
863 ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
864
865 // Compute g × 42.
866 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
867 ASSERT_TRUE(point);
868 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
869 nullptr, nullptr));
870
871 // Serialize the point.
872 std::vector<uint8_t> serialized;
873 ASSERT_TRUE(EncodeECPoint(&serialized, group(), point.get(),
874 POINT_CONVERSION_UNCOMPRESSED));
875
876 // Create a serialized point that is not on the curve.
877 serialized[serialized.size() - 1]++;
878
879 ASSERT_FALSE(EC_POINT_oct2point(group(), point.get(), serialized.data(),
880 serialized.size(), nullptr));
881 // After a failure, |point| should have been set to the generator to defend
882 // against code that doesn't check the return value.
883 ASSERT_EQ(0, EC_POINT_cmp(group(), point.get(),
884 EC_GROUP_get0_generator(group()), nullptr));
885 }
886
TEST_P(ECCurveTest,DoubleSpecialCase)887 TEST_P(ECCurveTest, DoubleSpecialCase) {
888 const EC_POINT *g = EC_GROUP_get0_generator(group());
889
890 bssl::UniquePtr<EC_POINT> two_g(EC_POINT_new(group()));
891 ASSERT_TRUE(two_g);
892 ASSERT_TRUE(EC_POINT_dbl(group(), two_g.get(), g, nullptr));
893
894 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
895 ASSERT_TRUE(p);
896 ASSERT_TRUE(EC_POINT_mul(group(), p.get(), BN_value_one(), g, BN_value_one(),
897 nullptr));
898 EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
899
900 EC_SCALAR one;
901 ASSERT_TRUE(ec_bignum_to_scalar(group(), &one, BN_value_one()));
902 ASSERT_TRUE(
903 ec_point_mul_scalar_public(group(), &p->raw, &one, &g->raw, &one));
904 EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
905 }
906
907 // This a regression test for a P-224 bug, but we may as well run it for all
908 // curves.
TEST_P(ECCurveTest,P224Bug)909 TEST_P(ECCurveTest, P224Bug) {
910 // P = -G
911 const EC_POINT *g = EC_GROUP_get0_generator(group());
912 bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group()));
913 ASSERT_TRUE(p);
914 ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr));
915
916 // Compute 31 * P + 32 * G = G
917 bssl::UniquePtr<EC_POINT> ret(EC_POINT_new(group()));
918 ASSERT_TRUE(ret);
919 bssl::UniquePtr<BIGNUM> bn31(BN_new()), bn32(BN_new());
920 ASSERT_TRUE(bn31);
921 ASSERT_TRUE(bn32);
922 ASSERT_TRUE(BN_set_word(bn31.get(), 31));
923 ASSERT_TRUE(BN_set_word(bn32.get(), 32));
924 ASSERT_TRUE(EC_POINT_mul(group(), ret.get(), bn32.get(), p.get(), bn31.get(),
925 nullptr));
926 EXPECT_EQ(0, EC_POINT_cmp(group(), ret.get(), g, nullptr));
927
928 // Repeat the computation with |ec_point_mul_scalar_public|, which ties the
929 // additions together.
930 EC_SCALAR sc31, sc32;
931 ASSERT_TRUE(ec_bignum_to_scalar(group(), &sc31, bn31.get()));
932 ASSERT_TRUE(ec_bignum_to_scalar(group(), &sc32, bn32.get()));
933 ASSERT_TRUE(
934 ec_point_mul_scalar_public(group(), &ret->raw, &sc32, &p->raw, &sc31));
935 EXPECT_EQ(0, EC_POINT_cmp(group(), ret.get(), g, nullptr));
936 }
937
TEST_P(ECCurveTest,GPlusMinusG)938 TEST_P(ECCurveTest, GPlusMinusG) {
939 const EC_POINT *g = EC_GROUP_get0_generator(group());
940
941 bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group()));
942 ASSERT_TRUE(p);
943 ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr));
944
945 bssl::UniquePtr<EC_POINT> sum(EC_POINT_new(group()));
946 ASSERT_TRUE(sum);
947 ASSERT_TRUE(EC_POINT_add(group(), sum.get(), g, p.get(), nullptr));
948 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), sum.get()));
949 }
950
951 // Test that we refuse to encode or decode the point at infinity.
TEST_P(ECCurveTest,EncodeInfinity)952 TEST_P(ECCurveTest, EncodeInfinity) {
953 // The point at infinity is encoded as a single zero byte, but we do not
954 // support it.
955 static const uint8_t kInfinity[] = {0};
956 bssl::UniquePtr<EC_POINT> inf(EC_POINT_new(group()));
957 ASSERT_TRUE(inf);
958 EXPECT_FALSE(EC_POINT_oct2point(group(), inf.get(), kInfinity,
959 sizeof(kInfinity), nullptr));
960
961 // Encoding it also fails.
962 ASSERT_TRUE(EC_POINT_set_to_infinity(group(), inf.get()));
963 uint8_t buf[128];
964 EXPECT_EQ(
965 0u, EC_POINT_point2oct(group(), inf.get(), POINT_CONVERSION_UNCOMPRESSED,
966 buf, sizeof(buf), nullptr));
967
968 // Measuring the length of the encoding also fails.
969 EXPECT_EQ(
970 0u, EC_POINT_point2oct(group(), inf.get(), POINT_CONVERSION_UNCOMPRESSED,
971 nullptr, 0, nullptr));
972 }
973
AllCurves()974 static std::vector<int> AllCurves() {
975 const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
976 std::vector<EC_builtin_curve> curves(num_curves);
977 EC_get_builtin_curves(curves.data(), num_curves);
978 std::vector<int> nids;
979 for (const auto& curve : curves) {
980 nids.push_back(curve.nid);
981 }
982 return nids;
983 }
984
CurveToString(const testing::TestParamInfo<int> & params)985 static std::string CurveToString(const testing::TestParamInfo<int> ¶ms) {
986 return OBJ_nid2sn(params.param);
987 }
988
989 INSTANTIATE_TEST_SUITE_P(All, ECCurveTest, testing::ValuesIn(AllCurves()),
990 CurveToString);
991
GetCurve(FileTest * t,const char * key)992 static const EC_GROUP *GetCurve(FileTest *t, const char *key) {
993 std::string curve_name;
994 if (!t->GetAttribute(&curve_name, key)) {
995 return nullptr;
996 }
997
998 if (curve_name == "P-224") {
999 return EC_group_p224();
1000 }
1001 if (curve_name == "P-256") {
1002 return EC_group_p256();
1003 }
1004 if (curve_name == "P-384") {
1005 return EC_group_p384();
1006 }
1007 if (curve_name == "P-521") {
1008 return EC_group_p521();
1009 }
1010
1011 t->PrintLine("Unknown curve '%s'", curve_name.c_str());
1012 return nullptr;
1013 }
1014
GetBIGNUM(FileTest * t,const char * key)1015 static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) {
1016 std::vector<uint8_t> bytes;
1017 if (!t->GetBytes(&bytes, key)) {
1018 return nullptr;
1019 }
1020
1021 return bssl::UniquePtr<BIGNUM>(
1022 BN_bin2bn(bytes.data(), bytes.size(), nullptr));
1023 }
1024
TEST(ECTest,ScalarBaseMultVectors)1025 TEST(ECTest, ScalarBaseMultVectors) {
1026 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1027 ASSERT_TRUE(ctx);
1028
1029 FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
1030 [&](FileTest *t) {
1031 const EC_GROUP *group = GetCurve(t, "Curve");
1032 ASSERT_TRUE(group);
1033 bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N");
1034 ASSERT_TRUE(n);
1035 bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
1036 ASSERT_TRUE(x);
1037 bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
1038 ASSERT_TRUE(y);
1039 bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get());
1040
1041 bssl::UniquePtr<BIGNUM> px(BN_new());
1042 ASSERT_TRUE(px);
1043 bssl::UniquePtr<BIGNUM> py(BN_new());
1044 ASSERT_TRUE(py);
1045 auto check_point = [&](const EC_POINT *p) {
1046 if (is_infinity) {
1047 EXPECT_TRUE(EC_POINT_is_at_infinity(group, p));
1048 } else {
1049 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
1050 group, p, px.get(), py.get(), ctx.get()));
1051 EXPECT_EQ(0, BN_cmp(x.get(), px.get()));
1052 EXPECT_EQ(0, BN_cmp(y.get(), py.get()));
1053 }
1054 };
1055
1056 const EC_POINT *g = EC_GROUP_get0_generator(group);
1057 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group));
1058 ASSERT_TRUE(p);
1059 // Test single-point multiplication.
1060 ASSERT_TRUE(EC_POINT_mul(group, p.get(), n.get(), nullptr, nullptr,
1061 ctx.get()));
1062 check_point(p.get());
1063
1064 ASSERT_TRUE(EC_POINT_mul(group, p.get(), nullptr, g, n.get(), ctx.get()));
1065 check_point(p.get());
1066 });
1067 }
1068
1069 // These tests take a very long time, but are worth running when we make
1070 // non-trivial changes to the EC code.
TEST(ECTest,DISABLED_ScalarBaseMultVectorsTwoPoint)1071 TEST(ECTest, DISABLED_ScalarBaseMultVectorsTwoPoint) {
1072 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1073 ASSERT_TRUE(ctx);
1074
1075 FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
1076 [&](FileTest *t) {
1077 const EC_GROUP *group = GetCurve(t, "Curve");
1078 ASSERT_TRUE(group);
1079 bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N");
1080 ASSERT_TRUE(n);
1081 bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
1082 ASSERT_TRUE(x);
1083 bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
1084 ASSERT_TRUE(y);
1085 bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get());
1086
1087 bssl::UniquePtr<BIGNUM> px(BN_new());
1088 ASSERT_TRUE(px);
1089 bssl::UniquePtr<BIGNUM> py(BN_new());
1090 ASSERT_TRUE(py);
1091 auto check_point = [&](const EC_POINT *p) {
1092 if (is_infinity) {
1093 EXPECT_TRUE(EC_POINT_is_at_infinity(group, p));
1094 } else {
1095 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
1096 group, p, px.get(), py.get(), ctx.get()));
1097 EXPECT_EQ(0, BN_cmp(x.get(), px.get()));
1098 EXPECT_EQ(0, BN_cmp(y.get(), py.get()));
1099 }
1100 };
1101
1102 const EC_POINT *g = EC_GROUP_get0_generator(group);
1103 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group));
1104 ASSERT_TRUE(p);
1105 bssl::UniquePtr<BIGNUM> a(BN_new()), b(BN_new());
1106 for (int i = -64; i < 64; i++) {
1107 SCOPED_TRACE(i);
1108 ASSERT_TRUE(BN_set_word(a.get(), abs(i)));
1109 if (i < 0) {
1110 ASSERT_TRUE(BN_sub(a.get(), EC_GROUP_get0_order(group), a.get()));
1111 }
1112
1113 ASSERT_TRUE(BN_copy(b.get(), n.get()));
1114 ASSERT_TRUE(BN_sub(b.get(), b.get(), a.get()));
1115 if (BN_is_negative(b.get())) {
1116 ASSERT_TRUE(BN_add(b.get(), b.get(), EC_GROUP_get0_order(group)));
1117 }
1118
1119 ASSERT_TRUE(EC_POINT_mul(group, p.get(), a.get(), g, b.get(), ctx.get()));
1120 check_point(p.get());
1121
1122 EC_SCALAR a_scalar, b_scalar;
1123 ASSERT_TRUE(ec_bignum_to_scalar(group, &a_scalar, a.get()));
1124 ASSERT_TRUE(ec_bignum_to_scalar(group, &b_scalar, b.get()));
1125 ASSERT_TRUE(ec_point_mul_scalar_public(group, &p->raw, &a_scalar, &g->raw,
1126 &b_scalar));
1127 check_point(p.get());
1128 }
1129 });
1130 }
1131
HexToBytes(const char * str)1132 static std::vector<uint8_t> HexToBytes(const char *str) {
1133 std::vector<uint8_t> ret;
1134 if (!DecodeHex(&ret, str)) {
1135 abort();
1136 }
1137 return ret;
1138 }
1139
TEST(ECTest,DeriveFromSecret)1140 TEST(ECTest, DeriveFromSecret) {
1141 struct DeriveTest {
1142 const EC_GROUP *group;
1143 std::vector<uint8_t> secret;
1144 std::vector<uint8_t> expected_priv;
1145 std::vector<uint8_t> expected_pub;
1146 };
1147 const DeriveTest kDeriveTests[] = {
1148 {EC_group_p256(), HexToBytes(""),
1149 HexToBytes(
1150 "b98a86a71efb51ebdac4759937b977e9b0c05224675bb2b6a58ba306e237f4b8"),
1151 HexToBytes(
1152 "04fbe6cab439918e00231a2ff073cdc25823998864a9eb36f809095a1a919ece875"
1153 "a145803fbe89a6cde53936e3c6d9c253ed3d38f5f58cae455c27e95645ceda9")},
1154 {EC_group_p256(), HexToBytes("123456"),
1155 HexToBytes(
1156 "44a72bc62087b88e5ab7126766177ed0d8f1ed09ad066cd746527fc201105a7e"),
1157 HexToBytes(
1158 "04ec0555cd76e991fef7f5504343937d0f38696db3360a4854052cb0d84a377a5a0"
1159 "ff64c352755c28692b4ae085c2b817db9a1eddbd22e9cf39c12751e0870791b")},
1160 {EC_group_p256(), HexToBytes("00000000000000000000000000000000"),
1161 HexToBytes(
1162 "7ca1e2c83e6a5f2c1b3e7d58180226f269930c4b9fbe2a275096079630b7c57d"),
1163 HexToBytes(
1164 "0442ef70c8fc0fbe383ed0a0da36f39f9a590f3feebc07863cc858c9a8ef0465731"
1165 "0408c249bd4d61929c54b71ffe056e6b4fa1eb537039b43d1c175f0ceab0f89")},
1166 {EC_group_p256(),
1167 HexToBytes(
1168 "de9c9b35543aaa0fba039e34e8ca9695da3225c7161c9e3a8c70356cac28c780"),
1169 HexToBytes(
1170 "659f5abf3b62b9931c29d6ed0722efd2349fa56f54e708cf3272f620f1bc44d0"),
1171 HexToBytes(
1172 "046741f806b593bf3a3d4a9d76bdcb9b0d7874633cbea8f42c05e78561f7e8ec362"
1173 "b9b6f1913ded796fbdafe7f210cea897ac22a4e580c06a60f2659fd09f1830f")},
1174 {EC_group_p384(), HexToBytes("123456"),
1175 HexToBytes("95cd90d548997de090c7622708eccb7edc1b1bd78d2422235ad97406dada"
1176 "076555309da200096f6e4b36c46002beee89"),
1177 HexToBytes(
1178 "04007b2d026aa7636fa912c3f970d62bb6c10fa81c8f3290ed90b2d701696d1c6b9"
1179 "5af88ce13e962996a7ac37e16527cb5d69bd081b8641d07634cf84b438600ec9434"
1180 "15ac6bd7a0236f7ab0ea31ece67df03fa11646ea2b75e73d1b5e45b75c18")},
1181 };
1182
1183 for (const auto &test : kDeriveTests) {
1184 SCOPED_TRACE(Bytes(test.secret));
1185
1186 bssl::UniquePtr<EC_KEY> key(EC_KEY_derive_from_secret(
1187 test.group, test.secret.data(), test.secret.size()));
1188 ASSERT_TRUE(key);
1189
1190 std::vector<uint8_t> priv(BN_num_bytes(EC_GROUP_get0_order(test.group)));
1191 ASSERT_TRUE(BN_bn2bin_padded(priv.data(), priv.size(),
1192 EC_KEY_get0_private_key(key.get())));
1193 EXPECT_EQ(Bytes(priv), Bytes(test.expected_priv));
1194
1195 uint8_t *pub = nullptr;
1196 size_t pub_len =
1197 EC_KEY_key2buf(key.get(), POINT_CONVERSION_UNCOMPRESSED, &pub, nullptr);
1198 bssl::UniquePtr<uint8_t> free_pub(pub);
1199 EXPECT_NE(pub_len, 0u);
1200 EXPECT_EQ(Bytes(pub, pub_len), Bytes(test.expected_pub));
1201 }
1202 }
1203
TEST(ECTest,HashToCurve)1204 TEST(ECTest, HashToCurve) {
1205 auto hash_to_curve_p384_sha512_draft07 =
1206 [](const EC_GROUP *group, EC_POINT *out, const uint8_t *dst,
1207 size_t dst_len, const uint8_t *msg, size_t msg_len) -> int {
1208 if (EC_GROUP_cmp(group, out->group, NULL) != 0) {
1209 return 0;
1210 }
1211 return ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(group, &out->raw, dst,
1212 dst_len, msg, msg_len);
1213 };
1214
1215 struct HashToCurveTest {
1216 int (*hash_to_curve)(const EC_GROUP *group, EC_POINT *out,
1217 const uint8_t *dst, size_t dst_len, const uint8_t *msg,
1218 size_t msg_len);
1219 const EC_GROUP *group;
1220 const char *dst;
1221 const char *msg;
1222 const char *x_hex;
1223 const char *y_hex;
1224 };
1225 const HashToCurveTest kTests[] = {
1226 // See RFC 9380, appendix J.1.1.
1227 {&EC_hash_to_curve_p256_xmd_sha256_sswu, EC_group_p256(),
1228 "QUUX-V01-CS02-with-P256_XMD:SHA-256_SSWU_RO_", "",
1229 "2c15230b26dbc6fc9a37051158c95b79656e17a1a920b11394ca91"
1230 "c44247d3e4",
1231 "8a7a74985cc5c776cdfe4b1f19884970453912e9d31528c060be9a"
1232 "b5c43e8415"},
1233 {&EC_hash_to_curve_p256_xmd_sha256_sswu, EC_group_p256(),
1234 "QUUX-V01-CS02-with-P256_XMD:SHA-256_SSWU_RO_", "abc",
1235 "0bb8b87485551aa43ed54f009230450b492fead5f1cc91658775da"
1236 "c4a3388a0f",
1237 "5c41b3d0731a27a7b14bc0bf0ccded2d8751f83493404c84a88e71"
1238 "ffd424212e"},
1239 {&EC_hash_to_curve_p256_xmd_sha256_sswu, EC_group_p256(),
1240 "QUUX-V01-CS02-with-P256_XMD:SHA-256_SSWU_RO_", "abcdef0123456789",
1241 "65038ac8f2b1def042a5df0b33b1f4eca6bff7cb0f9c6c15268118"
1242 "64e544ed80",
1243 "cad44d40a656e7aff4002a8de287abc8ae0482b5ae825822bb870d"
1244 "6df9b56ca3"},
1245 {&EC_hash_to_curve_p256_xmd_sha256_sswu, EC_group_p256(),
1246 "QUUX-V01-CS02-with-P256_XMD:SHA-256_SSWU_RO_",
1247 "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"
1248 "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"
1249 "qqqqqqqqqqqqqqqqqqqqqqqqq",
1250 "4be61ee205094282ba8a2042bcb48d88dfbb609301c49aa8b07853"
1251 "3dc65a0b5d",
1252 "98f8df449a072c4721d241a3b1236d3caccba603f916ca680f4539"
1253 "d2bfb3c29e"},
1254 {&EC_hash_to_curve_p256_xmd_sha256_sswu, EC_group_p256(),
1255 "QUUX-V01-CS02-with-P256_XMD:SHA-256_SSWU_RO_",
1256 "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1257 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1258 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1259 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1260 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1261 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1262 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1263 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1264 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1265 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1266 "457ae2981f70ca85d8e24c308b14db22f3e3862c5ea0f652ca38b5"
1267 "e49cd64bc5",
1268 "ecb9f0eadc9aeed232dabc53235368c1394c78de05dd96893eefa6"
1269 "2b0f4757dc"},
1270
1271 // See draft-irtf-cfrg-hash-to-curve-07, appendix G.2.1.
1272 {hash_to_curve_p384_sha512_draft07, EC_group_p384(),
1273 "P384_XMD:SHA-512_SSWU_RO_TESTGEN", "",
1274 "2fc0b9efdd63a8e43b4db88dc12f03c798f6fd91bccac0c9096185"
1275 "4386e58fdc54fc2a01f0f358759054ce1f9b762025",
1276 "949b936fabb72cdb02cd7980b86cb6a3adf286658e81301648851d"
1277 "b8a49d9bec00ccb57698d559fc5960fa5030a8e54b"},
1278 {hash_to_curve_p384_sha512_draft07, EC_group_p384(),
1279 "P384_XMD:SHA-512_SSWU_RO_TESTGEN", "abc",
1280 "4f3338035391e8ce8ce40c974136f0edc97f392ffd44a643338741"
1281 "8ed1b8c2603487e1688ec151f048fbc6b2c138c92f",
1282 "152b90aef6558be328a3168855fb1906452e7167b0f7c8a56ff9d4"
1283 "fa87d6fb522cdf8e409db54418b2c764fd26260757"},
1284 {hash_to_curve_p384_sha512_draft07, EC_group_p384(),
1285 "P384_XMD:SHA-512_SSWU_RO_TESTGEN", "abcdef0123456789",
1286 "e9e5d7ac397e123d060ad44301cbc8eb972f6e64ebcff29dcc9b9a"
1287 "10357902aace2240c580fec85e5b427d98b4e80703",
1288 "916cb8963521ad75105be43cc4148e5a5bbb4fcf107f1577e4f7fa"
1289 "3ca58cd786aa76890c8e687d2353393bc16c78ec4d"},
1290 {hash_to_curve_p384_sha512_draft07, EC_group_p384(),
1291 "P384_XMD:SHA-512_SSWU_RO_TESTGEN",
1292 "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1293 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1294 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1295 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1296 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1297 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1298 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1299 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1300 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1301 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1302 "41941db59a7b8b633bd5bfa462f1e29a9f18e5a341445d90fc6eb9"
1303 "37f2913224287b9dfb64742851f760eb14ca115ff9",
1304 "1510e764f1be968d661b7aaecb26a6d38c98e5205ca150f0ae426d"
1305 "2c3983c68e3a9ffb283c6ae4891d891b5705500475"},
1306 };
1307
1308 for (const auto &test : kTests) {
1309 SCOPED_TRACE(test.dst);
1310 SCOPED_TRACE(test.msg);
1311
1312 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(test.group));
1313 ASSERT_TRUE(p);
1314 ASSERT_TRUE(test.hash_to_curve(
1315 test.group, p.get(), reinterpret_cast<const uint8_t *>(test.dst),
1316 strlen(test.dst), reinterpret_cast<const uint8_t *>(test.msg),
1317 strlen(test.msg)));
1318
1319 std::vector<uint8_t> buf;
1320 ASSERT_TRUE(EncodeECPoint(&buf, test.group, p.get(),
1321 POINT_CONVERSION_UNCOMPRESSED));
1322 size_t field_len = (buf.size() - 1) / 2;
1323 EXPECT_EQ(test.x_hex,
1324 EncodeHex(bssl::MakeConstSpan(buf).subspan(1, field_len)));
1325 EXPECT_EQ(test.y_hex, EncodeHex(bssl::MakeConstSpan(buf).subspan(
1326 1 + field_len, field_len)));
1327 }
1328
1329 // hash-to-curve functions should check for the wrong group.
1330 EC_JACOBIAN raw;
1331 bssl::UniquePtr<EC_POINT> p_p384(EC_POINT_new(EC_group_p384()));
1332 ASSERT_TRUE(p_p384);
1333 bssl::UniquePtr<EC_POINT> p_p224(EC_POINT_new(EC_group_p224()));
1334 ASSERT_TRUE(p_p224);
1335 static const uint8_t kDST[] = {0, 1, 2, 3};
1336 static const uint8_t kMessage[] = {4, 5, 6, 7};
1337 EXPECT_FALSE(ec_hash_to_curve_p384_xmd_sha384_sswu(
1338 EC_group_p224(), &raw, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
1339 EXPECT_FALSE(EC_hash_to_curve_p384_xmd_sha384_sswu(
1340 EC_group_p224(), p_p224.get(), kDST, sizeof(kDST), kMessage,
1341 sizeof(kMessage)));
1342 EXPECT_FALSE(EC_hash_to_curve_p384_xmd_sha384_sswu(
1343 EC_group_p224(), p_p384.get(), kDST, sizeof(kDST), kMessage,
1344 sizeof(kMessage)));
1345 EXPECT_FALSE(EC_hash_to_curve_p384_xmd_sha384_sswu(
1346 EC_group_p384(), p_p224.get(), kDST, sizeof(kDST), kMessage,
1347 sizeof(kMessage)));
1348
1349 // Zero-length DSTs are not allowed.
1350 EXPECT_FALSE(ec_hash_to_curve_p384_xmd_sha384_sswu(
1351 EC_group_p384(), &raw, nullptr, 0, kMessage, sizeof(kMessage)));
1352 }
1353
TEST(ECTest,HashToScalar)1354 TEST(ECTest, HashToScalar) {
1355 struct HashToScalarTest {
1356 int (*hash_to_scalar)(const EC_GROUP *group, EC_SCALAR *out,
1357 const uint8_t *dst, size_t dst_len,
1358 const uint8_t *msg, size_t msg_len);
1359 const EC_GROUP *group;
1360 const char *dst;
1361 const char *msg;
1362 const char *result_hex;
1363 };
1364 const HashToScalarTest kTests[] = {
1365 {&ec_hash_to_scalar_p384_xmd_sha512_draft07, EC_group_p384(),
1366 "P384_XMD:SHA-512_SCALAR_TEST", "",
1367 "9687acc2de56c3cf94c0e05b6811a21aa480092254ec0532bdce63"
1368 "140ecd340f09dc2d45d77e21fb0aa76f7707b8a676"},
1369 {&ec_hash_to_scalar_p384_xmd_sha512_draft07, EC_group_p384(),
1370 "P384_XMD:SHA-512_SCALAR_TEST", "abcdef0123456789",
1371 "8f8076022a68233cbcecaceae68c2068f132724f001caa78619eff"
1372 "1ffc58fa871db73fe9034fc9cf853c384ed34b5666"},
1373 {&ec_hash_to_scalar_p384_xmd_sha512_draft07, EC_group_p384(),
1374 "P384_XMD:SHA-512_SCALAR_TEST",
1375 "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1376 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1377 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1378 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1379 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1380 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1381 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1382 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1383 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1384 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1385 "750f2fae7d2b2f41ac737d180c1d4363d85a1504798b4976d40921"
1386 "1ddb3651c13a5b4daba9975cdfce18336791131915"},
1387 };
1388
1389 for (const auto &test : kTests) {
1390 SCOPED_TRACE(test.dst);
1391 SCOPED_TRACE(test.msg);
1392
1393 EC_SCALAR scalar;
1394 ASSERT_TRUE(test.hash_to_scalar(
1395 test.group, &scalar, reinterpret_cast<const uint8_t *>(test.dst),
1396 strlen(test.dst), reinterpret_cast<const uint8_t *>(test.msg),
1397 strlen(test.msg)));
1398 uint8_t buf[EC_MAX_BYTES];
1399 size_t len;
1400 ec_scalar_to_bytes(test.group, buf, &len, &scalar);
1401 EXPECT_EQ(test.result_hex, EncodeHex(bssl::MakeConstSpan(buf, len)));
1402 }
1403
1404 // hash-to-scalar functions should check for the wrong group.
1405 EC_SCALAR scalar;
1406 static const uint8_t kDST[] = {0, 1, 2, 3};
1407 static const uint8_t kMessage[] = {4, 5, 6, 7};
1408 EXPECT_FALSE(ec_hash_to_scalar_p384_xmd_sha512_draft07(
1409 EC_group_p224(), &scalar, kDST, sizeof(kDST), kMessage,
1410 sizeof(kMessage)));
1411 }
1412