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