1/* Copyright (c) 2014, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15#include <stdio.h> 16#include <string.h> 17 18#include <vector> 19 20#include <gtest/gtest.h> 21 22#include <openssl/bn.h> 23#include <openssl/bytestring.h> 24#include <openssl/crypto.h> 25#include <openssl/ec_key.h> 26#include <openssl/err.h> 27#include <openssl/mem.h> 28#include <openssl/nid.h> 29#include <openssl/obj.h> 30 31#include "../bn/internal.h" 32#include "../../test/test_util.h" 33 34 35// 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 44// 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 74// 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. 105static bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in, 106 size_t in_len) { 107 CBS cbs; 108 CBS_init(&cbs, in, in_len); 109 bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL)); 110 if (!ret || CBS_len(&cbs) != 0) { 111 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. 118static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) { 119 bssl::ScopedCBB cbb; 120 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; 130} 131 132TEST(ECTest, Encoding) { 133 bssl::UniquePtr<EC_KEY> key = 134 DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic)); 135 ASSERT_TRUE(key); 136 137 // Test that the encoding round-trips. 138 std::vector<uint8_t> out; 139 ASSERT_TRUE(EncodeECPrivateKey(&out, key.get())); 140 EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size())); 141 142 const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get()); 143 ASSERT_TRUE(pub_key) << "Public key missing"; 144 145 bssl::UniquePtr<BIGNUM> x(BN_new()); 146 bssl::UniquePtr<BIGNUM> y(BN_new()); 147 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)); 151 bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get())); 152 bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get())); 153 ASSERT_TRUE(x_hex); 154 ASSERT_TRUE(y_hex); 155 156 EXPECT_STREQ( 157 "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681", 158 x_hex.get()); 159 EXPECT_STREQ( 160 "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88", 161 y_hex.get()); 162} 163 164TEST(ECTest, ZeroPadding) { 165 // Check that the correct encoding round-trips. 166 bssl::UniquePtr<EC_KEY> key = 167 DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros)); 168 ASSERT_TRUE(key); 169 std::vector<uint8_t> out; 170 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 171 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size())); 172 173 // Keys without leading zeros also parse, but they encode correctly. 174 key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros)); 175 ASSERT_TRUE(key); 176 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 177 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size())); 178} 179 180TEST(ECTest, SpecifiedCurve) { 181 // Test keys with specified curves may be decoded. 182 bssl::UniquePtr<EC_KEY> key = 183 DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve)); 184 ASSERT_TRUE(key); 185 186 // The group should have been interpreted as P-256. 187 EXPECT_EQ(NID_X9_62_prime256v1, 188 EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get()))); 189 190 // Encoding the key should still use named form. 191 std::vector<uint8_t> out; 192 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 193 EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size())); 194} 195 196TEST(ECTest, ArbitraryCurve) { 197 // Make a P-256 key and extract the affine coordinates. 198 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); 199 ASSERT_TRUE(key); 200 ASSERT_TRUE(EC_KEY_generate_key(key.get())); 201 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 }; 233 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 234 ASSERT_TRUE(ctx); 235 bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr)); 236 ASSERT_TRUE(p); 237 bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr)); 238 ASSERT_TRUE(a); 239 bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr)); 240 ASSERT_TRUE(b); 241 bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr)); 242 ASSERT_TRUE(gx); 243 bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr)); 244 ASSERT_TRUE(gy); 245 bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr)); 246 ASSERT_TRUE(order); 247 248 bssl::UniquePtr<EC_GROUP> group( 249 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); 250 ASSERT_TRUE(group); 251 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get())); 252 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())); 257 258 // |group| should not have a curve name. 259 EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get())); 260 261 // Copy |key| to |key2| using |group|. 262 bssl::UniquePtr<EC_KEY> key2(EC_KEY_new()); 263 ASSERT_TRUE(key2); 264 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 265 ASSERT_TRUE(point); 266 bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new()); 267 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())); 277 278 // The key must be valid according to the new group too. 279 EXPECT_TRUE(EC_KEY_check_key(key2.get())); 280 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)); 307} 308 309TEST(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 339class 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); 356 bssl::UniquePtr<BIGNUM> p(BN_new()); 357 ASSERT_TRUE(p); 358 EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp( 359 group, EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr)); 360 EXPECT_TRUE( 361 EC_GROUP_get_curve_GFp(group, p.get(), nullptr, nullptr, nullptr)); 362 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)); 377 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())); 386} 387 388TEST_P(ECCurveTest, GenerateFIPS) { 389 // Generate an EC_KEY. 390 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 391 ASSERT_TRUE(key); 392 ASSERT_TRUE(EC_KEY_generate_key_fips(key.get())); 393} 394 395TEST_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())); 399 400 const EC_GROUP *const group = EC_KEY_get0_group(key.get()); 401 402 bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group)); 403 ASSERT_TRUE(p1); 404 ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get()))); 405 406 bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group)); 407 ASSERT_TRUE(p2); 408 ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get()))); 409 410 bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group)); 411 ASSERT_TRUE(double_p1); 412 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 413 ASSERT_TRUE(ctx); 414 ASSERT_TRUE(EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get())); 415 416 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())); 420 421 EXPECT_EQ(0, 422 EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get())) 423 << "A+A != 2A"; 424} 425 426TEST_P(ECCurveTest, MulZero) { 427 bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); 428 ASSERT_TRUE(group); 429 430 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 431 ASSERT_TRUE(point); 432 bssl::UniquePtr<BIGNUM> zero(BN_new()); 433 ASSERT_TRUE(zero); 434 BN_zero(zero.get()); 435 ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), zero.get(), nullptr, 436 nullptr, nullptr)); 437 438 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get())) 439 << "g * 0 did not return point at infinity."; 440 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())); 444 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)); 449 450 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get())) 451 << "p * 0 did not return point at infinity."; 452} 453 454// 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 486// 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 532// 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 557#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 583// 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 602TEST_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 639static std::vector<EC_builtin_curve> AllCurves() { 640 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); 643 return curves; 644} 645 646static std::string CurveToString( 647 const testing::TestParamInfo<EC_builtin_curve> ¶ms) { 648 // The comment field contains characters GTest rejects, so use the OBJ name. 649 return OBJ_nid2sn(params.param.nid); 650} 651 652INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()), 653 CurveToString); 654