Skip to content

Commit b29566c

Browse files
committed
Merge magnitude/normalized fields, move/improve comments
Also split secp256k1_fe_verify into a generic and an implementation specific part.
1 parent 341cc19 commit b29566c

6 files changed

+96
-61
lines changed

src/field.h

+34-11
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)
@@ -34,6 +51,12 @@ static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
3451
0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
3552
);
3653

54+
#ifndef VERIFY
55+
/* In non-VERIFY mode, we #define the fe operations to be identical to their
56+
* internal field implementation, to avoid the potential overhead of a
57+
* function call (even though presumably inlinable). */
58+
#endif /* !defined(VERIFY) */
59+
3760
/** Normalize a field element. This brings the field element to a canonical representation, reduces
3861
* its magnitude to 1, and reduces it modulo field size `p`.
3962
*/

src/field_10x26.h

+20-7
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,28 @@
99

1010
#include <stdint.h>
1111

12+
/** This field implementation represents the value as 10 uint32_t limbs in base
13+
* 2^26. */
1214
typedef struct {
13-
/* X = sum(i=0..9, n[i]*2^(i*26)) mod p
14-
* where p = 2^256 - 0x1000003D1
15-
*/
15+
/* A field element f represents the sum(i=0..9, f.n[i] << (i*26)) mod p,
16+
* where p is the field modulus, 2^256 - 2^32 - 977.
17+
*
18+
* The individual limbs f.n[i] can exceed 2^26; the field's magnitude roughly
19+
* corresponds to how much excess is allowed. The value
20+
* sum(i=0..9, f.n[i] << (i*26)) may exceed p, unless the field element is
21+
* normalized. */
1622
uint32_t n[10];
17-
#ifdef VERIFY
18-
int magnitude;
19-
int normalized;
20-
#endif
23+
/*
24+
* Magnitude m requires:
25+
* n[i] <= 2 * m * (2^26 - 1) for i=0..8
26+
* n[9] <= 2 * m * (2^22 - 1)
27+
*
28+
* Normalized requires:
29+
* n[i] <= (2^26 - 1) for i=0..8
30+
* sum(i=0..9, n[i] << (i*26)) < p
31+
* (together these imply n[9] <= 2^22 - 1)
32+
*/
33+
SECP256K1_FE_VERIFY_FIELDS
2134
} secp256k1_fe;
2235

2336
/* Unpacks a constant into a overlapping multi-limbed FE element. */

src/field_10x26_impl.h

+2-15
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,8 @@
1212
#include "field.h"
1313
#include "modinv32_impl.h"
1414

