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