Home | History | Annotate | Download | only in ec
      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