Skip to content

Commit c63ec88

Browse files
committed
Merge #1066: Abstract out and merge all the magnitude/normalized logic
7fc642f Simplify secp256k1_fe_{impl_,}verify (Pieter Wuille) 4e176ad Abstract out verify logic for fe_is_square_var (Pieter Wuille) 4371f98 Abstract out verify logic for fe_add_int (Pieter Wuille) 89e324c Abstract out verify logic for fe_half (Pieter Wuille) 283cd80 Abstract out verify logic for fe_get_bounds (Pieter Wuille) d5aa2f0 Abstract out verify logic for fe_inv{,_var} (Pieter Wuille) 3167646 Abstract out verify logic for fe_from_storage (Pieter Wuille) 76d31e5 Abstract out verify logic for fe_to_storage (Pieter Wuille) 1e6894b Abstract out verify logic for fe_cmov (Pieter Wuille) be82bd8 Improve comments/checks for fe_sqrt (Pieter Wuille) 6ab3508 Abstract out verify logic for fe_sqr (Pieter Wuille) 4c25f6e Abstract out verify logic for fe_mul (Pieter Wuille) e179e65 Abstract out verify logic for fe_add (Pieter Wuille) 7e7ad7f Abstract out verify logic for fe_mul_int (Pieter Wuille) 65d82a3 Abstract out verify logic for fe_negate (Pieter Wuille) 1446708 Abstract out verify logic for fe_get_b32 (Pieter Wuille) f7a7666 Abstract out verify logic for fe_set_b32 (Pieter Wuille) ce4d209 Abstract out verify logic for fe_cmp_var (Pieter Wuille) 7d7d43c Improve comments/check for fe_equal{,_var} (Pieter Wuille) c5e788d Abstract out verify logic for fe_is_odd (Pieter Wuille) d3f3fe8 Abstract out verify logic for fe_is_zero (Pieter Wuille) c701d9a Abstract out verify logic for fe_clear (Pieter Wuille) 19a2bfe Abstract out verify logic for fe_set_int (Pieter Wuille) 864f9db Abstract out verify logic for fe_normalizes_to_zero{,_var} (Pieter Wuille) 6c31371 Abstract out verify logic for fe_normalize_var (Pieter Wuille) e28b51f Abstract out verify logic for fe_normalize_weak (Pieter Wuille) b6b6f9c Abstract out verify logic for fe_normalize (Pieter Wuille) 7fa5195 Bugfix: correct SECP256K1_FE_CONST mag/norm fields (Pieter Wuille) b29566c Merge magnitude/normalized fields, move/improve comments (Pieter Wuille) Pull request description: Right now, all the logic for propagating/computing the magnitude/normalized fields in `secp256k1_fe` (when `VERIFY` is defined) and the code for checking it, is duplicated across the two field implementations. I believe that is undesirable, as these properties should purely be a function of the performed fe_ functions, and not of the choice of field implementation. This becomes even uglier with #967, which would copy all that, and even needs an additional dimension that would then need to be added to the two other fields. It's also related to #1001, which I think will become easier if it doesn't need to be done/reasoned about separately for every field. This PR moves all logic around these fields (collectively called field verification) to implementations in field_impl.h, which dispatch to renamed functions in field_*_impl.h for the actual implementation. Fixes #1060. ACKs for top commit: jonasnick: ACK 7fc642f real-or-random: ACK 7fc642f Tree-SHA512: 0f94e13fedc47e47859261a182c4077308f8910495691f7e4d7877d9298385172c70e98b4a1e270b6bde4d0062b932607106306bdb35a519cdeab9695a5c71e4
2 parents 341cc19 + 7fc642f commit c63ec88

6 files changed

+665
-523
lines changed

src/field.h

+243-58
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,36 @@
77
#ifndef SECP256K1_FIELD_H
88
#define SECP256K1_FIELD_H
99

10-
/** Field element module.
11-
*
12-
* Field elements can be represented in several ways, but code accessing
13-
* it (and implementations) need to take certain properties into account:
14-
* - Each field element can be normalized or not.
15-
* - Each field element has a magnitude, which represents how far away
16-
* its representation is away from normalization. Normalized elements
17-
* always have a magnitude of 0 or 1, but a magnitude of 1 doesn't
18-
* imply normality.
19-
*/
20-
2110
#include "util.h"
2211