15-
/** See the comment at the top of field_5x52_impl.h for more details.
16-
*
17-
* Here, we represent field elements as 10 uint32_t's in base 2^26, least significant first,
18-
* where limbs can contain >26 bits.
19-
* A magnitude M means:
20-
* - 2*M*(2^22-1) is the max (inclusive) of the most significant limb
21-
* - 2*M*(2^26-1) is the max (inclusive) of the remaining limbs
22-
*/
23-
24-
static void secp256k1_fe_verify(const secp256k1_fe *a) {
2515
#ifdef VERIFY
16+
static void secp256k1_fe_impl_verify(const secp256k1_fe *a) {
2617
const uint32_t *d = a->n;
2718
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
2819
r &= (d[0] <= 0x3FFFFFFUL * m);
@@ -35,10 +26,7 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) {
3526
r &= (d[7] <= 0x3FFFFFFUL * m);
3627
r &= (d[8] <= 0x3FFFFFFUL * m);
3728
r &= (d[9] <= 0x03FFFFFUL * m);
38-
r &= (a->magnitude >= 0);
39-
r &= (a->magnitude <= 32);
4029
if (a->normalized) {
41-
r &= (a->magnitude <= 1);
4230
if (r && (d[9] == 0x03FFFFFUL)) {
4331
uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2];
4432
if (mid == 0x3FFFFFFUL) {
@@ -47,9 +35,8 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) {
4735
}
4836
}
4937
VERIFY_CHECK(r == 1);
50-
#endif
51-
(void)a;
5238
}
39+
#endif
5340

5441
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
5542
VERIFY_CHECK(m >= 0);

src/field_5x52.h

+20-7
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,28 @@
99

1010
#include <stdint.h>
1111

12+
/** This field implementation represents the value as 5 uint64_t limbs in base
13+
* 2^52. */
1214
typedef struct {
13-
/* X = sum(i=0..4, n[i]*2^(i*52)) mod p
14-
* where p = 2^256 - 0x1000003D1
15-
*/
15+
/* A field element f represents the sum(i=0..4, f.n[i] << (i*52)) mod p,
16+
* where p is the field modulus, 2^256 - 2^32 - 977.
17+
*
18+
* The individual limbs f.n[i] can exceed 2^52; the field's magnitude roughly
19+
* corresponds to how much excess is allowed. The value
20+
* sum(i=0..4, f.n[i] << (i*52)) may exceed p, unless the field element is
21+
* normalized. */
1622
uint64_t n[5];
17-
#ifdef VERIFY
18-
int magnitude;
19-
int normalized;
20-
#endif
23+
/*
24+
* Magnitude m requires:
25+
* n[i] <= 2 * m * (2^52 - 1) for i=0..3
26+
* n[4] <= 2 * m * (2^48 - 1)
27+
*
28+
* Normalized requires:
29+
* n[i] <= (2^52 - 1) for i=0..3
30+
* sum(i=0..4, n[i] << (i*52)) < p
31+
* (together these imply n[4] <= 2^48 - 1)
32+
*/
33+
SECP256K1_FE_VERIFY_FIELDS
2134
} secp256k1_fe;
2235

2336
/* Unpacks a constant into a overlapping multi-limbed FE element. */

src/field_5x52_impl.h

+2-21
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,8 @@
1818
#include "field_5x52_int128_impl.h"
1919
#endif
2020

21-
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
22-
* represented as 5 uint64_t's in base 2^52, least significant first. Note that the limbs are allowed to
23-
* contain >52 bits each.
24-
*
25-
* Each field element has a 'magnitude' associated with it. Internally, a magnitude M means:
26-
* - 2*M*(2^48-1) is the max (inclusive) of the most significant limb
27-
* - 2*M*(2^52-1) is the max (inclusive) of the remaining limbs
28-
*
29-
* Operations have different rules for propagating magnitude to their outputs. If an operation takes a
30-
* magnitude M as a parameter, that means the magnitude of input field elements can be at most M (inclusive).
31-
*
32-
* Each field element also has a 'normalized' flag. A field element is normalized if its magnitude is either
33-
* 0 or 1, and its value is already reduced modulo the order of the field.
34-
*/
35-
36-
static void secp256k1_fe_verify(const secp256k1_fe *a) {
3721
#ifdef VERIFY
22+
static void secp256k1_fe_impl_verify(const secp256k1_fe *a) {
3823
const uint64_t *d = a->n;
3924
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
4025
/* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
@@ -43,18 +28,14 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) {
4328
r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m);
4429
r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m);
4530
r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m);
46-
r &= (a->magnitude >= 0);
47-
r &= (a->magnitude <= 2048);
4831
if (a->normalized) {
49-
r &= (a->magnitude <= 1);
5032
if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) {
5133
r &= (d[0] < 0xFFFFEFFFFFC2FULL);
5234
}
5335
}
5436
VERIFY_CHECK(r == 1);
55-
#endif
56-
(void)a;
5737
}
38+
#endif
5839

5940
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
6041
VERIFY_CHECK(m >= 0);

src/field_impl.h

+18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#ifndef SECP256K1_FIELD_IMPL_H
88
#define SECP256K1_FIELD_IMPL_H
99

10+
#include "field.h"
1011
#include "util.h"
1112

1213
#if defined(SECP256K1_WIDEMUL_INT128)
@@ -131,4 +132,21 @@ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
131132
return secp256k1_fe_equal(&t1, a);
132133
}
133134

135+
#ifndef VERIFY
136+
static void secp256k1_fe_verify(const secp256k1_fe *a) { (void)a; }
137+
#else
138+
static void secp256k1_fe_impl_verify(const secp256k1_fe *a);
139+
static void secp256k1_fe_verify(const secp256k1_fe *a) {
140+
/* Magnitude between 0 and 32. */
141+
int r = (a->magnitude >= 0) & (a->magnitude <= 32);
142+
/* Normalized is 0 or 1. */
143+
r &= (a->normalized == 0) | (a->normalized == 1);
144+
/* If normalized, magnitude must be 0 or 1. */
145+
if (a->normalized) r &= (a->magnitude <= 1);
146+
VERIFY_CHECK(r == 1);
147+
/* Invoke implementation-specific checks. */
148+
secp256k1_fe_impl_verify(a);
149+
}
150+
#endif /* defined(VERIFY) */
151+
134152
#endif /* SECP256K1_FIELD_IMPL_H */

0 commit comments

Comments
 (0)