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