12+
/* This file defines the generic interface for working with secp256k1_fe
13+
* objects, which represent field elements (integers modulo 2^256 - 2^32 - 977).
14+
*
15+
* The actual definition of the secp256k1_fe type depends on the chosen field
16+
* implementation; see the field_5x52.h and field_10x26.h files for details.
17+
*
18+
* All secp256k1_fe objects have implicit properties that determine what
19+
* operations are permitted on it. These are purely a function of what
20+
* secp256k1_fe_ operations are applied on it, generally (implicitly) fixed at
21+
* compile time, and do not depend on the chosen field implementation. Despite
22+
* that, what these properties actually entail for the field representation
23+
* values depends on the chosen field implementation. These properties are:
24+
* - magnitude: an integer in [0,32]
25+
* - normalized: 0 or 1; normalized=1 implies magnitude <= 1.
26+
*
27+
* In VERIFY mode, they are materialized explicitly as fields in the struct,
28+
* allowing run-time verification of these properties. In that case, the field
29+
* implementation also provides a secp256k1_fe_verify routine to verify that
30+
* these fields match the run-time value and perform internal consistency
31+
* checks. */
32+
#ifdef VERIFY
33+
# define SECP256K1_FE_VERIFY_FIELDS \
34+
int magnitude; \
35+
int normalized;
36+
#else
37+
# define SECP256K1_FE_VERIFY_FIELDS
38+
#endif
39+
2340
#if defined(SECP256K1_WIDEMUL_INT128)
2441
#include "field_5x52.h"
2542
#elif defined(SECP256K1_WIDEMUL_INT64)
@@ -28,119 +45,287 @@
2845
#error "Please select wide multiplication implementation"
2946
#endif
3047

48+
#ifdef VERIFY
49+
/* Magnitude and normalized value for constants. */
50+
#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0) \
51+
/* Magnitude is 0 for constant 0; 1 otherwise. */ \
52+
, (((d7) | (d6) | (d5) | (d4) | (d3) | (d2) | (d1) | (d0)) != 0) \
53+
/* Normalized is 1 unless sum(d_i<<(32*i) for i=0..7) exceeds field modulus. */ \
54+
, (!(((d7) & (d6) & (d5) & (d4) & (d3) & (d2)) == 0xfffffffful && ((d1) == 0xfffffffful || ((d1) == 0xfffffffe && (d0 >= 0xfffffc2f)))))
55+
#else
56+
#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0)
57+
#endif
58+
59+
/** This expands to an initializer for a secp256k1_fe valued sum((i*32) * d_i, i=0..7) mod p.
60+
*
61+
* It has magnitude 1, unless d_i are all 0, in which case the magnitude is 0.
62+
* It is normalized, unless sum(2^(i*32) * d_i, i=0..7) >= p.
63+
*
64+
* SECP256K1_FE_CONST_INNER is provided by the implementation.
65+
*/
66+
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) SECP256K1_FE_VERIFY_CONST((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) }
67+
3168
static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
3269
static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
3370
0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
3471
0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
3572
);
3673

