1 /* Copyright (c) 2016, 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 <openssl/base.h> 16 17 #include <stdio.h> 18 #include <string.h> 19 20 #include <gtest/gtest.h> 21 22 #include <openssl/bn.h> 23 #include <openssl/cpu.h> 24 #include <openssl/ec.h> 25 #include <openssl/mem.h> 26 #include <openssl/nid.h> 27 28 #include "internal.h" 29 #include "../bn/internal.h" 30 #include "../../internal.h" 31 #include "../../test/abi_test.h" 32 #include "../../test/file_test.h" 33 #include "../../test/test_util.h" 34 #include "p256-x86_64.h" 35 36 37 // Disable tests if BORINGSSL_SHARED_LIBRARY is defined. These tests need access 38 // to internal functions. 39 #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ 40 !defined(OPENSSL_SMALL) && !defined(BORINGSSL_SHARED_LIBRARY) 41 42 TEST(P256_X86_64Test, SelectW5) { 43 // Fill a table with some garbage input. 44 alignas(64) P256_POINT table[16]; 45 for (size_t i = 0; i < 16; i++) { 46 OPENSSL_memset(table[i].X, 3 * i, sizeof(table[i].X)); 47 OPENSSL_memset(table[i].Y, 3 * i + 1, sizeof(table[i].Y)); 48 OPENSSL_memset(table[i].Z, 3 * i + 2, sizeof(table[i].Z)); 49 } 50 51 for (int i = 0; i <= 16; i++) { 52 P256_POINT val; 53 ecp_nistz256_select_w5(&val, table, i); 54 55 P256_POINT expected; 56 if (i == 0) { 57 OPENSSL_memset(&expected, 0, sizeof(expected)); 58 } else { 59 expected = table[i-1]; 60 } 61 62 EXPECT_EQ(Bytes(reinterpret_cast<const char *>(&expected), sizeof(expected)), 63 Bytes(reinterpret_cast<const char *>(&val), sizeof(val))); 64 } 65 66 // This is a constant-time function, so it is only necessary to instrument one 67 // index for ABI checking. 68 P256_POINT val; 69 CHECK_ABI(ecp_nistz256_select_w5, &val, table, 7); 70 } 71 72 TEST(P256_X86_64Test, SelectW7) { 73 // Fill a table with some garbage input. 74 alignas(64) P256_POINT_AFFINE table[64]; 75 for (size_t i = 0; i < 64; i++) { 76 OPENSSL_memset(table[i].X, 2 * i, sizeof(table[i].X)); 77 OPENSSL_memset(table[i].Y, 2 * i + 1, sizeof(table[i].Y)); 78 } 79 80 for (int i = 0; i <= 64; i++) { 81 P256_POINT_AFFINE val; 82 ecp_nistz256_select_w7(&val, table, i); 83 84 P256_POINT_AFFINE expected; 85 if (i == 0) { 86 OPENSSL_memset(&expected, 0, sizeof(expected)); 87 } else { 88 expected = table[i-1]; 89 } 90 91 EXPECT_EQ(Bytes(reinterpret_cast<const char *>(&expected), sizeof(expected)), 92 Bytes(reinterpret_cast<const char *>(&val), sizeof(val))); 93 } 94 95 // This is a constant-time function, so it is only necessary to instrument one 96 // index for ABI checking. 97 P256_POINT_AFFINE val; 98 CHECK_ABI(ecp_nistz256_select_w7, &val, table, 42); 99 } 100 101 TEST(P256_X86_64Test, BEEU) { 102 if ((OPENSSL_ia32cap_P[1] & (1 << 28)) == 0) { 103 // No AVX support; cannot run the BEEU code. 104 return; 105 } 106 107 bssl::UniquePtr<EC_GROUP> group( 108 EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); 109 ASSERT_TRUE(group); 110 111 BN_ULONG order_words[P256_LIMBS]; 112 ASSERT_TRUE( 113 bn_copy_words(order_words, P256_LIMBS, EC_GROUP_get0_order(group.get()))); 114 115 BN_ULONG in[P256_LIMBS], out[P256_LIMBS]; 116 EC_SCALAR in_scalar, out_scalar, result; 117 OPENSSL_memset(in, 0, sizeof(in)); 118 119 // Trying to find the inverse of zero should fail. 120 ASSERT_FALSE(beeu_mod_inverse_vartime(out, in, order_words)); 121 // This is not a constant-time function, so instrument both zero and a few 122 // inputs below. 123 ASSERT_FALSE(CHECK_ABI(beeu_mod_inverse_vartime, out, in, order_words)); 124 125 // kOneMont is 1, in Montgomery form. 126 static const BN_ULONG kOneMont[P256_LIMBS] = { 127 TOBN(0xc46353d, 0x039cdaaf), 128 TOBN(0x43190552, 0x58e8617b), 129 0, 130 0xffffffff, 131 }; 132 133 for (BN_ULONG i = 1; i < 2000; i++) { 134 SCOPED_TRACE(i); 135 136 in[0] = i; 137 if (i >= 1000) { 138 in[1] = i << 8; 139 in[2] = i << 32; 140 in[3] = i << 48; 141 } else { 142 in[1] = in[2] = in[3] = 0; 143 } 144 145 EXPECT_TRUE(bn_less_than_words(in, order_words, P256_LIMBS)); 146 ASSERT_TRUE(beeu_mod_inverse_vartime(out, in, order_words)); 147 EXPECT_TRUE(bn_less_than_words(out, order_words, P256_LIMBS)); 148 149 // Calculate out*in and confirm that it equals one, modulo the order. 150 OPENSSL_memcpy(in_scalar.bytes, in, sizeof(in)); 151 OPENSSL_memcpy(out_scalar.bytes, out, sizeof(out)); 152 ec_scalar_to_montgomery(group.get(), &in_scalar, &in_scalar); 153 ec_scalar_to_montgomery(group.get(), &out_scalar, &out_scalar); 154 ec_scalar_mul_montgomery(group.get(), &result, &in_scalar, &out_scalar); 155 156 EXPECT_EQ(0, OPENSSL_memcmp(kOneMont, &result, sizeof(kOneMont))); 157 158 // Invert the result and expect to get back to the original value. 159 ASSERT_TRUE(beeu_mod_inverse_vartime(out, out, order_words)); 160 EXPECT_EQ(0, OPENSSL_memcmp(in, out, sizeof(in))); 161 162 if (i < 5) { 163 EXPECT_TRUE(CHECK_ABI(beeu_mod_inverse_vartime, out, in, order_words)); 164 } 165 } 166 } 167 168 static bool GetFieldElement(FileTest *t, BN_ULONG out[P256_LIMBS], 169 const char *name) { 170 std::vector<uint8_t> bytes; 171 if (!t->GetBytes(&bytes, name)) { 172 return false; 173 } 174 175 if (bytes.size() != BN_BYTES * P256_LIMBS) { 176 ADD_FAILURE() << "Invalid length: " << name; 177 return false; 178 } 179 180 // |byte| contains bytes in big-endian while |out| should contain |BN_ULONG|s 181 // in little-endian. 182 OPENSSL_memset(out, 0, P256_LIMBS * sizeof(BN_ULONG)); 183 for (size_t i = 0; i < bytes.size(); i++) { 184 out[P256_LIMBS - 1 - (i / BN_BYTES)] <<= 8; 185 out[P256_LIMBS - 1 - (i / BN_BYTES)] |= bytes[i]; 186 } 187 188 return true; 189 } 190 191 static std::string FieldElementToString(const BN_ULONG a[P256_LIMBS]) { 192 std::string ret; 193 for (size_t i = P256_LIMBS-1; i < P256_LIMBS; i--) { 194 char buf[2 * BN_BYTES + 1]; 195 BIO_snprintf(buf, sizeof(buf), BN_HEX_FMT2, a[i]); 196 ret += buf; 197 } 198 return ret; 199 } 200 201 static testing::AssertionResult ExpectFieldElementsEqual( 202 const char *expected_expr, const char *actual_expr, 203 const BN_ULONG expected[P256_LIMBS], const BN_ULONG actual[P256_LIMBS]) { 204 if (OPENSSL_memcmp(expected, actual, sizeof(BN_ULONG) * P256_LIMBS) == 0) { 205 return testing::AssertionSuccess(); 206 } 207 208 return testing::AssertionFailure() 209 << "Expected: " << FieldElementToString(expected) << " (" 210 << expected_expr << ")\n" 211 << "Actual: " << FieldElementToString(actual) << " (" << actual_expr 212 << ")"; 213 } 214 215 #define EXPECT_FIELD_ELEMENTS_EQUAL(a, b) \ 216 EXPECT_PRED_FORMAT2(ExpectFieldElementsEqual, a, b) 217 218 static bool PointToAffine(P256_POINT_AFFINE *out, const P256_POINT *in) { 219 static const uint8_t kP[] = { 220 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 222 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 223 }; 224 225 bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new()), z(BN_new()); 226 bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr)); 227 if (!x || !y || !z || !p || 228 !bn_set_words(x.get(), in->X, P256_LIMBS) || 229 !bn_set_words(y.get(), in->Y, P256_LIMBS) || 230 !bn_set_words(z.get(), in->Z, P256_LIMBS)) { 231 return false; 232 } 233 234 // Coordinates must be fully-reduced. 235 if (BN_cmp(x.get(), p.get()) >= 0 || 236 BN_cmp(y.get(), p.get()) >= 0 || 237 BN_cmp(z.get(), p.get()) >= 0) { 238 return false; 239 } 240 241 if (BN_is_zero(z.get())) { 242 // The point at infinity is represented as (0, 0). 243 OPENSSL_memset(out, 0, sizeof(P256_POINT_AFFINE)); 244 return true; 245 } 246 247 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 248 bssl::UniquePtr<BN_MONT_CTX> mont( 249 BN_MONT_CTX_new_for_modulus(p.get(), ctx.get())); 250 if (!ctx || !mont || 251 // Invert Z. 252 !BN_from_montgomery(z.get(), z.get(), mont.get(), ctx.get()) || 253 !BN_mod_inverse(z.get(), z.get(), p.get(), ctx.get()) || 254 !BN_to_montgomery(z.get(), z.get(), mont.get(), ctx.get()) || 255 // Convert (X, Y, Z) to (X/Z^2, Y/Z^3). 256 !BN_mod_mul_montgomery(x.get(), x.get(), z.get(), mont.get(), 257 ctx.get()) || 258 !BN_mod_mul_montgomery(x.get(), x.get(), z.get(), mont.get(), 259 ctx.get()) || 260 !BN_mod_mul_montgomery(y.get(), y.get(), z.get(), mont.get(), 261 ctx.get()) || 262 !BN_mod_mul_montgomery(y.get(), y.get(), z.get(), mont.get(), 263 ctx.get()) || 264 !BN_mod_mul_montgomery(y.get(), y.get(), z.get(), mont.get(), 265 ctx.get()) || 266 !bn_copy_words(out->X, P256_LIMBS, x.get()) || 267 !bn_copy_words(out->Y, P256_LIMBS, y.get())) { 268 return false; 269 } 270 return true; 271 } 272 273 static testing::AssertionResult ExpectPointsEqual( 274 const char *expected_expr, const char *actual_expr, 275 const P256_POINT_AFFINE *expected, const P256_POINT *actual) { 276 // There are multiple representations of the same |P256_POINT|, so convert to 277 // |P256_POINT_AFFINE| and compare. 278 P256_POINT_AFFINE affine; 279 if (!PointToAffine(&affine, actual)) { 280 return testing::AssertionFailure() 281 << "Could not convert " << actual_expr << " to affine: (" 282 << FieldElementToString(actual->X) << ", " 283 << FieldElementToString(actual->Y) << ", " 284 << FieldElementToString(actual->Z) << ")"; 285 } 286 287 if (OPENSSL_memcmp(expected, &affine, sizeof(P256_POINT_AFFINE)) != 0) { 288 return testing::AssertionFailure() 289 << "Expected: (" << FieldElementToString(expected->X) << ", " 290 << FieldElementToString(expected->Y) << ") (" << expected_expr 291 << "; affine)\n" 292 << "Actual: (" << FieldElementToString(affine.X) << ", " 293 << FieldElementToString(affine.Y) << ") (" << actual_expr << ")"; 294 } 295 296 return testing::AssertionSuccess(); 297 } 298 299 #define EXPECT_POINTS_EQUAL(a, b) EXPECT_PRED_FORMAT2(ExpectPointsEqual, a, b) 300 301 static void TestNegate(FileTest *t) { 302 BN_ULONG a[P256_LIMBS], b[P256_LIMBS]; 303 ASSERT_TRUE(GetFieldElement(t, a, "A")); 304 ASSERT_TRUE(GetFieldElement(t, b, "B")); 305 306 // Test that -A = B. 307 BN_ULONG ret[P256_LIMBS]; 308 ecp_nistz256_neg(ret, a); 309 EXPECT_FIELD_ELEMENTS_EQUAL(b, ret); 310 311 OPENSSL_memcpy(ret, a, sizeof(ret)); 312 ecp_nistz256_neg(ret, ret /* a */); 313 EXPECT_FIELD_ELEMENTS_EQUAL(b, ret); 314 315 // Test that -B = A. 316 ecp_nistz256_neg(ret, b); 317 EXPECT_FIELD_ELEMENTS_EQUAL(a, ret); 318 319 OPENSSL_memcpy(ret, b, sizeof(ret)); 320 ecp_nistz256_neg(ret, ret /* b */); 321 EXPECT_FIELD_ELEMENTS_EQUAL(a, ret); 322 } 323 324 static void TestMulMont(FileTest *t) { 325 BN_ULONG a[P256_LIMBS], b[P256_LIMBS], result[P256_LIMBS]; 326 ASSERT_TRUE(GetFieldElement(t, a, "A")); 327 ASSERT_TRUE(GetFieldElement(t, b, "B")); 328 ASSERT_TRUE(GetFieldElement(t, result, "Result")); 329 330 BN_ULONG ret[P256_LIMBS]; 331 ecp_nistz256_mul_mont(ret, a, b); 332 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 333 334 ecp_nistz256_mul_mont(ret, b, a); 335 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 336 337 OPENSSL_memcpy(ret, a, sizeof(ret)); 338 ecp_nistz256_mul_mont(ret, ret /* a */, b); 339 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 340 341 OPENSSL_memcpy(ret, a, sizeof(ret)); 342 ecp_nistz256_mul_mont(ret, b, ret); 343 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 344 345 OPENSSL_memcpy(ret, b, sizeof(ret)); 346 ecp_nistz256_mul_mont(ret, a, ret /* b */); 347 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 348 349 OPENSSL_memcpy(ret, b, sizeof(ret)); 350 ecp_nistz256_mul_mont(ret, ret /* b */, a); 351 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 352 353 if (OPENSSL_memcmp(a, b, sizeof(a)) == 0) { 354 ecp_nistz256_sqr_mont(ret, a); 355 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 356 357 OPENSSL_memcpy(ret, a, sizeof(ret)); 358 ecp_nistz256_sqr_mont(ret, ret /* a */); 359 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 360 } 361 } 362 363 static void TestFromMont(FileTest *t) { 364 BN_ULONG a[P256_LIMBS], result[P256_LIMBS]; 365 ASSERT_TRUE(GetFieldElement(t, a, "A")); 366 ASSERT_TRUE(GetFieldElement(t, result, "Result")); 367 368 BN_ULONG ret[P256_LIMBS]; 369 ecp_nistz256_from_mont(ret, a); 370 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 371 372 OPENSSL_memcpy(ret, a, sizeof(ret)); 373 ecp_nistz256_from_mont(ret, ret /* a */); 374 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 375 } 376 377 static void TestPointAdd(FileTest *t) { 378 P256_POINT a, b; 379 P256_POINT_AFFINE result; 380 ASSERT_TRUE(GetFieldElement(t, a.X, "A.X")); 381 ASSERT_TRUE(GetFieldElement(t, a.Y, "A.Y")); 382 ASSERT_TRUE(GetFieldElement(t, a.Z, "A.Z")); 383 ASSERT_TRUE(GetFieldElement(t, b.X, "B.X")); 384 ASSERT_TRUE(GetFieldElement(t, b.Y, "B.Y")); 385 ASSERT_TRUE(GetFieldElement(t, b.Z, "B.Z")); 386 ASSERT_TRUE(GetFieldElement(t, result.X, "Result.X")); 387 ASSERT_TRUE(GetFieldElement(t, result.Y, "Result.Y")); 388 389 P256_POINT ret; 390 ecp_nistz256_point_add(&ret, &a, &b); 391 EXPECT_POINTS_EQUAL(&result, &ret); 392 393 ecp_nistz256_point_add(&ret, &b, &a); 394 EXPECT_POINTS_EQUAL(&result, &ret); 395 396 OPENSSL_memcpy(&ret, &a, sizeof(ret)); 397 ecp_nistz256_point_add(&ret, &ret /* a */, &b); 398 EXPECT_POINTS_EQUAL(&result, &ret); 399 400 OPENSSL_memcpy(&ret, &a, sizeof(ret)); 401 ecp_nistz256_point_add(&ret, &b, &ret /* a */); 402 EXPECT_POINTS_EQUAL(&result, &ret); 403 404 OPENSSL_memcpy(&ret, &b, sizeof(ret)); 405 ecp_nistz256_point_add(&ret, &a, &ret /* b */); 406 EXPECT_POINTS_EQUAL(&result, &ret); 407 408 OPENSSL_memcpy(&ret, &b, sizeof(ret)); 409 ecp_nistz256_point_add(&ret, &ret /* b */, &a); 410 EXPECT_POINTS_EQUAL(&result, &ret); 411 412 P256_POINT_AFFINE a_affine, b_affine, infinity; 413 OPENSSL_memset(&infinity, 0, sizeof(infinity)); 414 ASSERT_TRUE(PointToAffine(&a_affine, &a)); 415 ASSERT_TRUE(PointToAffine(&b_affine, &b)); 416 417 // ecp_nistz256_point_add_affine does not work when a == b unless doubling the 418 // point at infinity. 419 if (OPENSSL_memcmp(&a_affine, &b_affine, sizeof(a_affine)) != 0 || 420 OPENSSL_memcmp(&a_affine, &infinity, sizeof(a_affine)) == 0) { 421 ecp_nistz256_point_add_affine(&ret, &a, &b_affine); 422 EXPECT_POINTS_EQUAL(&result, &ret); 423 424 OPENSSL_memcpy(&ret, &a, sizeof(ret)); 425 ecp_nistz256_point_add_affine(&ret, &ret /* a */, &b_affine); 426 EXPECT_POINTS_EQUAL(&result, &ret); 427 428 ecp_nistz256_point_add_affine(&ret, &b, &a_affine); 429 EXPECT_POINTS_EQUAL(&result, &ret); 430 431 OPENSSL_memcpy(&ret, &b, sizeof(ret)); 432 ecp_nistz256_point_add_affine(&ret, &ret /* b */, &a_affine); 433 EXPECT_POINTS_EQUAL(&result, &ret); 434 } 435 436 if (OPENSSL_memcmp(&a, &b, sizeof(a)) == 0) { 437 ecp_nistz256_point_double(&ret, &a); 438 EXPECT_POINTS_EQUAL(&result, &ret); 439 440 ret = a; 441 ecp_nistz256_point_double(&ret, &ret /* a */); 442 EXPECT_POINTS_EQUAL(&result, &ret); 443 } 444 } 445 446 static void TestOrdMulMont(FileTest *t) { 447 // This test works on scalars rather than field elements, but the 448 // representation is the same. 449 BN_ULONG a[P256_LIMBS], b[P256_LIMBS], result[P256_LIMBS]; 450 ASSERT_TRUE(GetFieldElement(t, a, "A")); 451 ASSERT_TRUE(GetFieldElement(t, b, "B")); 452 ASSERT_TRUE(GetFieldElement(t, result, "Result")); 453 454 BN_ULONG ret[P256_LIMBS]; 455 ecp_nistz256_ord_mul_mont(ret, a, b); 456 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 457 458 ecp_nistz256_ord_mul_mont(ret, b, a); 459 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 460 461 OPENSSL_memcpy(ret, a, sizeof(ret)); 462 ecp_nistz256_ord_mul_mont(ret, ret /* a */, b); 463 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 464 465 OPENSSL_memcpy(ret, a, sizeof(ret)); 466 ecp_nistz256_ord_mul_mont(ret, b, ret); 467 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 468 469 OPENSSL_memcpy(ret, b, sizeof(ret)); 470 ecp_nistz256_ord_mul_mont(ret, a, ret /* b */); 471 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 472 473 OPENSSL_memcpy(ret, b, sizeof(ret)); 474 ecp_nistz256_ord_mul_mont(ret, ret /* b */, a); 475 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 476 477 if (OPENSSL_memcmp(a, b, sizeof(a)) == 0) { 478 ecp_nistz256_ord_sqr_mont(ret, a, 1); 479 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 480 481 OPENSSL_memcpy(ret, a, sizeof(ret)); 482 ecp_nistz256_ord_sqr_mont(ret, ret /* a */, 1); 483 EXPECT_FIELD_ELEMENTS_EQUAL(result, ret); 484 } 485 } 486 487 TEST(P256_X86_64Test, TestVectors) { 488 return FileTestGTest("crypto/fipsmodule/ec/p256-x86_64_tests.txt", 489 [](FileTest *t) { 490 if (t->GetParameter() == "Negate") { 491 TestNegate(t); 492 } else if (t->GetParameter() == "MulMont") { 493 TestMulMont(t); 494 } else if (t->GetParameter() == "FromMont") { 495 TestFromMont(t); 496 } else if (t->GetParameter() == "PointAdd") { 497 TestPointAdd(t); 498 } else if (t->GetParameter() == "OrdMulMont") { 499 TestOrdMulMont(t); 500 } else { 501 FAIL() << "Unknown test type:" << t->GetParameter(); 502 } 503 }); 504 } 505 506 // Instrument the functions covered in TestVectors for ABI checking. 507 TEST(P256_X86_64Test, ABI) { 508 BN_ULONG a[P256_LIMBS], b[P256_LIMBS], c[P256_LIMBS]; 509 OPENSSL_memset(a, 0x01, sizeof(a)); 510 // These functions are all constant-time, so it is only necessary to 511 // instrument one call each for ABI checking. 512 CHECK_ABI(ecp_nistz256_neg, b, a); 513 CHECK_ABI(ecp_nistz256_mul_mont, c, a, b); 514 CHECK_ABI(ecp_nistz256_sqr_mont, c, a); 515 CHECK_ABI(ecp_nistz256_from_mont, c, a); 516 CHECK_ABI(ecp_nistz256_ord_mul_mont, c, a, b); 517 518 // Check a few different loop counts. 519 CHECK_ABI(ecp_nistz256_ord_sqr_mont, b, a, 1); 520 CHECK_ABI(ecp_nistz256_ord_sqr_mont, b, a, 3); 521 522 // Point addition has some special cases around infinity and doubling. Test a 523 // few different scenarios. 524 static const P256_POINT kA = { 525 {TOBN(0x60559ac7, 0xc8d0d89d), TOBN(0x6cda3400, 0x545f7e2c), 526 TOBN(0x9b5159e0, 0x323e6048), TOBN(0xcb8dea33, 0x27057fe6)}, 527 {TOBN(0x81a2d3bc, 0xc93a2d53), TOBN(0x81f40762, 0xa4f33ccf), 528 TOBN(0xc3c3300a, 0xa8ad50ea), TOBN(0x553de89b, 0x31719830)}, 529 {TOBN(0x3fd9470f, 0xb277d181), TOBN(0xc191b8d5, 0x6376f206), 530 TOBN(0xb2572c1f, 0x45eda26f), TOBN(0x4589e40d, 0xf2efc546)}, 531 }; 532 static const P256_POINT kB = { 533 {TOBN(0x3cf0b0aa, 0x92054341), TOBN(0xb949bb80, 0xdab57807), 534 TOBN(0x99de6814, 0xefd21b3e), TOBN(0x32ad5649, 0x7c6c6e83)}, 535 {TOBN(0x06afaa02, 0x688399e0), TOBN(0x75f2d096, 0x2a3ce65c), 536 TOBN(0xf6a31eb7, 0xca0244b3), TOBN(0x57b33b7a, 0xcfeee75e)}, 537 {TOBN(0x7617d2e0, 0xb4f1d35f), TOBN(0xa922cb10, 0x7f592b65), 538 TOBN(0x12fd6c7a, 0x51a2f474), TOBN(0x337d5e1e, 0xc2fc711b)}, 539 }; 540 // This file represents Jacobian infinity as (*, *, 0). 541 static const P256_POINT kInfinity = { 542 {TOBN(0, 0), TOBN(0, 0), TOBN(0, 0), TOBN(0, 0)}, 543 {TOBN(0, 0), TOBN(0, 0), TOBN(0, 0), TOBN(0, 0)}, 544 {TOBN(0, 0), TOBN(0, 0), TOBN(0, 0), TOBN(0, 0)}, 545 }; 546 547 P256_POINT p; 548 CHECK_ABI(ecp_nistz256_point_add, &p, &kA, &kB); 549 CHECK_ABI(ecp_nistz256_point_add, &p, &kA, &kA); 550 OPENSSL_memcpy(&p, &kA, sizeof(P256_POINT)); 551 ecp_nistz256_neg(p.Y, p.Y); 552 CHECK_ABI(ecp_nistz256_point_add, &p, &kA, &p); // A + -A 553 CHECK_ABI(ecp_nistz256_point_add, &p, &kA, &kInfinity); 554 CHECK_ABI(ecp_nistz256_point_add, &p, &kInfinity, &kA); 555 CHECK_ABI(ecp_nistz256_point_add, &p, &kInfinity, &kInfinity); 556 CHECK_ABI(ecp_nistz256_point_double, &p, &kA); 557 CHECK_ABI(ecp_nistz256_point_double, &p, &kInfinity); 558 559 static const P256_POINT_AFFINE kC = { 560 {TOBN(0x7e3ad339, 0xfb3fa5f0), TOBN(0x559d669d, 0xe3a047b2), 561 TOBN(0x8883b298, 0x7042e595), TOBN(0xfabada65, 0x7e477f08)}, 562 {TOBN(0xd9cfceb8, 0xda1c3e85), TOBN(0x80863761, 0x0ce6d6bc), 563 TOBN(0xa8409d84, 0x66034f02), TOBN(0x05519925, 0x31a68d55)}, 564 }; 565 // This file represents affine infinity as (0, 0). 566 static const P256_POINT_AFFINE kInfinityAffine = { 567 {TOBN(0, 0), TOBN(0, 0), TOBN(0, 0), TOBN(0, 0)}, 568 {TOBN(0, 0), TOBN(0, 0), TOBN(0, 0), TOBN(0, 0)}, 569 }; 570 571 CHECK_ABI(ecp_nistz256_point_add_affine, &p, &kA, &kC); 572 CHECK_ABI(ecp_nistz256_point_add_affine, &p, &kA, &kInfinityAffine); 573 CHECK_ABI(ecp_nistz256_point_add_affine, &p, &kInfinity, &kInfinityAffine); 574 CHECK_ABI(ecp_nistz256_point_add_affine, &p, &kInfinity, &kC); 575 } 576 577 #endif 578