Skip to content

Commit d64bb5d

Browse files
committed
Add fe_half tests for worst-case inputs
- Add field method _fe_get_bounds
1 parent 4eb8b93 commit d64bb5d

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

src/field.h

+4
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,8 @@ static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
135135
* The output is not guaranteed to be normalized, regardless of the input. */
136136
static void secp256k1_fe_half(secp256k1_fe *r);
137137

138+
/** Sets each limb of 'r' to its upper bound at magnitude 'm'. The output will also have its
139+
* magnitude set to 'm' and is normalized if (and only if) 'm' is zero. */
140+
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m);
141+
138142
#endif /* SECP256K1_FIELD_H */

src/field_10x26_impl.h

+20
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) {
4949
}
5050
#endif
5151

52+
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
53+
VERIFY_CHECK(m >= 0);
54+
VERIFY_CHECK(m <= 2048);
55+
r->n[0] = 0x3FFFFFFUL * 2 * m;
56+
r->n[1] = 0x3FFFFFFUL * 2 * m;
57+
r->n[2] = 0x3FFFFFFUL * 2 * m;
58+
r->n[3] = 0x3FFFFFFUL * 2 * m;
59+
r->n[4] = 0x3FFFFFFUL * 2 * m;
60+
r->n[5] = 0x3FFFFFFUL * 2 * m;
61+
r->n[6] = 0x3FFFFFFUL * 2 * m;
62+
r->n[7] = 0x3FFFFFFUL * 2 * m;
63+
r->n[8] = 0x3FFFFFFUL * 2 * m;
64+
r->n[9] = 0x03FFFFFUL * 2 * m;
65+
#ifdef VERIFY
66+
r->magnitude = m;
67+
r->normalized = (m == 0);
68+
secp256k1_fe_verify(r);
69+
#endif
70+
}
71+
5272
static void secp256k1_fe_normalize(secp256k1_fe *r) {
5373
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
5474
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];

src/field_5x52_impl.h

+15
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) {
5858
}
5959
#endif
6060

61+
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
62+
VERIFY_CHECK(m >= 0);
63+
VERIFY_CHECK(m <= 2048);
64+
r->n[0] = 0xFFFFFFFFFFFFFULL * 2 * m;
65+
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * m;
66+
r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * m;
67+
r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * m;
68+
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * m;
69+
#ifdef VERIFY
70+
r->magnitude = m;
71+
r->normalized = (m == 0);
72+
secp256k1_fe_verify(r);
73+
#endif
74+
}
75+
6176
static void secp256k1_fe_normalize(secp256k1_fe *r) {
6277
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
6378

src/tests.c

+50
Original file line numberDiff line numberDiff line change
@@ -2471,6 +2471,55 @@ int fe_identical(const secp256k1_fe *a, const secp256k1_fe *b) {
24712471
return ret;
24722472
}
24732473

2474+
void run_field_half(void) {
2475+
secp256k1_fe t, u;
2476+
int m;
2477+
2478+
/* Check magnitude 0 input */
2479+
secp256k1_fe_get_bounds(&t, 0);
2480+
secp256k1_fe_half(&t);
2481+
#ifdef VERIFY
2482+
CHECK(t.magnitude == 1);
2483+
CHECK(t.normalized == 0);
2484+
#endif
2485+
CHECK(secp256k1_fe_normalizes_to_zero(&t));
2486+
2487+
/* Check non-zero magnitudes in the supported range */
2488+
for (m = 1; m < 32; m++) {
2489+
/* Check max-value input */
2490+
secp256k1_fe_get_bounds(&t, m);
2491+
2492+
u = t;
2493+
secp256k1_fe_half(&u);
2494+
#ifdef VERIFY
2495+
CHECK(u.magnitude == (m >> 1) + 1);
2496+
CHECK(u.normalized == 0);
2497+
#endif
2498+
secp256k1_fe_normalize_weak(&u);
2499+
secp256k1_fe_add(&u, &u);
2500+
CHECK(check_fe_equal(&t, &u));
2501+
2502+
/* Check worst-case input: ensure the LSB is 1 so that P will be added,
2503+
* which will also cause all carries to be 1, since all limbs that can
2504+
* generate a carry are initially even and all limbs of P are odd in
2505+
* every existing field implementation. */
2506+
secp256k1_fe_get_bounds(&t, m);
2507+
CHECK(t.n[0] > 0);
2508+
CHECK((t.n[0] & 1) == 0);
2509+
--t.n[0];
2510+
2511+
u = t;
2512+
secp256k1_fe_half(&u);
2513+
#ifdef VERIFY
2514+
CHECK(u.magnitude == (m >> 1) + 1);
2515+
CHECK(u.normalized == 0);
2516+
#endif
2517+
secp256k1_fe_normalize_weak(&u);
2518+
secp256k1_fe_add(&u, &u);
2519+
CHECK(check_fe_equal(&t, &u));
2520+
}
2521+
}
2522+
24742523
void run_field_misc(void) {
24752524
secp256k1_fe x;
24762525
secp256k1_fe y;
@@ -6924,6 +6973,7 @@ int main(int argc, char **argv) {
69246973
run_scalar_tests();
69256974

69266975
/* field tests */
6976+
run_field_half();
69276977
run_field_misc();
69286978
run_field_convert();
69296979
run_fe_mul();

0 commit comments

Comments
 (0)