37-
/** Normalize a field element. This brings the field element to a canonical representation, reduces
38-
* its magnitude to 1, and reduces it modulo field size `p`.
74+
#ifndef VERIFY
75+
/* In non-VERIFY mode, we #define the fe operations to be identical to their
76+
* internal field implementation, to avoid the potential overhead of a
77+
* function call (even though presumably inlinable). */
78+
# define secp256k1_fe_normalize secp256k1_fe_impl_normalize
79+
# define secp256k1_fe_normalize_weak secp256k1_fe_impl_normalize_weak
80+
# define secp256k1_fe_normalize_var secp256k1_fe_impl_normalize_var
81+
# define secp256k1_fe_normalizes_to_zero secp256k1_fe_impl_normalizes_to_zero
82+
# define secp256k1_fe_normalizes_to_zero_var secp256k1_fe_impl_normalizes_to_zero_var
83+
# define secp256k1_fe_set_int secp256k1_fe_impl_set_int
84+
# define secp256k1_fe_clear secp256k1_fe_impl_clear
85+
# define secp256k1_fe_is_zero secp256k1_fe_impl_is_zero
86+
# define secp256k1_fe_is_odd secp256k1_fe_impl_is_odd
87+
# define secp256k1_fe_cmp_var secp256k1_fe_impl_cmp_var
88+
# define secp256k1_fe_set_b32 secp256k1_fe_impl_set_b32
89+
# define secp256k1_fe_get_b32 secp256k1_fe_impl_get_b32
90+
# define secp256k1_fe_negate secp256k1_fe_impl_negate
91+
# define secp256k1_fe_mul_int secp256k1_fe_impl_mul_int
92+
# define secp256k1_fe_add secp256k1_fe_impl_add
93+
# define secp256k1_fe_mul secp256k1_fe_impl_mul
94+
# define secp256k1_fe_sqr secp256k1_fe_impl_sqr
95+
# define secp256k1_fe_cmov secp256k1_fe_impl_cmov
96+
# define secp256k1_fe_to_storage secp256k1_fe_impl_to_storage
97+
# define secp256k1_fe_from_storage secp256k1_fe_impl_from_storage
98+
# define secp256k1_fe_inv secp256k1_fe_impl_inv
99+
# define secp256k1_fe_inv_var secp256k1_fe_impl_inv_var
100+
# define secp256k1_fe_get_bounds secp256k1_fe_impl_get_bounds
101+
# define secp256k1_fe_half secp256k1_fe_impl_half
102+
# define secp256k1_fe_add_int secp256k1_fe_impl_add_int
103+
# define secp256k1_fe_is_square_var secp256k1_fe_impl_is_square_var
104+
#endif /* !defined(VERIFY) */
105+
106+
/** Normalize a field element.
107+
*
108+
* On input, r must be a valid field element.
109+
* On output, r represents the same value but has normalized=1 and magnitude=1.
39110
*/
40111
static void secp256k1_fe_normalize(secp256k1_fe *r);
41112

42-
/** Weakly normalize a field element: reduce its magnitude to 1, but don't fully normalize. */
113+
/** Give a field element magnitude 1.
114+
*
115+
* On input, r must be a valid field element.
116+
* On output, r represents the same value but has magnitude=1. Normalized is unchanged.
117+
*/
43118
static void secp256k1_fe_normalize_weak(secp256k1_fe *r);
44119

45-
/** Normalize a field element, without constant-time guarantee. */
120+
/** Normalize a field element, without constant-time guarantee.
121+
*
122+
* Identical in behavior to secp256k1_fe_normalize, but not constant time in r.
123+
*/
46124
static void secp256k1_fe_normalize_var(secp256k1_fe *r);
47125

48-
/** Verify whether a field element represents zero i.e. would normalize to a zero value. */
126+
/** Determine whether r represents field element 0.
127+
*
128+
* On input, r must be a valid field element.
129+
* Returns whether r = 0 (mod p).
130+
*/
49131
static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r);
50132

51-
/** Verify whether a field element represents zero i.e. would normalize to a zero value,
52-
* without constant-time guarantee. */
133+
/** Determine whether r represents field element 0, without constant-time guarantee.
134+
*
135+
* Identical in behavior to secp256k1_normalizes_to_zero, but not constant time in r.
136+
*/
53137
static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r);
54138

55-
/** Set a field element equal to a small (not greater than 0x7FFF), non-negative integer.
56-
* Resulting field element is normalized; it has magnitude 0 if a == 0, and magnitude 1 otherwise.
139+
/** Set a field element to an integer in range [0,0x7FFF].
140+
*
141+
* On input, r does not need to be initialized, a must be in [0,0x7FFF].
142+
* On output, r represents value a, is normalized and has magnitude (a!=0).
57143
*/
58144
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
59145

60-
/** Sets a field element equal to zero, initializing all fields. */
146+
/** Set a field element to 0.
147+
*
148+
* On input, a does not need to be initialized.
149+
* On output, a represents 0, is normalized and has magnitude 0.
150+
*/
61151
static void secp256k1_fe_clear(secp256k1_fe *a);
62152

63-
/** Verify whether a field element is zero. Requires the input to be normalized. */
153+
/** Determine whether a represents field element 0.
154+
*
155+
* On input, a must be a valid normalized field element.
156+
* Returns whether a = 0 (mod p).
157+
*
158+
* This behaves identical to secp256k1_normalizes_to_zero{,_var}, but requires
159+
* normalized input (and is much faster).
160+
*/
64161
static int secp256k1_fe_is_zero(const secp256k1_fe *a);
65162

