1 /* Copyright (c) 2014, Google Inc.
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.
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. */
21 #include <gtest/gtest.h>
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>
32 #include "../../test/file_test.h"
33 #include "../../test/test_util.h"
34 #include "../bn/internal.h"
38 // kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
40 static const uint8_t kECKeyWithoutPublic[] = {
41 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0,
42 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e,
43 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
44 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
47 // kECKeySpecifiedCurve is the above key with P-256's parameters explicitly
48 // spelled out rather than using a named curve.
49 static const uint8_t kECKeySpecifiedCurve[] = {
50 0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa,
51 0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb,
52 0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc,
53 0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02,
54 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
55 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
58 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
61 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
62 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
63 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
64 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
65 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
66 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
67 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
68 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
69 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
70 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
71 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
72 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
73 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
74 0x63, 0x25, 0x51, 0x02, 0x01, 0x01,
77 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
78 // the private key is one. The private key is incorrectly encoded without zero
80 static const uint8_t kECKeyMissingZeros[] = {
81 0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a,
82 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
83 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
84 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1,
85 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f,
86 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
87 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
90 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
91 // the private key is one. The private key is encoded with the required zero
93 static const uint8_t kECKeyWithZeros[] = {
94 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
97 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1,
98 0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
99 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d,
100 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3,
101 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e,
102 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
103 0x37, 0xbf, 0x51, 0xf5,
106 // DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
107 // result or nullptr on error.
108 static bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in,
111 CBS_init(&cbs, in, in_len);
112 bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL));
113 if (!ret || CBS_len(&cbs) != 0) {
119 // EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
120 // returns true on success or false on error.
121 static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
125 if (!CBB_init(cbb.get(), 0) ||
126 !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) ||
127 !CBB_finish(cbb.get(), &der, &der_len)) {
130 out->assign(der, der + der_len);
135 TEST(ECTest, Encoding) {
136 bssl::UniquePtr<EC_KEY> key =
137 DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
140 // Test that the encoding round-trips.
141 std::vector<uint8_t> out;
142 ASSERT_TRUE(EncodeECPrivateKey(&out, key.get()));
143 EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
145 const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
146 ASSERT_TRUE(pub_key) << "Public key missing";
148 bssl::UniquePtr<BIGNUM> x(BN_new());
149 bssl::UniquePtr<BIGNUM> y(BN_new());
152 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
153 EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL));
154 bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
155 bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
160 "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681",
163 "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88",
167 TEST(ECTest, ZeroPadding) {
168 // Check that the correct encoding round-trips.
169 bssl::UniquePtr<EC_KEY> key =
170 DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros));
172 std::vector<uint8_t> out;
173 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
174 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
176 // Keys without leading zeros also parse, but they encode correctly.
177 key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
179 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
180 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
183 TEST(ECTest, SpecifiedCurve) {
184 // Test keys with specified curves may be decoded.
185 bssl::UniquePtr<EC_KEY> key =
186 DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve));
189 // The group should have been interpreted as P-256.
190 EXPECT_EQ(NID_X9_62_prime256v1,
191 EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())));
193 // Encoding the key should still use named form.
194 std::vector<uint8_t> out;
195 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
196 EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
199 TEST(ECTest, ArbitraryCurve) {
200 // Make a P-256 key and extract the affine coordinates.
201 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
203 ASSERT_TRUE(EC_KEY_generate_key(key.get()));
205 // Make an arbitrary curve which is identical to P-256.
206 static const uint8_t kP[] = {
207 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
211 static const uint8_t kA[] = {
212 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
214 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
216 static const uint8_t kB[] = {
217 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
218 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
219 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
221 static const uint8_t kX[] = {
222 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6,
223 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb,
224 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96,
226 static const uint8_t kY[] = {
227 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
228 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
229 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
231 static const uint8_t kOrder[] = {
232 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
233 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
234 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
236 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
238 bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
240 bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
242 bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
244 bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr));
246 bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr));
248 bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
251 bssl::UniquePtr<EC_GROUP> group(
252 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
254 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
255 ASSERT_TRUE(generator);
256 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
257 group.get(), generator.get(), gx.get(), gy.get(), ctx.get()));
258 ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
261 // |group| should not have a curve name.
262 EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get()));
264 // Copy |key| to |key2| using |group|.
265 bssl::UniquePtr<EC_KEY> key2(EC_KEY_new());
267 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
269 bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
271 ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get()));
273 EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())));
274 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
275 EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(),
277 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(),
278 x.get(), y.get(), nullptr));
279 ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get()));
281 // The key must be valid according to the new group too.
282 EXPECT_TRUE(EC_KEY_check_key(key2.get()));
284 // Make a second instance of |group|.
285 bssl::UniquePtr<EC_GROUP> group2(
286 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
288 bssl::UniquePtr<EC_POINT> generator2(EC_POINT_new(group2.get()));
289 ASSERT_TRUE(generator2);
290 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
291 group2.get(), generator2.get(), gx.get(), gy.get(), ctx.get()));
292 ASSERT_TRUE(EC_GROUP_set_generator(group2.get(), generator2.get(),
293 order.get(), BN_value_one()));
295 EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
296 EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), NULL));
298 // group3 uses the wrong generator.
299 bssl::UniquePtr<EC_GROUP> group3(
300 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
302 bssl::UniquePtr<EC_POINT> generator3(EC_POINT_new(group3.get()));
303 ASSERT_TRUE(generator3);
304 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
305 group3.get(), generator3.get(), x.get(), y.get(), ctx.get()));
306 ASSERT_TRUE(EC_GROUP_set_generator(group3.get(), generator3.get(),
307 order.get(), BN_value_one()));
309 EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL));
311 #if !defined(BORINGSSL_SHARED_LIBRARY)
312 // group4 has non-minimal components that do not fit in |EC_SCALAR| and the
313 // future |EC_FELEM|.
314 ASSERT_TRUE(bn_resize_words(p.get(), 32));
315 ASSERT_TRUE(bn_resize_words(a.get(), 32));
316 ASSERT_TRUE(bn_resize_words(b.get(), 32));
317 ASSERT_TRUE(bn_resize_words(gx.get(), 32));
318 ASSERT_TRUE(bn_resize_words(gy.get(), 32));
319 ASSERT_TRUE(bn_resize_words(order.get(), 32));
321 bssl::UniquePtr<EC_GROUP> group4(
322 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
324 bssl::UniquePtr<EC_POINT> generator4(EC_POINT_new(group4.get()));
325 ASSERT_TRUE(generator4);
326 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
327 group4.get(), generator4.get(), gx.get(), gy.get(), ctx.get()));
328 ASSERT_TRUE(EC_GROUP_set_generator(group4.get(), generator4.get(),
329 order.get(), BN_value_one()));
331 EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group4.get(), NULL));
335 TEST(ECTest, SetKeyWithoutGroup) {
336 bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
339 // Private keys may not be configured without a group.
340 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), BN_value_one()));
342 // Public keys may not be configured without a group.
343 bssl::UniquePtr<EC_GROUP> group(
344 EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
347 EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(group.get())));
350 TEST(ECTest, GroupMismatch) {
351 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
353 bssl::UniquePtr<EC_GROUP> p256(
354 EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
357 // Changing a key's group is invalid.
358 EXPECT_FALSE(EC_KEY_set_group(key.get(), p256.get()));
360 // Configuring a public key with the wrong group is invalid.
362 EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(p256.get())));
365 TEST(ECTest, EmptyKey) {
366 bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
368 EXPECT_FALSE(EC_KEY_get0_group(key.get()));
369 EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
370 EXPECT_FALSE(EC_KEY_get0_private_key(key.get()));
373 class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {
375 const EC_GROUP *group() const { return group_.get(); }
377 void SetUp() override {
378 group_.reset(EC_GROUP_new_by_curve_name(GetParam().nid));
383 bssl::UniquePtr<EC_GROUP> group_;
386 TEST_P(ECCurveTest, SetAffine) {
387 // Generate an EC_KEY.
388 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
390 ASSERT_TRUE(EC_KEY_generate_key(key.get()));
392 EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()),
395 // Get the public key's coordinates.
396 bssl::UniquePtr<BIGNUM> x(BN_new());
398 bssl::UniquePtr<BIGNUM> y(BN_new());
400 bssl::UniquePtr<BIGNUM> p(BN_new());
402 EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
403 group(), EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
405 EC_GROUP_get_curve_GFp(group(), p.get(), nullptr, nullptr, nullptr));
407 // Points on the curve should be accepted.
408 auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group()));
410 EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group(), point.get(), x.get(),
413 // Subtract one from |y| to make the point no longer on the curve.
414 EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one()));
416 // Points not on the curve should be rejected.
417 bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group()));
418 ASSERT_TRUE(invalid_point);
419 EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
420 x.get(), y.get(), nullptr));
422 // Coordinates out of range should be rejected.
423 EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one()));
424 EXPECT_TRUE(BN_add(y.get(), y.get(), p.get()));
426 EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
427 x.get(), y.get(), nullptr));
429 EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
432 TEST_P(ECCurveTest, GenerateFIPS) {
433 // Generate an EC_KEY.
434 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
436 ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()));
439 TEST_P(ECCurveTest, AddingEqualPoints) {
440 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
442 ASSERT_TRUE(EC_KEY_generate_key(key.get()));
444 bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group()));
446 ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
448 bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group()));
450 ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
452 bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group()));
453 ASSERT_TRUE(double_p1);
454 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
456 ASSERT_TRUE(EC_POINT_dbl(group(), double_p1.get(), p1.get(), ctx.get()));
458 bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group()));
459 ASSERT_TRUE(p1_plus_p2);
461 EC_POINT_add(group(), p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
464 EC_POINT_cmp(group(), double_p1.get(), p1_plus_p2.get(), ctx.get()))
468 TEST_P(ECCurveTest, MulZero) {
469 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
471 bssl::UniquePtr<BIGNUM> zero(BN_new());
474 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), zero.get(), nullptr, nullptr,
477 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
478 << "g * 0 did not return point at infinity.";
480 // Test that zero times an arbitrary point is also infinity. The generator is
481 // used as the arbitrary point.
482 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group()));
483 ASSERT_TRUE(generator);
484 ASSERT_TRUE(EC_POINT_mul(group(), generator.get(), BN_value_one(), nullptr,
486 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, generator.get(),
487 zero.get(), nullptr));
489 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
490 << "p * 0 did not return point at infinity.";
493 // Test that multiplying by the order produces ∞ and, moreover, that callers may
494 // do so. |EC_POINT_mul| is almost exclusively used with reduced scalars, with
495 // this exception. This comes from consumers following NIST SP 800-56A section
496 // 5.6.2.3.2. (Though all our curves have cofactor one, so this check isn't
498 TEST_P(ECCurveTest, MulOrder) {
499 // Test that g × order = ∞.
500 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
502 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), EC_GROUP_get0_order(group()),
503 nullptr, nullptr, nullptr));
505 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
506 << "g * order did not return point at infinity.";
508 // Test that p × order = ∞, for some arbitrary p.
509 bssl::UniquePtr<BIGNUM> forty_two(BN_new());
510 ASSERT_TRUE(forty_two);
511 ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
512 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
514 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, point.get(),
515 EC_GROUP_get0_order(group()), nullptr));
517 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
518 << "p * order did not return point at infinity.";
521 // Test that |EC_POINT_mul| works with out-of-range scalars. The operation will
522 // not be constant-time, but we'll compute the right answer.
523 TEST_P(ECCurveTest, MulOutOfRange) {
524 bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(EC_GROUP_get0_order(group())));
525 ASSERT_TRUE(n_minus_one);
526 ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1));
528 bssl::UniquePtr<BIGNUM> minus_one(BN_new());
529 ASSERT_TRUE(minus_one);
530 ASSERT_TRUE(BN_one(minus_one.get()));
531 BN_set_negative(minus_one.get(), 1);
533 bssl::UniquePtr<BIGNUM> seven(BN_new());
535 ASSERT_TRUE(BN_set_word(seven.get(), 7));
537 bssl::UniquePtr<BIGNUM> ten_n_plus_seven(
538 BN_dup(EC_GROUP_get0_order(group())));
539 ASSERT_TRUE(ten_n_plus_seven);
540 ASSERT_TRUE(BN_mul_word(ten_n_plus_seven.get(), 10));
541 ASSERT_TRUE(BN_add_word(ten_n_plus_seven.get(), 7));
543 bssl::UniquePtr<EC_POINT> point1(EC_POINT_new(group())),
544 point2(EC_POINT_new(group()));
548 ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), n_minus_one.get(), nullptr,
550 ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), minus_one.get(), nullptr,
552 EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
553 << "-1 * G and (n-1) * G did not give the same result";
555 ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), seven.get(), nullptr, nullptr,
557 ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), ten_n_plus_seven.get(),
558 nullptr, nullptr, nullptr));
559 EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
560 << "7 * G and (10n + 7) * G did not give the same result";
563 // Test that 10×∞ + G = G.
564 TEST_P(ECCurveTest, Mul) {
565 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
567 bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group()));
569 bssl::UniquePtr<BIGNUM> n(BN_new());
571 ASSERT_TRUE(EC_POINT_set_to_infinity(group(), p.get()));
572 ASSERT_TRUE(BN_set_word(n.get(), 10));
574 // First check that 10×∞ = ∞.
576 EC_POINT_mul(group(), result.get(), nullptr, p.get(), n.get(), nullptr));
577 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), result.get()));
579 // Now check that 10×∞ + G = G.
580 const EC_POINT *generator = EC_GROUP_get0_generator(group());
581 ASSERT_TRUE(EC_POINT_mul(group(), result.get(), BN_value_one(), p.get(),
583 EXPECT_EQ(0, EC_POINT_cmp(group(), result.get(), generator, nullptr));
586 TEST_P(ECCurveTest, MulNonMinimal) {
587 bssl::UniquePtr<BIGNUM> forty_two(BN_new());
588 ASSERT_TRUE(forty_two);
589 ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
592 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
594 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
597 // Compute it again with a non-minimal 42, much larger than the scalar.
598 ASSERT_TRUE(bn_resize_words(forty_two.get(), 64));
600 bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group()));
602 ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), forty_two.get(), nullptr,
604 EXPECT_EQ(0, EC_POINT_cmp(group(), point.get(), point2.get(), nullptr));
607 // Test that EC_KEY_set_private_key rejects invalid values.
608 TEST_P(ECCurveTest, SetInvalidPrivateKey) {
609 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
612 bssl::UniquePtr<BIGNUM> bn(BN_new());
613 ASSERT_TRUE(BN_one(bn.get()));
614 BN_set_negative(bn.get(), 1);
615 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
616 << "Unexpectedly set a key of -1";
620 BN_copy(bn.get(), EC_GROUP_get0_order(EC_KEY_get0_group(key.get()))));
621 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
622 << "Unexpectedly set a key of the group order.";
626 TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
627 bssl::UniquePtr<BIGNUM> forty_two(BN_new());
628 ASSERT_TRUE(forty_two);
629 ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
632 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
634 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
637 // Serialize the point.
638 size_t serialized_len = EC_POINT_point2oct(
639 group(), point.get(), POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
640 ASSERT_NE(0u, serialized_len);
642 std::vector<uint8_t> serialized(serialized_len);
645 EC_POINT_point2oct(group(), point.get(), POINT_CONVERSION_UNCOMPRESSED,
646 serialized.data(), serialized_len, nullptr));
648 // Create a serialized point that is not on the curve.
649 serialized[serialized_len - 1]++;
651 ASSERT_FALSE(EC_POINT_oct2point(group(), point.get(), serialized.data(),
652 serialized.size(), nullptr));
653 // After a failure, |point| should have been set to the generator to defend
654 // against code that doesn't check the return value.
655 ASSERT_EQ(0, EC_POINT_cmp(group(), point.get(),
656 EC_GROUP_get0_generator(group()), nullptr));
659 TEST_P(ECCurveTest, DoubleSpecialCase) {
660 const EC_POINT *g = EC_GROUP_get0_generator(group());
662 bssl::UniquePtr<EC_POINT> two_g(EC_POINT_new(group()));
664 ASSERT_TRUE(EC_POINT_dbl(group(), two_g.get(), g, nullptr));
666 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
668 ASSERT_TRUE(EC_POINT_mul(group(), p.get(), BN_value_one(), g, BN_value_one(),
670 EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
673 ASSERT_TRUE(ec_bignum_to_scalar(group(), &one, BN_value_one()));
675 ec_point_mul_scalar_public(group(), p.get(), &one, g, &one, nullptr));
676 EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
679 // This a regression test for a P-224 bug, but we may as well run it for all
681 TEST_P(ECCurveTest, P224Bug) {
683 const EC_POINT *g = EC_GROUP_get0_generator(group());
684 bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group()));
686 ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr));
688 // Compute 31 * P + 32 * G = G
689 bssl::UniquePtr<EC_POINT> ret(EC_POINT_new(group()));
691 bssl::UniquePtr<BIGNUM> bn31(BN_new()), bn32(BN_new());
694 ASSERT_TRUE(BN_set_word(bn31.get(), 31));
695 ASSERT_TRUE(BN_set_word(bn32.get(), 32));
696 ASSERT_TRUE(EC_POINT_mul(group(), ret.get(), bn32.get(), p.get(), bn31.get(),
699 EXPECT_EQ(0, EC_POINT_cmp(group(), ret.get(), g, nullptr));
702 static std::vector<EC_builtin_curve> AllCurves() {
703 const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
704 std::vector<EC_builtin_curve> curves(num_curves);
705 EC_get_builtin_curves(curves.data(), num_curves);
709 static std::string CurveToString(
710 const testing::TestParamInfo<EC_builtin_curve> ¶ms) {
711 // The comment field contains characters GTest rejects, so use the OBJ name.
712 return OBJ_nid2sn(params.param.nid);
715 INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
718 static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) {
719 std::string curve_name;
720 if (!t->GetAttribute(&curve_name, key)) {
724 if (curve_name == "P-224") {
725 return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp224r1));
727 if (curve_name == "P-256") {
728 return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(
729 NID_X9_62_prime256v1));
731 if (curve_name == "P-384") {
732 return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp384r1));
734 if (curve_name == "P-521") {
735 return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp521r1));
738 t->PrintLine("Unknown curve '%s'", curve_name.c_str());
742 static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) {
743 std::vector<uint8_t> bytes;
744 if (!t->GetBytes(&bytes, key)) {
748 return bssl::UniquePtr<BIGNUM>(
749 BN_bin2bn(bytes.data(), bytes.size(), nullptr));
752 TEST(ECTest, ScalarBaseMultVectors) {
753 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
756 FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
758 bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
760 bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N");
762 bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
764 bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
766 bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get());
768 bssl::UniquePtr<BIGNUM> px(BN_new());
770 bssl::UniquePtr<BIGNUM> py(BN_new());
772 auto check_point = [&](const EC_POINT *p) {
774 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), p));
776 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
777 group.get(), p, px.get(), py.get(), ctx.get()));
778 EXPECT_EQ(0, BN_cmp(x.get(), px.get()));
779 EXPECT_EQ(0, BN_cmp(y.get(), py.get()));
783 const EC_POINT *g = EC_GROUP_get0_generator(group.get());
784 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
786 // Test single-point multiplication.
787 ASSERT_TRUE(EC_POINT_mul(group.get(), p.get(), n.get(), nullptr, nullptr,
789 check_point(p.get());
792 EC_POINT_mul(group.get(), p.get(), nullptr, g, n.get(), ctx.get()));
793 check_point(p.get());
795 // These tests take a very long time, but are worth running when we make
796 // non-trivial changes to the EC code.
798 // Test two-point multiplication.
799 bssl::UniquePtr<BIGNUM> a(BN_new()), b(BN_new());
800 for (int i = -64; i < 64; i++) {
802 ASSERT_TRUE(BN_set_word(a.get(), abs(i)));
804 ASSERT_TRUE(BN_sub(a.get(), EC_GROUP_get0_order(group.get()), a.get()));
807 ASSERT_TRUE(BN_copy(b.get(), n.get()));
808 ASSERT_TRUE(BN_sub(b.get(), b.get(), a.get()));
809 if (BN_is_negative(b.get())) {
810 ASSERT_TRUE(BN_add(b.get(), b.get(), EC_GROUP_get0_order(group.get())));
814 EC_POINT_mul(group.get(), p.get(), a.get(), g, b.get(), ctx.get()));
815 check_point(p.get());
817 EC_SCALAR a_scalar, b_scalar;
818 ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &a_scalar, a.get()));
819 ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &b_scalar, b.get()));
820 ASSERT_TRUE(ec_point_mul_scalar_public(group.get(), p.get(), &a_scalar, g,
821 &b_scalar, ctx.get()));
822 check_point(p.get());