Bitcoin Core  26.1.0
P2P Digital Currency
field_impl.h
Go to the documentation of this file.
1 /***********************************************************************
2  * Copyright (c) 2013, 2014 Pieter Wuille *
3  * Distributed under the MIT software license, see the accompanying *
4  * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
5  ***********************************************************************/
6 
7 #ifndef SECP256K1_FIELD_IMPL_H
8 #define SECP256K1_FIELD_IMPL_H
9 
10 #include "field.h"
11 #include "util.h"
12 
13 #if defined(SECP256K1_WIDEMUL_INT128)
14 #include "field_5x52_impl.h"
15 #elif defined(SECP256K1_WIDEMUL_INT64)
16 #include "field_10x26_impl.h"
17 #else
18 #error "Please select wide multiplication implementation"
19 #endif
20 
22  secp256k1_fe na;
23 #ifdef VERIFY
28 #endif
29  secp256k1_fe_negate(&na, a, 1);
30  secp256k1_fe_add(&na, b);
32 }
33 
44  secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
45  int j, ret;
46 
47 #ifdef VERIFY
48  VERIFY_CHECK(r != a);
51 #endif
52 
58  secp256k1_fe_sqr(&x2, a);
59  secp256k1_fe_mul(&x2, &x2, a);
60 
61  secp256k1_fe_sqr(&x3, &x2);
62  secp256k1_fe_mul(&x3, &x3, a);
63 
64  x6 = x3;
65  for (j=0; j<3; j++) {
66  secp256k1_fe_sqr(&x6, &x6);
67  }
68  secp256k1_fe_mul(&x6, &x6, &x3);
69 
70  x9 = x6;
71  for (j=0; j<3; j++) {
72  secp256k1_fe_sqr(&x9, &x9);
73  }
74  secp256k1_fe_mul(&x9, &x9, &x3);
75 
76  x11 = x9;
77  for (j=0; j<2; j++) {
78  secp256k1_fe_sqr(&x11, &x11);
79  }
80  secp256k1_fe_mul(&x11, &x11, &x2);
81 
82  x22 = x11;
83  for (j=0; j<11; j++) {
84  secp256k1_fe_sqr(&x22, &x22);
85  }
86  secp256k1_fe_mul(&x22, &x22, &x11);
87 
88  x44 = x22;
89  for (j=0; j<22; j++) {
90  secp256k1_fe_sqr(&x44, &x44);
91  }
92  secp256k1_fe_mul(&x44, &x44, &x22);
93 
94  x88 = x44;
95  for (j=0; j<44; j++) {
96  secp256k1_fe_sqr(&x88, &x88);
97  }
98  secp256k1_fe_mul(&x88, &x88, &x44);
99 
100  x176 = x88;
101  for (j=0; j<88; j++) {
102  secp256k1_fe_sqr(&x176, &x176);
103  }
104  secp256k1_fe_mul(&x176, &x176, &x88);
105 
106  x220 = x176;
107  for (j=0; j<44; j++) {
108  secp256k1_fe_sqr(&x220, &x220);
109  }
110  secp256k1_fe_mul(&x220, &x220, &x44);
111 
112  x223 = x220;
113  for (j=0; j<3; j++) {
114  secp256k1_fe_sqr(&x223, &x223);
115  }
116  secp256k1_fe_mul(&x223, &x223, &x3);
117 
118  /* The final result is then assembled using a sliding window over the blocks. */
119 
120  t1 = x223;
121  for (j=0; j<23; j++) {
122  secp256k1_fe_sqr(&t1, &t1);
123  }
124  secp256k1_fe_mul(&t1, &t1, &x22);
125  for (j=0; j<6; j++) {
126  secp256k1_fe_sqr(&t1, &t1);
127  }
128  secp256k1_fe_mul(&t1, &t1, &x2);
129  secp256k1_fe_sqr(&t1, &t1);
130  secp256k1_fe_sqr(r, &t1);
131 
132  /* Check that a square root was actually calculated */
133 
134  secp256k1_fe_sqr(&t1, r);
135  ret = secp256k1_fe_equal(&t1, a);
136 
137 #ifdef VERIFY
138  if (!ret) {
139  secp256k1_fe_negate(&t1, &t1, 1);
142  }
143 #endif
144  return ret;
145 }
146 
147 #ifndef VERIFY
148 static void secp256k1_fe_verify(const secp256k1_fe *a) { (void)a; }
149 static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) { (void)a; (void)m; }
150 #else
151 static void secp256k1_fe_impl_verify(const secp256k1_fe *a);
152 static void secp256k1_fe_verify(const secp256k1_fe *a) {
153  /* Magnitude between 0 and 32. */
155  /* Normalized is 0 or 1. */
156  VERIFY_CHECK((a->normalized == 0) || (a->normalized == 1));
157  /* If normalized, magnitude must be 0 or 1. */
158  if (a->normalized) secp256k1_fe_verify_magnitude(a, 1);
159  /* Invoke implementation-specific checks. */
160  secp256k1_fe_impl_verify(a);
161 }
162 
163 static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) {
164  VERIFY_CHECK(m >= 0);
165  VERIFY_CHECK(m <= 32);
166  VERIFY_CHECK(a->magnitude <= m);
167 }
168 
173  r->magnitude = 1;
174  r->normalized = 1;
176 }
177 
182  r->magnitude = 1;
184 }
185 
190  r->magnitude = 1;
191  r->normalized = 1;
193 }
194 
199 }
200 
205 }
206 
207 static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a);
208 SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
209  VERIFY_CHECK(0 <= a && a <= 0x7FFF);
211  r->magnitude = (a != 0);
212  r->normalized = 1;
214 }
215 
216 static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a);
217 SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
218  VERIFY_CHECK(0 <= a && a <= 0x7FFF);
221  r->magnitude += 1;
222  r->normalized = 0;
224 }
225 
226 static void secp256k1_fe_impl_clear(secp256k1_fe *a);
228  a->magnitude = 0;
229  a->normalized = 1;
232 }
233 
234 static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a);
237  VERIFY_CHECK(a->normalized);
238  return secp256k1_fe_impl_is_zero(a);
239 }
240 
241 static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a);
244  VERIFY_CHECK(a->normalized);
245  return secp256k1_fe_impl_is_odd(a);
246 }
247 
248 static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
249 SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
252  VERIFY_CHECK(a->normalized);
253  VERIFY_CHECK(b->normalized);
254  return secp256k1_fe_impl_cmp_var(a, b);
255 }
256 
257 static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a);
258 SECP256K1_INLINE static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a) {
260  r->magnitude = 1;
261  r->normalized = 0;
263 }
264 
265 static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a);
266 SECP256K1_INLINE static int secp256k1_fe_set_b32_limit(secp256k1_fe *r, const unsigned char *a) {
268  r->magnitude = 1;
269  r->normalized = 1;
271  return 1;
272  } else {
273  /* Mark the output field element as invalid. */
274  r->magnitude = -1;
275  return 0;
276  }
277 }
278 
279 static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a);
280 SECP256K1_INLINE static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
282  VERIFY_CHECK(a->normalized);
284 }
285 
286 static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m);
289  VERIFY_CHECK(m >= 0 && m <= 31);
292  r->magnitude = m + 1;
293  r->normalized = 0;
295 }
296 
300  VERIFY_CHECK(a >= 0 && a <= 32);
301  VERIFY_CHECK(a*r->magnitude <= 32);
303  r->magnitude *= a;
304  r->normalized = 0;
306 }
307 
308 static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a);
312  VERIFY_CHECK(r->magnitude + a->magnitude <= 32);
313  secp256k1_fe_impl_add(r, a);
314  r->magnitude += a->magnitude;
315  r->normalized = 0;
317 }
318 
325  VERIFY_CHECK(r != b);
326  VERIFY_CHECK(a != b);
327  secp256k1_fe_impl_mul(r, a, b);
328  r->magnitude = 1;
329  r->normalized = 0;
331 }
332 
333 static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a);
337  secp256k1_fe_impl_sqr(r, a);
338  r->magnitude = 1;
339  r->normalized = 0;
341 }
342 
343 static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
344 SECP256K1_INLINE static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
345  VERIFY_CHECK(flag == 0 || flag == 1);
348  secp256k1_fe_impl_cmov(r, a, flag);
349  if (a->magnitude > r->magnitude) r->magnitude = a->magnitude;
350  if (!a->normalized) r->normalized = 0;
352 }
353 
357  VERIFY_CHECK(a->normalized);
359 }
360 
364  r->magnitude = 1;
365  r->normalized = 1;
367 }
368 
369 static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x);
371  int input_is_zero = secp256k1_fe_normalizes_to_zero(x);
373  secp256k1_fe_impl_inv(r, x);
374  r->magnitude = x->magnitude > 0;
375  r->normalized = 1;
376  VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero);
378 }
379 
380 static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x);
382  int input_is_zero = secp256k1_fe_normalizes_to_zero(x);
385  r->magnitude = x->magnitude > 0;
386  r->normalized = 1;
387  VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero);
389 }
390 
391 static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x);
393  int ret;
394  secp256k1_fe tmp = *x, sqrt;
398  VERIFY_CHECK(ret == secp256k1_fe_sqrt(&sqrt, &tmp));
399  return ret;
400 }
401 
402 static void secp256k1_fe_impl_get_bounds(secp256k1_fe* r, int m);
404  VERIFY_CHECK(m >= 0);
405  VERIFY_CHECK(m <= 32);
407  r->magnitude = m;
408  r->normalized = (m == 0);
410 }
411 
412 static void secp256k1_fe_impl_half(secp256k1_fe *r);
417  r->magnitude = (r->magnitude >> 1) + 1;
418  r->normalized = 0;
420 }
421 
422 #endif /* defined(VERIFY) */
423 
424 #endif /* SECP256K1_FIELD_IMPL_H */
#define VERIFY_CHECK(cond)
Definition: util.h:143
static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r)
#define secp256k1_fe_set_b32_mod
Definition: field.h:88
This field implementation represents the value as 10 uint32_t limbs in base 2^26. ...
Definition: field_10x26.h:14
int ret
#define secp256k1_fe_add_int
Definition: field.h:103
#define secp256k1_fe_negate_unchecked
Definition: field.h:91
static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m)
Definition: field_impl.h:149
static SECP256K1_INLINE void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag)
#define secp256k1_fe_set_b32_limit
Definition: field.h:89
static SECP256K1_INLINE void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a)
static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r)
#define secp256k1_fe_is_zero
Definition: field.h:85
#define secp256k1_fe_inv_var
Definition: field.h:100
#define secp256k1_fe_mul
Definition: field.h:94
#define secp256k1_fe_normalizes_to_zero
Definition: field.h:81
static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r)
#define secp256k1_fe_mul_int_unchecked
Definition: field.h:92
static SECP256K1_INLINE void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a)
#define secp256k1_fe_clear
Definition: field.h:84
static SECP256K1_INLINE void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a)
static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a)
static void secp256k1_fe_impl_get_bounds(secp256k1_fe *r, int m)
#define secp256k1_fe_half
Definition: field.h:102
#define secp256k1_fe_is_square_var
Definition: field.h:104
#define secp256k1_fe_sqr
Definition: field.h:95
static void secp256k1_fe_impl_normalize(secp256k1_fe *r)
#define secp256k1_fe_normalize_weak
Definition: field.h:79
static SECP256K1_INLINE int secp256k1_fe_impl_is_zero(const secp256k1_fe *a)
#define secp256k1_fe_add
Definition: field.h:93
static SECP256K1_INLINE int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b)
Definition: field_impl.h:21
static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r)
static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x)
static SECP256K1_INLINE void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a)
static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x)
#define secp256k1_fe_cmov
Definition: field.h:96
#define SECP256K1_INLINE
Definition: util.h:48
static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b)
static SECP256K1_INLINE void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe *SECP256K1_RESTRICT b)
#define secp256k1_fe_normalizes_to_zero_var
Definition: field.h:82
static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r)
static int secp256k1_fe_sqrt(secp256k1_fe *SECP256K1_RESTRICT r, const secp256k1_fe *SECP256K1_RESTRICT a)
Definition: field_impl.h:34
static SECP256K1_INLINE int secp256k1_fe_impl_is_odd(const secp256k1_fe *a)
#define secp256k1_fe_inv
Definition: field.h:99
#define SECP256K1_RESTRICT
Definition: util.h:176
#define secp256k1_fe_is_odd
Definition: field.h:86
static SECP256K1_INLINE void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m)
#define secp256k1_fe_get_bounds
Definition: field.h:101
#define secp256k1_fe_set_int
Definition: field.h:83
static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a)
#define secp256k1_fe_to_storage
Definition: field.h:97
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a)
Convert a field element to a 32-byte big endian value.
static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x)
#define secp256k1_fe_normalize
Definition: field.h:78
#define secp256k1_fe_normalize_var
Definition: field.h:80
#define secp256k1_fe_negate(r, a, m)
Negate a field element.
Definition: field.h:215
static SECP256K1_INLINE void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a)
#define secp256k1_fe_get_b32
Definition: field.h:90
static void secp256k1_fe_verify(const secp256k1_fe *a)
Definition: field_impl.h:148
static SECP256K1_INLINE void secp256k1_fe_impl_clear(secp256k1_fe *a)
#define secp256k1_fe_cmp_var
Definition: field.h:87
static SECP256K1_INLINE void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a)
static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a)
#define secp256k1_fe_from_storage
Definition: field.h:98