66-
/** Check the "oddness" of a field element. Requires the input to be normalized. */
163+
/** Determine whether a (mod p) is odd.
164+
*
165+
* On input, a must be a valid normalized field element.
166+
* Returns (int(a) mod p) & 1.
167+
*/
67168
static int secp256k1_fe_is_odd(const secp256k1_fe *a);
68169

69-
/** Compare two field elements. Requires magnitude-1 inputs. */
170+
/** Determine whether two field elements are equal.
171+
*
172+
* On input, a and b must be valid field elements with magnitudes not exceeding
173+
* 1 and 31, respectively.
174+
* Returns a = b (mod p).
175+
*/
70176
static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b);
71177

72-
/** Same as secp256k1_fe_equal, but may be variable time. */
178+
/** Determine whether two field elements are equal, without constant-time guarantee.
179+
*
180+
* Identical in behavior to secp256k1_fe_equal, but not constant time in either a or b.
181+
*/
73182
static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b);
74183

75-
/** Compare two field elements. Requires both inputs to be normalized */
184+
/** Compare the values represented by 2 field elements, without constant-time guarantee.
185+
*
186+
* On input, a and b must be valid normalized field elements.
187+
* Returns 1 if a > b, -1 if a < b, and 0 if a = b (comparisons are done as integers
188+
* in range 0..p-1).
189+
*/
76190
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
77191

78-
/** Set a field element equal to 32-byte big endian value.
79-
* Returns 1 if no overflow occurred, and then the output is normalized.
80-
* Returns 0 if overflow occurred, and then the output is only weakly normalized. */
192+
/** Set a field element equal to a provided 32-byte big endian value.
193+
*
194+
* On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
195+
* On output, r = a (mod p). It will have magnitude 1, and if (a < p), it will be normalized.
196+
* If not, it will only be weakly normalized. Returns whether (a < p).
197+
*
198+
* Note that this function is unusual in that the normalization of the output depends on the
199+
* run-time value of a.
200+
*/
81201
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a);
82202

83-
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
203+
/** Convert a field element to 32-byte big endian byte array.
204+
* On input, a must be a valid normalized field element, and r a pointer to a 32-byte array.
205+
* On output, r = a (mod p).
206+
*/
84207
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
85208

86-
/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input
87-
* as an argument. The magnitude of the output is one higher. */
209+
/** Negate a field element.
210+
*
211+
* On input, r does not need to be initialized. a must be a valid field element with
212+
* magnitude not exceeding m. m must be an integer in [0,31].
213+
* Performs {r = -a}.
214+
* On output, r will not be normalized, and will have magnitude m+1.
215+
*/
88216
static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
89217

90-
/** Adds a small integer (up to 0x7FFF) to r. The resulting magnitude increases by one. */
218+
/** Add a small integer to a field element.
219+
*
220+
* Performs {r += a}. The magnitude of r increases by 1, and normalized is cleared.
221+
* a must be in range [0,0xFFFF].
222+
*/
91223
static void secp256k1_fe_add_int(secp256k1_fe *r, int a);
92224

93-
/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
94-
* small integer. */
225+
/** Multiply a field element with a small integer.
226+
*
227+
* On input, r must be a valid field element. a must be an integer in [0,32].
228+
* The magnitude of r times a must not exceed 32.
229+
* Performs {r *= a}.
230+
* On output, r's magnitude is multiplied by a, and r will not be normalized.
231+
*/
95232
static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
96233

97-
/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */
234+
/** Increment a field element by another.
235+
*
236+
* On input, r and a must be valid field elements, not necessarily normalized.
237+
* The sum of their magnitudes must not exceed 32.
238+
* Performs {r += a}.
239+
* On output, r will not be normalized, and will have magnitude incremented by a's.
240+
*/
98241
static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a);
99242

100-
/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
101-
* The output magnitude is 1 (but not guaranteed to be normalized). */
243+
/** Multiply two field elements.
244+
*
245+
* On input, a and b must be valid field elements; r does not need to be initialized.
246+
* r and a may point to the same object, but neither can be equal to b. The magnitudes
247+
* of a and b must not exceed 8.
248+
* Performs {r = a * b}
249+
* On output, r will have magnitude 1, but won't be normalized.
250+
*/
102251
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b);
103252

