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 
TEST(P256_X86_64Test,SelectW5)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 
TEST(P256_X86_64Test,SelectW7)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 
TEST(P256_X86_64Test,BEEU)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 
GetFieldElement(FileTest * t,BN_ULONG out[P256_LIMBS],const char * name)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 
FieldElementToString(const BN_ULONG a[P256_LIMBS])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 
ExpectFieldElementsEqual(const char * expected_expr,const char * actual_expr,const BN_ULONG expected[P256_LIMBS],const BN_ULONG actual[P256_LIMBS])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 
PointToAffine(P256_POINT_AFFINE * out,const P256_POINT * in)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 
ExpectPointsEqual(const char * expected_expr,const char * actual_expr,const P256_POINT_AFFINE * expected,const P256_POINT * actual)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 
TestNegate(FileTest * t)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 
TestMulMont(FileTest * t)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 
TestFromMont(FileTest * t)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 
TestPointAdd(FileTest * t)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 
TestOrdMulMont(FileTest * t)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 
TEST(P256_X86_64Test,TestVectors)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.
TEST(P256_X86_64Test,ABI)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