blob: 8a215e9139cdf35a42cfe4b91337324c4ff709a1 [file] [log] [blame]
Adam Langleye9ada862015-05-11 17:20:37 -07001/* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15#include <stdio.h>
16#include <string.h>
17
18#include <vector>
19
Robert Sloana94fe052017-02-21 08:49:28 -080020#include <gtest/gtest.h>
21
David Benjaminf0c4a6c2016-08-11 13:26:41 -040022#include <openssl/bn.h>
23#include <openssl/bytestring.h>
Adam Langleye9ada862015-05-11 17:20:37 -070024#include <openssl/crypto.h>
25#include <openssl/ec_key.h>
26#include <openssl/err.h>
27#include <openssl/mem.h>
David Benjaminf0c4a6c2016-08-11 13:26:41 -040028#include <openssl/nid.h>
Robert Sloana94fe052017-02-21 08:49:28 -080029#include <openssl/obj.h>
30
Robert Sloan8542c082018-02-05 09:07:34 -080031#include "../bn/internal.h"
Robert Sloan8ff03552017-06-14 12:40:58 -070032#include "../../test/test_util.h"
Adam Langleye9ada862015-05-11 17:20:37 -070033
Adam Langleye9ada862015-05-11 17:20:37 -070034
Adam Langleye9ada862015-05-11 17:20:37 -070035// kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
36// omitted.
37static const uint8_t kECKeyWithoutPublic[] = {
38 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0,
39 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e,
40 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
41 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
42};
43
David Benjamin4969cc92016-04-22 15:02:23 -040044// kECKeySpecifiedCurve is the above key with P-256's parameters explicitly
45// spelled out rather than using a named curve.
46static const uint8_t kECKeySpecifiedCurve[] = {
47 0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa,
48 0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb,
49 0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc,
50 0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02,
51 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
52 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
58 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
59 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
60 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
61 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
62 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
63 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
64 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
65 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
66 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
67 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
68 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
69 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
70 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
71 0x63, 0x25, 0x51, 0x02, 0x01, 0x01,
72};
73
Adam Langleye9ada862015-05-11 17:20:37 -070074// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
75// the private key is one. The private key is incorrectly encoded without zero
76// padding.
77static const uint8_t kECKeyMissingZeros[] = {
78 0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a,
79 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
80 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
81 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1,
82 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f,
83 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
84 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
85};
86
87// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
88// the private key is one. The private key is encoded with the required zero
89// padding.
90static const uint8_t kECKeyWithZeros[] = {
91 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
94 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1,
95 0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
96 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d,
97 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3,
98 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e,
99 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
100 0x37, 0xbf, 0x51, 0xf5,
101};
102
103// DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
104// result or nullptr on error.
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400105static bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in,
106 size_t in_len) {
David Benjamin4969cc92016-04-22 15:02:23 -0400107 CBS cbs;
108 CBS_init(&cbs, in, in_len);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400109 bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL));
David Benjamin4969cc92016-04-22 15:02:23 -0400110 if (!ret || CBS_len(&cbs) != 0) {
Adam Langleye9ada862015-05-11 17:20:37 -0700111 return nullptr;
112 }
113 return ret;
114}
115
116// EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
117// returns true on success or false on error.
David Benjamin4969cc92016-04-22 15:02:23 -0400118static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
Steven Valdez909b19f2016-11-21 15:35:44 -0500119 bssl::ScopedCBB cbb;
David Benjamin4969cc92016-04-22 15:02:23 -0400120 uint8_t *der;
121 size_t der_len;
122 if (!CBB_init(cbb.get(), 0) ||
123 !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) ||
124 !CBB_finish(cbb.get(), &der, &der_len)) {
125 return false;
126 }
127 out->assign(der, der + der_len);
128 OPENSSL_free(der);
129 return true;
Adam Langleye9ada862015-05-11 17:20:37 -0700130}
131
Robert Sloana94fe052017-02-21 08:49:28 -0800132TEST(ECTest, Encoding) {
133 bssl::UniquePtr<EC_KEY> key =
134 DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
135 ASSERT_TRUE(key);
Adam Langleye9ada862015-05-11 17:20:37 -0700136
Robert Sloana94fe052017-02-21 08:49:28 -0800137 // Test that the encoding round-trips.
Adam Langleye9ada862015-05-11 17:20:37 -0700138 std::vector<uint8_t> out;
Robert Sloana94fe052017-02-21 08:49:28 -0800139 ASSERT_TRUE(EncodeECPrivateKey(&out, key.get()));
140 EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
Adam Langleye9ada862015-05-11 17:20:37 -0700141
142 const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
Robert Sloana94fe052017-02-21 08:49:28 -0800143 ASSERT_TRUE(pub_key) << "Public key missing";
Adam Langleye9ada862015-05-11 17:20:37 -0700144
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400145 bssl::UniquePtr<BIGNUM> x(BN_new());
146 bssl::UniquePtr<BIGNUM> y(BN_new());
Robert Sloana94fe052017-02-21 08:49:28 -0800147 ASSERT_TRUE(x);
148 ASSERT_TRUE(y);
149 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
150 EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL));
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400151 bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
152 bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
Robert Sloana94fe052017-02-21 08:49:28 -0800153 ASSERT_TRUE(x_hex);
154 ASSERT_TRUE(y_hex);
Adam Langleye9ada862015-05-11 17:20:37 -0700155
Robert Sloana94fe052017-02-21 08:49:28 -0800156 EXPECT_STREQ(
157 "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681",
158 x_hex.get());
159 EXPECT_STREQ(
160 "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88",
161 y_hex.get());
Adam Langleye9ada862015-05-11 17:20:37 -0700162}
163
Robert Sloana94fe052017-02-21 08:49:28 -0800164TEST(ECTest, ZeroPadding) {
Adam Langleye9ada862015-05-11 17:20:37 -0700165 // Check that the correct encoding round-trips.
Robert Sloana94fe052017-02-21 08:49:28 -0800166 bssl::UniquePtr<EC_KEY> key =
167 DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros));
168 ASSERT_TRUE(key);
Adam Langleye9ada862015-05-11 17:20:37 -0700169 std::vector<uint8_t> out;
Robert Sloana94fe052017-02-21 08:49:28 -0800170 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
171 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
Adam Langleye9ada862015-05-11 17:20:37 -0700172
173 // Keys without leading zeros also parse, but they encode correctly.
174 key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
Robert Sloana94fe052017-02-21 08:49:28 -0800175 ASSERT_TRUE(key);
176 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
177 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
Adam Langleye9ada862015-05-11 17:20:37 -0700178}
179
Robert Sloana94fe052017-02-21 08:49:28 -0800180TEST(ECTest, SpecifiedCurve) {
David Benjamin4969cc92016-04-22 15:02:23 -0400181 // Test keys with specified curves may be decoded.
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400182 bssl::UniquePtr<EC_KEY> key =
David Benjamin4969cc92016-04-22 15:02:23 -0400183 DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve));
Robert Sloana94fe052017-02-21 08:49:28 -0800184 ASSERT_TRUE(key);
David Benjamin4969cc92016-04-22 15:02:23 -0400185
186 // The group should have been interpreted as P-256.
Robert Sloana94fe052017-02-21 08:49:28 -0800187 EXPECT_EQ(NID_X9_62_prime256v1,
188 EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())));
David Benjamin4969cc92016-04-22 15:02:23 -0400189
190 // Encoding the key should still use named form.
191 std::vector<uint8_t> out;
Robert Sloana94fe052017-02-21 08:49:28 -0800192 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
193 EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
David Benjamin4969cc92016-04-22 15:02:23 -0400194}
195
Robert Sloana94fe052017-02-21 08:49:28 -0800196TEST(ECTest, ArbitraryCurve) {
David Benjamin4969cc92016-04-22 15:02:23 -0400197 // Make a P-256 key and extract the affine coordinates.
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400198 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
Robert Sloana94fe052017-02-21 08:49:28 -0800199 ASSERT_TRUE(key);
200 ASSERT_TRUE(EC_KEY_generate_key(key.get()));
David Benjamin4969cc92016-04-22 15:02:23 -0400201
202 // Make an arbitrary curve which is identical to P-256.
203 static const uint8_t kP[] = {
204 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
206 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
207 };
208 static const uint8_t kA[] = {
209 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
212 };
213 static const uint8_t kB[] = {
214 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
215 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
216 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
217 };
218 static const uint8_t kX[] = {
219 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6,
220 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb,
221 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96,
222 };
223 static const uint8_t kY[] = {
224 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
225 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
226 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
227 };
228 static const uint8_t kOrder[] = {
229 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
230 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
231 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
232 };
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400233 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
Robert Sloana94fe052017-02-21 08:49:28 -0800234 ASSERT_TRUE(ctx);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400235 bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
Robert Sloana94fe052017-02-21 08:49:28 -0800236 ASSERT_TRUE(p);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400237 bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
Robert Sloana94fe052017-02-21 08:49:28 -0800238 ASSERT_TRUE(a);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400239 bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
Robert Sloana94fe052017-02-21 08:49:28 -0800240 ASSERT_TRUE(b);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400241 bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr));
Robert Sloana94fe052017-02-21 08:49:28 -0800242 ASSERT_TRUE(gx);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400243 bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr));
Robert Sloana94fe052017-02-21 08:49:28 -0800244 ASSERT_TRUE(gy);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400245 bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
Robert Sloana94fe052017-02-21 08:49:28 -0800246 ASSERT_TRUE(order);
David Benjamin4969cc92016-04-22 15:02:23 -0400247
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400248 bssl::UniquePtr<EC_GROUP> group(
David Benjamin4969cc92016-04-22 15:02:23 -0400249 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
Robert Sloana94fe052017-02-21 08:49:28 -0800250 ASSERT_TRUE(group);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400251 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
Robert Sloana94fe052017-02-21 08:49:28 -0800252 ASSERT_TRUE(generator);
253 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
254 group.get(), generator.get(), gx.get(), gy.get(), ctx.get()));
255 ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
256 BN_value_one()));
David Benjamin4969cc92016-04-22 15:02:23 -0400257
258 // |group| should not have a curve name.
Robert Sloana94fe052017-02-21 08:49:28 -0800259 EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get()));
David Benjamin4969cc92016-04-22 15:02:23 -0400260
261 // Copy |key| to |key2| using |group|.
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400262 bssl::UniquePtr<EC_KEY> key2(EC_KEY_new());
Robert Sloana94fe052017-02-21 08:49:28 -0800263 ASSERT_TRUE(key2);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400264 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
Robert Sloana94fe052017-02-21 08:49:28 -0800265 ASSERT_TRUE(point);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400266 bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
Robert Sloana94fe052017-02-21 08:49:28 -0800267 ASSERT_TRUE(x);
268 ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get()));
269 ASSERT_TRUE(
270 EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())));
271 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
272 EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(),
273 y.get(), nullptr));
274 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(),
275 x.get(), y.get(), nullptr));
276 ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get()));
David Benjamin4969cc92016-04-22 15:02:23 -0400277
278 // The key must be valid according to the new group too.
Robert Sloana94fe052017-02-21 08:49:28 -0800279 EXPECT_TRUE(EC_KEY_check_key(key2.get()));
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700280
281 // Make a second instance of |group|.
282 bssl::UniquePtr<EC_GROUP> group2(
283 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
284 ASSERT_TRUE(group2);
285 bssl::UniquePtr<EC_POINT> generator2(EC_POINT_new(group2.get()));
286 ASSERT_TRUE(generator2);
287 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
288 group2.get(), generator2.get(), gx.get(), gy.get(), ctx.get()));
289 ASSERT_TRUE(EC_GROUP_set_generator(group2.get(), generator2.get(),
290 order.get(), BN_value_one()));
291
292 EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
293 EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), NULL));
294
295 // group3 uses the wrong generator.
296 bssl::UniquePtr<EC_GROUP> group3(
297 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
298 ASSERT_TRUE(group3);
299 bssl::UniquePtr<EC_POINT> generator3(EC_POINT_new(group3.get()));
300 ASSERT_TRUE(generator3);
301 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
302 group3.get(), generator3.get(), x.get(), y.get(), ctx.get()));
303 ASSERT_TRUE(EC_GROUP_set_generator(group3.get(), generator3.get(),
304 order.get(), BN_value_one()));
305
306 EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL));
David Benjamin4969cc92016-04-22 15:02:23 -0400307}
308
Robert Sloan0da43952018-01-03 15:13:14 -0800309TEST(ECTest, SetKeyWithoutGroup) {
310 bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
311 ASSERT_TRUE(key);
312
313 // Private keys may not be configured without a group.
314 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), BN_value_one()));
315
316 // Public keys may not be configured without a group.
317 bssl::UniquePtr<EC_GROUP> group(
318 EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
319 ASSERT_TRUE(group);
320 EXPECT_FALSE(
321 EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(group.get())));
322}
323
324TEST(ECTest, GroupMismatch) {
325 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
326 ASSERT_TRUE(key);
327 bssl::UniquePtr<EC_GROUP> p256(
328 EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
329 ASSERT_TRUE(p256);
330
331 // Changing a key's group is invalid.
332 EXPECT_FALSE(EC_KEY_set_group(key.get(), p256.get()));
333
334 // Configuring a public key with the wrong group is invalid.
335 EXPECT_FALSE(
336 EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(p256.get())));
337}
338
Robert Sloana94fe052017-02-21 08:49:28 -0800339class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {};
340
341TEST_P(ECCurveTest, SetAffine) {
342 // Generate an EC_KEY.
343 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
344 ASSERT_TRUE(key);
345 ASSERT_TRUE(EC_KEY_generate_key(key.get()));
346
347 const EC_GROUP *const group = EC_KEY_get0_group(key.get());
348 EXPECT_TRUE(
349 EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()), nullptr));
350
351 // Get the public key's coordinates.
352 bssl::UniquePtr<BIGNUM> x(BN_new());
353 ASSERT_TRUE(x);
354 bssl::UniquePtr<BIGNUM> y(BN_new());
355 ASSERT_TRUE(y);
Robert Sloan0db7f542018-01-16 15:48:33 -0800356 bssl::UniquePtr<BIGNUM> p(BN_new());
357 ASSERT_TRUE(p);
Robert Sloana94fe052017-02-21 08:49:28 -0800358 EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
359 group, EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
Robert Sloan0db7f542018-01-16 15:48:33 -0800360 EXPECT_TRUE(
361 EC_GROUP_get_curve_GFp(group, p.get(), nullptr, nullptr, nullptr));
Robert Sloana94fe052017-02-21 08:49:28 -0800362
363 // Points on the curve should be accepted.
364 auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group));
365 ASSERT_TRUE(point);
366 EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(),
367 y.get(), nullptr));
368
369 // Subtract one from |y| to make the point no longer on the curve.
370 EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one()));
371
372 // Points not on the curve should be rejected.
373 bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group));
374 ASSERT_TRUE(invalid_point);
375 EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(),
376 x.get(), y.get(), nullptr));
Robert Sloan0db7f542018-01-16 15:48:33 -0800377
378 // Coordinates out of range should be rejected.
379 EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one()));
380 EXPECT_TRUE(BN_add(y.get(), y.get(), p.get()));
381
382 EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(),
383 x.get(), y.get(), nullptr));
384 EXPECT_FALSE(
385 EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
Robert Sloana94fe052017-02-21 08:49:28 -0800386}
387
Robert Sloan8ff03552017-06-14 12:40:58 -0700388TEST_P(ECCurveTest, GenerateFIPS) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700389 // Generate an EC_KEY.
390 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
391 ASSERT_TRUE(key);
Robert Sloan8ff03552017-06-14 12:40:58 -0700392 ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()));
Robert Sloan572a4e22017-04-17 10:52:19 -0700393}
394
Robert Sloana94fe052017-02-21 08:49:28 -0800395TEST_P(ECCurveTest, AddingEqualPoints) {
396 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
397 ASSERT_TRUE(key);
398 ASSERT_TRUE(EC_KEY_generate_key(key.get()));
David Benjamin4969cc92016-04-22 15:02:23 -0400399
400 const EC_GROUP *const group = EC_KEY_get0_group(key.get());
401
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400402 bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group));
Robert Sloana94fe052017-02-21 08:49:28 -0800403 ASSERT_TRUE(p1);
404 ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
405
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400406 bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group));
Robert Sloana94fe052017-02-21 08:49:28 -0800407 ASSERT_TRUE(p2);
408 ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
409
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400410 bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group));
Robert Sloana94fe052017-02-21 08:49:28 -0800411 ASSERT_TRUE(double_p1);
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400412 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
Robert Sloana94fe052017-02-21 08:49:28 -0800413 ASSERT_TRUE(ctx);
414 ASSERT_TRUE(EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()));
David Benjamin4969cc92016-04-22 15:02:23 -0400415
Robert Sloana94fe052017-02-21 08:49:28 -0800416 bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group));
417 ASSERT_TRUE(p1_plus_p2);
418 ASSERT_TRUE(
419 EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
David Benjamin4969cc92016-04-22 15:02:23 -0400420
Robert Sloana94fe052017-02-21 08:49:28 -0800421 EXPECT_EQ(0,
422 EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()))
423 << "A+A != 2A";
David Benjamin4969cc92016-04-22 15:02:23 -0400424}
425
Robert Sloana94fe052017-02-21 08:49:28 -0800426TEST_P(ECCurveTest, MulZero) {
427 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
428 ASSERT_TRUE(group);
Steven Valdez909b19f2016-11-21 15:35:44 -0500429
430 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
Robert Sloana94fe052017-02-21 08:49:28 -0800431 ASSERT_TRUE(point);
Steven Valdez909b19f2016-11-21 15:35:44 -0500432 bssl::UniquePtr<BIGNUM> zero(BN_new());
Robert Sloana94fe052017-02-21 08:49:28 -0800433 ASSERT_TRUE(zero);
Steven Valdez909b19f2016-11-21 15:35:44 -0500434 BN_zero(zero.get());
Robert Sloana94fe052017-02-21 08:49:28 -0800435 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), zero.get(), nullptr,
436 nullptr, nullptr));
Steven Valdez909b19f2016-11-21 15:35:44 -0500437
Robert Sloana94fe052017-02-21 08:49:28 -0800438 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
439 << "g * 0 did not return point at infinity.";
Steven Valdez909b19f2016-11-21 15:35:44 -0500440
441 // Test that zero times an arbitrary point is also infinity. The generator is
442 // used as the arbitrary point.
443 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
Robert Sloana94fe052017-02-21 08:49:28 -0800444 ASSERT_TRUE(generator);
445 ASSERT_TRUE(EC_POINT_mul(group.get(), generator.get(), BN_value_one(),
446 nullptr, nullptr, nullptr));
447 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, generator.get(),
448 zero.get(), nullptr));
Steven Valdez909b19f2016-11-21 15:35:44 -0500449
Robert Sloana94fe052017-02-21 08:49:28 -0800450 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
451 << "p * 0 did not return point at infinity.";
Steven Valdez909b19f2016-11-21 15:35:44 -0500452}
453
Robert Sloan99319a12017-11-27 10:32:46 -0800454// Test that multiplying by the order produces ∞ and, moreover, that callers may
455// do so. |EC_POINT_mul| is almost exclusively used with reduced scalars, with
456// this exception. This comes from consumers following NIST SP 800-56A section
457// 5.6.2.3.2. (Though all our curves have cofactor one, so this check isn't
458// useful.)
459TEST_P(ECCurveTest, MulOrder) {
460 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
461 ASSERT_TRUE(group);
462
463 // Test that g × order = ∞.
464 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
465 ASSERT_TRUE(point);
466 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(),
467 EC_GROUP_get0_order(group.get()), nullptr, nullptr,
468 nullptr));
469
470 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
471 << "g * order did not return point at infinity.";
472
473 // Test that p × order = ∞, for some arbitrary p.
474 bssl::UniquePtr<BIGNUM> forty_two(BN_new());
475 ASSERT_TRUE(forty_two);
476 ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
477 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr,
478 nullptr, nullptr));
479 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, point.get(),
480 EC_GROUP_get0_order(group.get()), nullptr));
481
482 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
483 << "p * order did not return point at infinity.";
484}
485
Robert Sloana815d5a2017-12-04 11:49:16 -0800486// Test that |EC_POINT_mul| works with out-of-range scalars. Even beyond the
487// usual |bn_correct_top| disclaimer, we completely disclaim all hope here as a
488// reduction is needed, but we'll compute the right answer.
489TEST_P(ECCurveTest, MulOutOfRange) {
490 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
491 ASSERT_TRUE(group);
492
493 bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(EC_GROUP_get0_order(group.get())));
494 ASSERT_TRUE(n_minus_one);
495 ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1));
496
497 bssl::UniquePtr<BIGNUM> minus_one(BN_new());
498 ASSERT_TRUE(minus_one);
499 ASSERT_TRUE(BN_one(minus_one.get()));
500 BN_set_negative(minus_one.get(), 1);
501
502 bssl::UniquePtr<BIGNUM> seven(BN_new());
503 ASSERT_TRUE(seven);
504 ASSERT_TRUE(BN_set_word(seven.get(), 7));
505
506 bssl::UniquePtr<BIGNUM> ten_n_plus_seven(
507 BN_dup(EC_GROUP_get0_order(group.get())));
508 ASSERT_TRUE(ten_n_plus_seven);
509 ASSERT_TRUE(BN_mul_word(ten_n_plus_seven.get(), 10));
510 ASSERT_TRUE(BN_add_word(ten_n_plus_seven.get(), 7));
511
512 bssl::UniquePtr<EC_POINT> point1(EC_POINT_new(group.get())),
513 point2(EC_POINT_new(group.get()));
514 ASSERT_TRUE(point1);
515 ASSERT_TRUE(point2);
516
517 ASSERT_TRUE(EC_POINT_mul(group.get(), point1.get(), n_minus_one.get(),
518 nullptr, nullptr, nullptr));
519 ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), minus_one.get(), nullptr,
520 nullptr, nullptr));
521 EXPECT_EQ(0, EC_POINT_cmp(group.get(), point1.get(), point2.get(), nullptr))
522 << "-1 * G and (n-1) * G did not give the same result";
523
524 ASSERT_TRUE(EC_POINT_mul(group.get(), point1.get(), seven.get(), nullptr,
525 nullptr, nullptr));
526 ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), ten_n_plus_seven.get(),
527 nullptr, nullptr, nullptr));
528 EXPECT_EQ(0, EC_POINT_cmp(group.get(), point1.get(), point2.get(), nullptr))
529 << "7 * G and (10n + 7) * G did not give the same result";
530}
531
Robert Sloana12bf462017-07-17 07:08:26 -0700532// Test that 10×∞ + G = G.
533TEST_P(ECCurveTest, Mul) {
534 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
535 ASSERT_TRUE(group);
536 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
537 ASSERT_TRUE(p);
538 bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group.get()));
539 ASSERT_TRUE(result);
540 bssl::UniquePtr<BIGNUM> n(BN_new());
541 ASSERT_TRUE(n);
542 ASSERT_TRUE(EC_POINT_set_to_infinity(group.get(), p.get()));
543 ASSERT_TRUE(BN_set_word(n.get(), 10));
544
545 // First check that 10×∞ = ∞.
546 ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), nullptr, p.get(), n.get(),
547 nullptr));
548 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), result.get()));
549
550 // Now check that 10×∞ + G = G.
551 const EC_POINT *generator = EC_GROUP_get0_generator(group.get());
552 ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), BN_value_one(), p.get(),
553 n.get(), nullptr));
554 EXPECT_EQ(0, EC_POINT_cmp(group.get(), result.get(), generator, nullptr));
555}
556
Robert Sloan8542c082018-02-05 09:07:34 -0800557#if !defined(BORINGSSL_SHARED_LIBRARY)
558TEST_P(ECCurveTest, MulNonMinimal) {
559 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
560 ASSERT_TRUE(group);
561
562 bssl::UniquePtr<BIGNUM> forty_two(BN_new());
563 ASSERT_TRUE(forty_two);
564 ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
565
566 // Compute g × 42.
567 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
568 ASSERT_TRUE(point);
569 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr,
570 nullptr, nullptr));
571
572 // Compute it again with a non-minimal 42, much larger than the scalar.
573 ASSERT_TRUE(bn_resize_words(forty_two.get(), 64));
574
575 bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group.get()));
576 ASSERT_TRUE(point2);
577 ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), forty_two.get(), nullptr,
578 nullptr, nullptr));
579 EXPECT_EQ(0, EC_POINT_cmp(group.get(), point.get(), point2.get(), nullptr));
580}
581#endif // BORINGSSL_SHARED_LIBRARY
582
Robert Sloancd79cde2017-12-11 09:06:12 -0800583// Test that EC_KEY_set_private_key rejects invalid values.
584TEST_P(ECCurveTest, SetInvalidPrivateKey) {
585 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
586 ASSERT_TRUE(key);
587
588 bssl::UniquePtr<BIGNUM> bn(BN_new());
589 ASSERT_TRUE(BN_one(bn.get()));
590 BN_set_negative(bn.get(), 1);
591 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
592 << "Unexpectedly set a key of -1";
593 ERR_clear_error();
594
595 ASSERT_TRUE(
596 BN_copy(bn.get(), EC_GROUP_get0_order(EC_KEY_get0_group(key.get()))));
597 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
598 << "Unexpectedly set a key of the group order.";
599 ERR_clear_error();
600}
601
Robert Sloan8542c082018-02-05 09:07:34 -0800602TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
603 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
604 ASSERT_TRUE(group);
605
606 bssl::UniquePtr<BIGNUM> forty_two(BN_new());
607 ASSERT_TRUE(forty_two);
608 ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
609
610 // Compute g × 42.
611 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
612 ASSERT_TRUE(point);
613 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr,
614 nullptr, nullptr));
615
616 // Serialize the point.
617 size_t serialized_len =
618 EC_POINT_point2oct(group.get(), point.get(),
619 POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
620 ASSERT_NE(0u, serialized_len);
621
622 std::vector<uint8_t> serialized(serialized_len);
623 ASSERT_EQ(serialized_len,
624 EC_POINT_point2oct(group.get(), point.get(),
625 POINT_CONVERSION_UNCOMPRESSED, serialized.data(),
626 serialized_len, nullptr));
627
628 // Create a serialized point that is not on the curve.
629 serialized[serialized_len - 1]++;
630
631 ASSERT_FALSE(EC_POINT_oct2point(group.get(), point.get(), serialized.data(),
632 serialized.size(), nullptr));
633 // After a failure, |point| should have been set to the generator to defend
634 // against code that doesn't check the return value.
635 ASSERT_EQ(0, EC_POINT_cmp(group.get(), point.get(),
636 EC_GROUP_get0_generator(group.get()), nullptr));
637}
638
Robert Sloana94fe052017-02-21 08:49:28 -0800639static std::vector<EC_builtin_curve> AllCurves() {
David Benjamin4969cc92016-04-22 15:02:23 -0400640 const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
641 std::vector<EC_builtin_curve> curves(num_curves);
642 EC_get_builtin_curves(curves.data(), num_curves);
Robert Sloana94fe052017-02-21 08:49:28 -0800643 return curves;
David Benjamin4969cc92016-04-22 15:02:23 -0400644}
645
Robert Sloana94fe052017-02-21 08:49:28 -0800646static std::string CurveToString(
647 const testing::TestParamInfo<EC_builtin_curve> &params) {
648 // The comment field contains characters GTest rejects, so use the OBJ name.
649 return OBJ_nid2sn(params.param.nid);
Adam Langleye9ada862015-05-11 17:20:37 -0700650}
Robert Sloana94fe052017-02-21 08:49:28 -0800651
652INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
653 CurveToString);