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