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