104-
/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
105-
* The output magnitude is 1 (but not guaranteed to be normalized). */
253+
/** Square a field element.
254+
*
255+
* On input, a must be a valid field element; r does not need to be initialized. The magnitude
256+
* of a must not exceed 8.
257+
* Performs {r = a**2}
258+
* On output, r will have magnitude 1, but won't be normalized.
259+
*/
106260
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
107261

108-
/** If a has a square root, it is computed in r and 1 is returned. If a does not
109-
* have a square root, the root of its negation is computed and 0 is returned.
110-
* The input's magnitude can be at most 8. The output magnitude is 1 (but not
111-
* guaranteed to be normalized). The result in r will always be a square
112-
* itself. */
113-
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a);
262+
/** Compute a square root of a field element.
263+
*
264+
* On input, a must be a valid field element with magnitude<=8; r need not be initialized.
265+
* Performs {r = sqrt(a)} or {r = sqrt(-a)}, whichever exists. The resulting value
266+
* represented by r will be a square itself. Variables r and a must not point to the same object.
267+
* On output, r will have magnitude 1 but will not be normalized.
268+
*/
269+
static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a);
114270

115-
/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
116-
* at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
271+
/** Compute the modular inverse of a field element.
272+
*
273+
* On input, a must be a valid field element; r need not be initialized.
274+
* Performs {r = a**(p-2)} (which maps 0 to 0, and every other element to its
275+
* inverse).
276+
* On output, r will have magnitude (a.magnitude != 0) and be normalized.
277+
*/
117278
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a);
118279

119-
/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */
280+
/** Compute the modular inverse of a field element, without constant-time guarantee.
281+
*
282+
* Behaves identically to secp256k1_fe_inv, but is not constant-time in a.
283+
*/
120284
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a);
121285

122-
/** Convert a field element to the storage type. */
286+
/** Convert a field element to secp256k1_fe_storage.
287+
*
288+
* On input, a must be a valid normalized field element.
289+
* Performs {r = a}.
290+
*/
123291
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a);
124292

125-
/** Convert a field element back from the storage type. */
293+
/** Convert a field element back from secp256k1_fe_storage.
294+
*
295+
* On input, r need not be initialized.
296+
* Performs {r = a}.
297+
* On output, r will be normalized and will have magnitude 1.
298+
*/
126299
static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
127300

128301
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
129302
static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag);
130303

131-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
304+
/** Conditionally move a field element in constant time.
305+
*
306+
* On input, both r and a must be valid field elements. Flag must be 0 or 1.
307+
* Performs {r = flag ? a : r}.
308+
* On output, r's magnitude and normalized will equal a's in case of flag=1, unchanged otherwise.
309+
*/
132310
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
133311

134-
/** Halves the value of a field element modulo the field prime. Constant-time.
135-
* For an input magnitude 'm', the output magnitude is set to 'floor(m/2) + 1'.
136-
* The output is not guaranteed to be normalized, regardless of the input. */
312+
/** Halve the value of a field element modulo the field prime in constant-time.
313+
*
314+
* On input, r must be a valid field element.
315+
* On output, r will be normalized and have magnitude floor(m/2) + 1 where m is
316+
* the magnitude of r on input.
317+
*/
137318
static void secp256k1_fe_half(secp256k1_fe *r);
138319

139-
/** Sets each limb of 'r' to its upper bound at magnitude 'm'. The output will also have its
140-
* magnitude set to 'm' and is normalized if (and only if) 'm' is zero. */
320+
/** Sets r to a field element with magnitude m, normalized if (and only if) m==0.
321+
* The value is chosen so that it is likely to trigger edge cases related to
322+
* internal overflows. */
141323
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m);
142324

143-
/** Determine whether a is a square (modulo p). */
325+
/** Determine whether a is a square (modulo p).
326+
*
327+
* On input, a must be a valid field element.
328+
*/
144329
static int secp256k1_fe_is_square_var(const secp256k1_fe *a);
145330

146331
/** Check invariants on a field element (no-op unless VERIFY is enabled). */

0 commit comments

Comments
 (0)