1 /* Copyright (c) 2014, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include <vector> 20 21 #include <gtest/gtest.h> 22 23 #include <openssl/bn.h> 24 #include <openssl/bytestring.h> 25 #include <openssl/crypto.h> 26 #include <openssl/ec_key.h> 27 #include <openssl/err.h> 28 #include <openssl/mem.h> 29 #include <openssl/nid.h> 30 #include <openssl/obj.h> 31 32 #include "../../test/file_test.h" 33 #include "../../test/test_util.h" 34 #include "../bn/internal.h" 35 #include "internal.h" 36 37 38 // kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field 39 // omitted. 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, 45 }; 46 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, 75 }; 76 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 79 // padding. 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, 88 }; 89 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 92 // padding. 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, 104 }; 105 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, 109 size_t in_len) { 110 CBS cbs; 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) { 114 return nullptr; 115 } 116 return ret; 117 } 118 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) { 122 bssl::ScopedCBB cbb; 123 uint8_t *der; 124 size_t der_len; 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)) { 128 return false; 129 } 130 out->assign(der, der + der_len); 131 OPENSSL_free(der); 132 return true; 133 } 134 135 TEST(ECTest, Encoding) { 136 bssl::UniquePtr<EC_KEY> key = 137 DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic)); 138 ASSERT_TRUE(key); 139 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())); 144 145 const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get()); 146 ASSERT_TRUE(pub_key) << "Public key missing"; 147 148 bssl::UniquePtr<BIGNUM> x(BN_new()); 149 bssl::UniquePtr<BIGNUM> y(BN_new()); 150 ASSERT_TRUE(x); 151 ASSERT_TRUE(y); 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())); 156 ASSERT_TRUE(x_hex); 157 ASSERT_TRUE(y_hex); 158 159 EXPECT_STREQ( 160 "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681", 161 x_hex.get()); 162 EXPECT_STREQ( 163 "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88", 164 y_hex.get()); 165 } 166 167 TEST(ECTest, ZeroPadding) { 168 // Check that the correct encoding round-trips. 169 bssl::UniquePtr<EC_KEY> key = 170 DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros)); 171 ASSERT_TRUE(key); 172 std::vector<uint8_t> out; 173 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 174 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size())); 175 176 // Keys without leading zeros also parse, but they encode correctly. 177 key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros)); 178 ASSERT_TRUE(key); 179 EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 180 EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size())); 181 } 182 183 TEST(ECTest, SpecifiedCurve) { 184 // Test keys with specified curves may be decoded. 185 bssl::UniquePtr<EC_KEY> key = 186 DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve)); 187 ASSERT_TRUE(key); 188 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()))); 192 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())); 197 } 198 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)); 202 ASSERT_TRUE(key); 203 ASSERT_TRUE(EC_KEY_generate_key(key.get())); 204 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, 210 }; 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, 215 }; 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, 220 }; 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, 225 }; 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, 230 }; 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, 235 }; 236 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 237 ASSERT_TRUE(ctx); 238 bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr)); 239 ASSERT_TRUE(p); 240 bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr)); 241 ASSERT_TRUE(a); 242 bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr)); 243 ASSERT_TRUE(b); 244 bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr)); 245 ASSERT_TRUE(gx); 246 bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr)); 247 ASSERT_TRUE(gy); 248 bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr)); 249 ASSERT_TRUE(order); 250 251 bssl::UniquePtr<EC_GROUP> group( 252 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); 253 ASSERT_TRUE(group); 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(), 259 BN_value_one())); 260 261 // |group| should not have a curve name. 262 EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get())); 263 264 // Copy |key| to |key2| using |group|. 265 bssl::UniquePtr<EC_KEY> key2(EC_KEY_new()); 266 ASSERT_TRUE(key2); 267 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 268 ASSERT_TRUE(point); 269 bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new()); 270 ASSERT_TRUE(x); 271 ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get())); 272 ASSERT_TRUE( 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(), 276 y.get(), nullptr)); 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())); 280 281 // The key must be valid according to the new group too. 282 EXPECT_TRUE(EC_KEY_check_key(key2.get())); 283 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())); 287 ASSERT_TRUE(group2); 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())); 294 295 EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL)); 296 EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), NULL)); 297 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())); 301 ASSERT_TRUE(group3); 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())); 308 309 EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL)); 310 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)); 320 321 bssl::UniquePtr<EC_GROUP> group4( 322 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); 323 ASSERT_TRUE(group4); 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())); 330 331 EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group4.get(), NULL)); 332 #endif 333 } 334 335 TEST(ECTest, SetKeyWithoutGroup) { 336 bssl::UniquePtr<EC_KEY> key(EC_KEY_new()); 337 ASSERT_TRUE(key); 338 339 // Private keys may not be configured without a group. 340 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), BN_value_one())); 341 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)); 345 ASSERT_TRUE(group); 346 EXPECT_FALSE( 347 EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(group.get()))); 348 } 349 350 TEST(ECTest, SetNULLKey) { 351 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); 352 ASSERT_TRUE(key); 353 354 EXPECT_TRUE(EC_KEY_set_public_key( 355 key.get(), EC_GROUP_get0_generator(EC_KEY_get0_group(key.get())))); 356 EXPECT_TRUE(EC_KEY_get0_public_key(key.get())); 357 358 // Setting a NULL public-key should clear the public-key and return zero, in 359 // order to match OpenSSL behaviour exactly. 360 EXPECT_FALSE(EC_KEY_set_public_key(key.get(), nullptr)); 361 EXPECT_FALSE(EC_KEY_get0_public_key(key.get())); 362 } 363 364 TEST(ECTest, GroupMismatch) { 365 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1)); 366 ASSERT_TRUE(key); 367 bssl::UniquePtr<EC_GROUP> p256( 368 EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); 369 ASSERT_TRUE(p256); 370 371 // Changing a key's group is invalid. 372 EXPECT_FALSE(EC_KEY_set_group(key.get(), p256.get())); 373 374 // Configuring a public key with the wrong group is invalid. 375 EXPECT_FALSE( 376 EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(p256.get()))); 377 } 378 379 TEST(ECTest, EmptyKey) { 380 bssl::UniquePtr<EC_KEY> key(EC_KEY_new()); 381 ASSERT_TRUE(key); 382 EXPECT_FALSE(EC_KEY_get0_group(key.get())); 383 EXPECT_FALSE(EC_KEY_get0_public_key(key.get())); 384 EXPECT_FALSE(EC_KEY_get0_private_key(key.get())); 385 } 386 387 static bssl::UniquePtr<BIGNUM> HexToBIGNUM(const char *hex) { 388 BIGNUM *bn = nullptr; 389 BN_hex2bn(&bn, hex); 390 return bssl::UniquePtr<BIGNUM>(bn); 391 } 392 393 // Test that point arithmetic works with custom curves using an arbitrary |a|, 394 // rather than -3, as is common (and more efficient). 395 TEST(ECTest, BrainpoolP256r1) { 396 static const char kP[] = 397 "a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377"; 398 static const char kA[] = 399 "7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9"; 400 static const char kB[] = 401 "26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6"; 402 static const char kX[] = 403 "8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262"; 404 static const char kY[] = 405 "547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"; 406 static const char kN[] = 407 "a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7"; 408 static const char kD[] = 409 "0da21d76fed40dd82ac3314cce91abb585b5c4246e902b238a839609ea1e7ce1"; 410 static const char kQX[] = 411 "3a55e0341cab50452fe27b8a87e4775dec7a9daca94b0d84ad1e9f85b53ea513"; 412 static const char kQY[] = 413 "40088146b33bbbe81b092b41146774b35dd478cf056437cfb35ef0df2d269339"; 414 415 bssl::UniquePtr<BIGNUM> p = HexToBIGNUM(kP), a = HexToBIGNUM(kA), 416 b = HexToBIGNUM(kB), x = HexToBIGNUM(kX), 417 y = HexToBIGNUM(kY), n = HexToBIGNUM(kN), 418 d = HexToBIGNUM(kD), qx = HexToBIGNUM(kQX), 419 qy = HexToBIGNUM(kQY); 420 ASSERT_TRUE(p && a && b && x && y && n && d && qx && qy); 421 422 bssl::UniquePtr<EC_GROUP> group( 423 EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), nullptr)); 424 ASSERT_TRUE(group); 425 bssl::UniquePtr<EC_POINT> g(EC_POINT_new(group.get())); 426 ASSERT_TRUE(g); 427 ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), g.get(), x.get(), 428 y.get(), nullptr)); 429 ASSERT_TRUE( 430 EC_GROUP_set_generator(group.get(), g.get(), n.get(), BN_value_one())); 431 432 bssl::UniquePtr<EC_POINT> q(EC_POINT_new(group.get())); 433 ASSERT_TRUE(q); 434 ASSERT_TRUE( 435 EC_POINT_mul(group.get(), q.get(), d.get(), nullptr, nullptr, nullptr)); 436 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(group.get(), q.get(), x.get(), 437 y.get(), nullptr)); 438 EXPECT_EQ(0, BN_cmp(x.get(), qx.get())); 439 EXPECT_EQ(0, BN_cmp(y.get(), qy.get())); 440 } 441 442 class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> { 443 public: 444 const EC_GROUP *group() const { return group_.get(); } 445 446 void SetUp() override { 447 group_.reset(EC_GROUP_new_by_curve_name(GetParam().nid)); 448 ASSERT_TRUE(group_); 449 } 450 451 private: 452 bssl::UniquePtr<EC_GROUP> group_; 453 }; 454 455 TEST_P(ECCurveTest, SetAffine) { 456 // Generate an EC_KEY. 457 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 458 ASSERT_TRUE(key); 459 ASSERT_TRUE(EC_KEY_generate_key(key.get())); 460 461 EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()), 462 nullptr)); 463 464 // Get the public key's coordinates. 465 bssl::UniquePtr<BIGNUM> x(BN_new()); 466 ASSERT_TRUE(x); 467 bssl::UniquePtr<BIGNUM> y(BN_new()); 468 ASSERT_TRUE(y); 469 bssl::UniquePtr<BIGNUM> p(BN_new()); 470 ASSERT_TRUE(p); 471 EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp( 472 group(), EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr)); 473 EXPECT_TRUE( 474 EC_GROUP_get_curve_GFp(group(), p.get(), nullptr, nullptr, nullptr)); 475 476 // Points on the curve should be accepted. 477 auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group())); 478 ASSERT_TRUE(point); 479 EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group(), point.get(), x.get(), 480 y.get(), nullptr)); 481 482 // Subtract one from |y| to make the point no longer on the curve. 483 EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one())); 484 485 // Points not on the curve should be rejected. 486 bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group())); 487 ASSERT_TRUE(invalid_point); 488 EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(), 489 x.get(), y.get(), nullptr)); 490 491 // Coordinates out of range should be rejected. 492 EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one())); 493 EXPECT_TRUE(BN_add(y.get(), y.get(), p.get())); 494 495 EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(), 496 x.get(), y.get(), nullptr)); 497 EXPECT_FALSE( 498 EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get())); 499 } 500 501 TEST_P(ECCurveTest, GenerateFIPS) { 502 // Generate an EC_KEY. 503 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 504 ASSERT_TRUE(key); 505 ASSERT_TRUE(EC_KEY_generate_key_fips(key.get())); 506 } 507 508 TEST_P(ECCurveTest, AddingEqualPoints) { 509 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 510 ASSERT_TRUE(key); 511 ASSERT_TRUE(EC_KEY_generate_key(key.get())); 512 513 bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group())); 514 ASSERT_TRUE(p1); 515 ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get()))); 516 517 bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group())); 518 ASSERT_TRUE(p2); 519 ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get()))); 520 521 bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group())); 522 ASSERT_TRUE(double_p1); 523 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 524 ASSERT_TRUE(ctx); 525 ASSERT_TRUE(EC_POINT_dbl(group(), double_p1.get(), p1.get(), ctx.get())); 526 527 bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group())); 528 ASSERT_TRUE(p1_plus_p2); 529 ASSERT_TRUE( 530 EC_POINT_add(group(), p1_plus_p2.get(), p1.get(), p2.get(), ctx.get())); 531 532 EXPECT_EQ(0, 533 EC_POINT_cmp(group(), double_p1.get(), p1_plus_p2.get(), ctx.get())) 534 << "A+A != 2A"; 535 } 536 537 TEST_P(ECCurveTest, MulZero) { 538 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group())); 539 ASSERT_TRUE(point); 540 bssl::UniquePtr<BIGNUM> zero(BN_new()); 541 ASSERT_TRUE(zero); 542 BN_zero(zero.get()); 543 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), zero.get(), nullptr, nullptr, 544 nullptr)); 545 546 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get())) 547 << "g * 0 did not return point at infinity."; 548 549 // Test that zero times an arbitrary point is also infinity. The generator is 550 // used as the arbitrary point. 551 bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group())); 552 ASSERT_TRUE(generator); 553 ASSERT_TRUE(EC_POINT_mul(group(), generator.get(), BN_value_one(), nullptr, 554 nullptr, nullptr)); 555 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, generator.get(), 556 zero.get(), nullptr)); 557 558 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get())) 559 << "p * 0 did not return point at infinity."; 560 } 561 562 // Test that multiplying by the order produces and, moreover, that callers may 563 // do so. |EC_POINT_mul| is almost exclusively used with reduced scalars, with 564 // this exception. This comes from consumers following NIST SP 800-56A section 565 // 5.6.2.3.2. (Though all our curves have cofactor one, so this check isn't 566 // useful.) 567 TEST_P(ECCurveTest, MulOrder) { 568 // Test that g order = . 569 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group())); 570 ASSERT_TRUE(point); 571 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), EC_GROUP_get0_order(group()), 572 nullptr, nullptr, nullptr)); 573 574 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get())) 575 << "g * order did not return point at infinity."; 576 577 // Test that p order = , for some arbitrary p. 578 bssl::UniquePtr<BIGNUM> forty_two(BN_new()); 579 ASSERT_TRUE(forty_two); 580 ASSERT_TRUE(BN_set_word(forty_two.get(), 42)); 581 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr, 582 nullptr, nullptr)); 583 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, point.get(), 584 EC_GROUP_get0_order(group()), nullptr)); 585 586 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get())) 587 << "p * order did not return point at infinity."; 588 } 589 590 // Test that |EC_POINT_mul| works with out-of-range scalars. The operation will 591 // not be constant-time, but we'll compute the right answer. 592 TEST_P(ECCurveTest, MulOutOfRange) { 593 bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(EC_GROUP_get0_order(group()))); 594 ASSERT_TRUE(n_minus_one); 595 ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1)); 596 597 bssl::UniquePtr<BIGNUM> minus_one(BN_new()); 598 ASSERT_TRUE(minus_one); 599 ASSERT_TRUE(BN_one(minus_one.get())); 600 BN_set_negative(minus_one.get(), 1); 601 602 bssl::UniquePtr<BIGNUM> seven(BN_new()); 603 ASSERT_TRUE(seven); 604 ASSERT_TRUE(BN_set_word(seven.get(), 7)); 605 606 bssl::UniquePtr<BIGNUM> ten_n_plus_seven( 607 BN_dup(EC_GROUP_get0_order(group()))); 608 ASSERT_TRUE(ten_n_plus_seven); 609 ASSERT_TRUE(BN_mul_word(ten_n_plus_seven.get(), 10)); 610 ASSERT_TRUE(BN_add_word(ten_n_plus_seven.get(), 7)); 611 612 bssl::UniquePtr<EC_POINT> point1(EC_POINT_new(group())), 613 point2(EC_POINT_new(group())); 614 ASSERT_TRUE(point1); 615 ASSERT_TRUE(point2); 616 617 ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), n_minus_one.get(), nullptr, 618 nullptr, nullptr)); 619 ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), minus_one.get(), nullptr, 620 nullptr, nullptr)); 621 EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr)) 622 << "-1 * G and (n-1) * G did not give the same result"; 623 624 ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), seven.get(), nullptr, nullptr, 625 nullptr)); 626 ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), ten_n_plus_seven.get(), 627 nullptr, nullptr, nullptr)); 628 EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr)) 629 << "7 * G and (10n + 7) * G did not give the same result"; 630 } 631 632 // Test that 10 + G = G. 633 TEST_P(ECCurveTest, Mul) { 634 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group())); 635 ASSERT_TRUE(p); 636 bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group())); 637 ASSERT_TRUE(result); 638 bssl::UniquePtr<BIGNUM> n(BN_new()); 639 ASSERT_TRUE(n); 640 ASSERT_TRUE(EC_POINT_set_to_infinity(group(), p.get())); 641 ASSERT_TRUE(BN_set_word(n.get(), 10)); 642 643 // First check that 10 = . 644 ASSERT_TRUE( 645 EC_POINT_mul(group(), result.get(), nullptr, p.get(), n.get(), nullptr)); 646 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), result.get())); 647 648 // Now check that 10 + G = G. 649 const EC_POINT *generator = EC_GROUP_get0_generator(group()); 650 ASSERT_TRUE(EC_POINT_mul(group(), result.get(), BN_value_one(), p.get(), 651 n.get(), nullptr)); 652 EXPECT_EQ(0, EC_POINT_cmp(group(), result.get(), generator, nullptr)); 653 } 654 655 TEST_P(ECCurveTest, MulNonMinimal) { 656 bssl::UniquePtr<BIGNUM> forty_two(BN_new()); 657 ASSERT_TRUE(forty_two); 658 ASSERT_TRUE(BN_set_word(forty_two.get(), 42)); 659 660 // Compute g 42. 661 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group())); 662 ASSERT_TRUE(point); 663 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr, 664 nullptr, nullptr)); 665 666 // Compute it again with a non-minimal 42, much larger than the scalar. 667 ASSERT_TRUE(bn_resize_words(forty_two.get(), 64)); 668 669 bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group())); 670 ASSERT_TRUE(point2); 671 ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), forty_two.get(), nullptr, 672 nullptr, nullptr)); 673 EXPECT_EQ(0, EC_POINT_cmp(group(), point.get(), point2.get(), nullptr)); 674 } 675 676 // Test that EC_KEY_set_private_key rejects invalid values. 677 TEST_P(ECCurveTest, SetInvalidPrivateKey) { 678 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 679 ASSERT_TRUE(key); 680 681 bssl::UniquePtr<BIGNUM> bn(BN_new()); 682 ASSERT_TRUE(BN_one(bn.get())); 683 BN_set_negative(bn.get(), 1); 684 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get())) 685 << "Unexpectedly set a key of -1"; 686 ERR_clear_error(); 687 688 ASSERT_TRUE( 689 BN_copy(bn.get(), EC_GROUP_get0_order(EC_KEY_get0_group(key.get())))); 690 EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get())) 691 << "Unexpectedly set a key of the group order."; 692 ERR_clear_error(); 693 } 694 695 TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) { 696 bssl::UniquePtr<BIGNUM> forty_two(BN_new()); 697 ASSERT_TRUE(forty_two); 698 ASSERT_TRUE(BN_set_word(forty_two.get(), 42)); 699 700 // Compute g 42. 701 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group())); 702 ASSERT_TRUE(point); 703 ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr, 704 nullptr, nullptr)); 705 706 // Serialize the point. 707 size_t serialized_len = EC_POINT_point2oct( 708 group(), point.get(), POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr); 709 ASSERT_NE(0u, serialized_len); 710 711 std::vector<uint8_t> serialized(serialized_len); 712 ASSERT_EQ( 713 serialized_len, 714 EC_POINT_point2oct(group(), point.get(), POINT_CONVERSION_UNCOMPRESSED, 715 serialized.data(), serialized_len, nullptr)); 716 717 // Create a serialized point that is not on the curve. 718 serialized[serialized_len - 1]++; 719 720 ASSERT_FALSE(EC_POINT_oct2point(group(), point.get(), serialized.data(), 721 serialized.size(), nullptr)); 722 // After a failure, |point| should have been set to the generator to defend 723 // against code that doesn't check the return value. 724 ASSERT_EQ(0, EC_POINT_cmp(group(), point.get(), 725 EC_GROUP_get0_generator(group()), nullptr)); 726 } 727 728 TEST_P(ECCurveTest, DoubleSpecialCase) { 729 const EC_POINT *g = EC_GROUP_get0_generator(group()); 730 731 bssl::UniquePtr<EC_POINT> two_g(EC_POINT_new(group())); 732 ASSERT_TRUE(two_g); 733 ASSERT_TRUE(EC_POINT_dbl(group(), two_g.get(), g, nullptr)); 734 735 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group())); 736 ASSERT_TRUE(p); 737 ASSERT_TRUE(EC_POINT_mul(group(), p.get(), BN_value_one(), g, BN_value_one(), 738 nullptr)); 739 EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr)); 740 741 EC_SCALAR one; 742 ASSERT_TRUE(ec_bignum_to_scalar(group(), &one, BN_value_one())); 743 ASSERT_TRUE( 744 ec_point_mul_scalar_public(group(), &p->raw, &one, &g->raw, &one)); 745 EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr)); 746 } 747 748 // This a regression test for a P-224 bug, but we may as well run it for all 749 // curves. 750 TEST_P(ECCurveTest, P224Bug) { 751 // P = -G 752 const EC_POINT *g = EC_GROUP_get0_generator(group()); 753 bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group())); 754 ASSERT_TRUE(p); 755 ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr)); 756 757 // Compute 31 * P + 32 * G = G 758 bssl::UniquePtr<EC_POINT> ret(EC_POINT_new(group())); 759 ASSERT_TRUE(ret); 760 bssl::UniquePtr<BIGNUM> bn31(BN_new()), bn32(BN_new()); 761 ASSERT_TRUE(bn31); 762 ASSERT_TRUE(bn32); 763 ASSERT_TRUE(BN_set_word(bn31.get(), 31)); 764 ASSERT_TRUE(BN_set_word(bn32.get(), 32)); 765 ASSERT_TRUE(EC_POINT_mul(group(), ret.get(), bn32.get(), p.get(), bn31.get(), 766 nullptr)); 767 768 EXPECT_EQ(0, EC_POINT_cmp(group(), ret.get(), g, nullptr)); 769 } 770 771 TEST_P(ECCurveTest, GPlusMinusG) { 772 const EC_POINT *g = EC_GROUP_get0_generator(group()); 773 bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group())); 774 ASSERT_TRUE(p); 775 ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr)); 776 bssl::UniquePtr<EC_POINT> sum(EC_POINT_new(group())); 777 778 ASSERT_TRUE(EC_POINT_add(group(), sum.get(), g, p.get(), nullptr)); 779 EXPECT_TRUE(EC_POINT_is_at_infinity(group(), sum.get())); 780 } 781 782 static std::vector<EC_builtin_curve> AllCurves() { 783 const size_t num_curves = EC_get_builtin_curves(nullptr, 0); 784 std::vector<EC_builtin_curve> curves(num_curves); 785 EC_get_builtin_curves(curves.data(), num_curves); 786 return curves; 787 } 788 789 static std::string CurveToString( 790 const testing::TestParamInfo<EC_builtin_curve> ¶ms) { 791 // The comment field contains characters GTest rejects, so use the OBJ name. 792 return OBJ_nid2sn(params.param.nid); 793 } 794 795 INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()), 796 CurveToString); 797 798 static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) { 799 std::string curve_name; 800 if (!t->GetAttribute(&curve_name, key)) { 801 return nullptr; 802 } 803 804 if (curve_name == "P-224") { 805 return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp224r1)); 806 } 807 if (curve_name == "P-256") { 808 return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name( 809 NID_X9_62_prime256v1)); 810 } 811 if (curve_name == "P-384") { 812 return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp384r1)); 813 } 814 if (curve_name == "P-521") { 815 return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp521r1)); 816 } 817 818 t->PrintLine("Unknown curve '%s'", curve_name.c_str()); 819 return nullptr; 820 } 821 822 static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) { 823 std::vector<uint8_t> bytes; 824 if (!t->GetBytes(&bytes, key)) { 825 return nullptr; 826 } 827 828 return bssl::UniquePtr<BIGNUM>( 829 BN_bin2bn(bytes.data(), bytes.size(), nullptr)); 830 } 831 832 TEST(ECTest, ScalarBaseMultVectors) { 833 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 834 ASSERT_TRUE(ctx); 835 836 FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt", 837 [&](FileTest *t) { 838 bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve"); 839 ASSERT_TRUE(group); 840 bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N"); 841 ASSERT_TRUE(n); 842 bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X"); 843 ASSERT_TRUE(x); 844 bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y"); 845 ASSERT_TRUE(y); 846 bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get()); 847 848 bssl::UniquePtr<BIGNUM> px(BN_new()); 849 ASSERT_TRUE(px); 850 bssl::UniquePtr<BIGNUM> py(BN_new()); 851 ASSERT_TRUE(py); 852 auto check_point = [&](const EC_POINT *p) { 853 if (is_infinity) { 854 EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), p)); 855 } else { 856 ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp( 857 group.get(), p, px.get(), py.get(), ctx.get())); 858 EXPECT_EQ(0, BN_cmp(x.get(), px.get())); 859 EXPECT_EQ(0, BN_cmp(y.get(), py.get())); 860 } 861 }; 862 863 const EC_POINT *g = EC_GROUP_get0_generator(group.get()); 864 bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get())); 865 ASSERT_TRUE(p); 866 // Test single-point multiplication. 867 ASSERT_TRUE(EC_POINT_mul(group.get(), p.get(), n.get(), nullptr, nullptr, 868 ctx.get())); 869 check_point(p.get()); 870 871 ASSERT_TRUE( 872 EC_POINT_mul(group.get(), p.get(), nullptr, g, n.get(), ctx.get())); 873 check_point(p.get()); 874 875 // These tests take a very long time, but are worth running when we make 876 // non-trivial changes to the EC code. 877 #if 0 878 // Test two-point multiplication. 879 bssl::UniquePtr<BIGNUM> a(BN_new()), b(BN_new()); 880 for (int i = -64; i < 64; i++) { 881 SCOPED_TRACE(i); 882 ASSERT_TRUE(BN_set_word(a.get(), abs(i))); 883 if (i < 0) { 884 ASSERT_TRUE(BN_sub(a.get(), EC_GROUP_get0_order(group.get()), a.get())); 885 } 886 887 ASSERT_TRUE(BN_copy(b.get(), n.get())); 888 ASSERT_TRUE(BN_sub(b.get(), b.get(), a.get())); 889 if (BN_is_negative(b.get())) { 890 ASSERT_TRUE(BN_add(b.get(), b.get(), EC_GROUP_get0_order(group.get()))); 891 } 892 893 ASSERT_TRUE( 894 EC_POINT_mul(group.get(), p.get(), a.get(), g, b.get(), ctx.get())); 895 check_point(p.get()); 896 897 EC_SCALAR a_scalar, b_scalar; 898 ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &a_scalar, a.get())); 899 ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &b_scalar, b.get())); 900 ASSERT_TRUE(ec_point_mul_scalar_public(group.get(), &p->raw, &a_scalar, &g->raw, 901 &b_scalar)); 902 check_point(p.get()); 903 } 904 #endif 905 }); 906 } 907