]>
Commit | Line | Data |
---|---|---|
0a433ea2 PW |
1 | // Copyright (c) 2013 Pieter Wuille |
2 | // Distributed under the MIT/X11 software license, see the accompanying | |
3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | |
4 | ||
7a4b7691 PW |
5 | #ifndef _SECP256K1_FIELD_REPR_IMPL_H_ |
6 | #define _SECP256K1_FIELD_REPR_IMPL_H_ | |
7 | ||
78cd96b1 CF |
8 | #if defined HAVE_CONFIG_H |
9 | #include "libsecp256k1-config.h" | |
10 | #endif | |
11 | ||
e6d142a8 | 12 | #include <assert.h> |
910d0de4 | 13 | #include <string.h> |
1c7fa133 | 14 | #include "util.h" |
11ab5622 PW |
15 | #include "num.h" |
16 | #include "field.h" | |
e6d142a8 | 17 | |
f0c89aad | 18 | #if defined(USE_FIELD_5X52_ASM) |
11ab5622 | 19 | #include "field_5x52_asm_impl.h" |
f0c89aad | 20 | #elif defined(USE_FIELD_5X52_INT128) |
11ab5622 | 21 | #include "field_5x52_int128_impl.h" |
f0c89aad PW |
22 | #else |
23 | #error "Please select field_5x52 implementation" | |
e6d142a8 PW |
24 | #endif |
25 | ||
e6d142a8 PW |
26 | /** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F, |
27 | * represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, | |
28 | * each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element | |
29 | * is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations | |
30 | * accept any input with magnitude at most M, and have different rules for propagating magnitude to their | |
31 | * output. | |
32 | */ | |
33 | ||
6baf08df PW |
34 | void static secp256k1_fe_inner_start(void) {} |
35 | void static secp256k1_fe_inner_stop(void) {} | |
36 | ||
59447da3 | 37 | #ifdef VERIFY |
21f81a84 | 38 | void static secp256k1_fe_verify(const secp256k1_fe_t *a) { |
59447da3 | 39 | const uint64_t *d = a->n; |
21f81a84 | 40 | int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; |
59447da3 PD |
41 | r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m); |
42 | r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m); | |
43 | r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m); | |
44 | r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m); | |
45 | r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m); | |
46 | if (a->normalized) { | |
47 | r &= (m == 1); | |
48 | if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) { | |
49 | r &= (d[0] < 0xFFFFEFFFFFC2FULL); | |
50 | } | |
51 | } | |
1c7fa133 | 52 | VERIFY_CHECK(r == 1); |
59447da3 | 53 | } |
21f81a84 PW |
54 | #else |
55 | void static secp256k1_fe_verify(const secp256k1_fe_t *a) {} | |
59447da3 PD |
56 | #endif |
57 | ||
910d0de4 | 58 | void static secp256k1_fe_normalize(secp256k1_fe_t *r) { |
90377077 PD |
59 | uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; |
60 | ||
61 | // Reduce t4 at the start so there will be at most a single carry from the first pass | |
62 | uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; | |
42822baa | 63 | uint64_t m; |
90377077 PD |
64 | |
65 | // The first pass ensures the magnitude is 1, ... | |
66 | t0 += x * 0x1000003D1ULL; | |
67 | t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; | |
42822baa PD |
68 | t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; |
69 | t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; | |
70 | t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; | |
90377077 PD |
71 | |
72 | // ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) | |
1c7fa133 | 73 | VERIFY_CHECK(t4 >> 49 == 0); |
90377077 PD |
74 | |
75 | // At most a single final reduction is needed; check if the value is >= the field characteristic | |
42822baa | 76 | x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) |
90377077 PD |
77 | & (t0 >= 0xFFFFEFFFFFC2FULL)); |
78 | ||
79 | // Apply the final reduction (for constant-time behaviour, we do it always) | |
80 | t0 += x * 0x1000003D1ULL; | |
81 | t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; | |
82 | t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; | |
83 | t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; | |
84 | t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; | |
85 | ||
86 | // If t4 didn't carry to bit 48 already, then it should have after any final reduction | |
1c7fa133 | 87 | VERIFY_CHECK(t4 >> 48 == x); |
90377077 PD |
88 | |
89 | // Mask off the possible multiple of 2^256 from the final reduction | |
90 | t4 &= 0x0FFFFFFFFFFFFULL; | |
91 | ||
910d0de4 PW |
92 | r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; |
93 | ||
94 | #ifdef VERIFY | |
95 | r->magnitude = 1; | |
96 | r->normalized = 1; | |
21f81a84 | 97 | secp256k1_fe_verify(r); |
910d0de4 PW |
98 | #endif |
99 | } | |
e6d142a8 | 100 | |
fba1d58d | 101 | void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { |
910d0de4 PW |
102 | r->n[0] = a; |
103 | r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; | |
104 | #ifdef VERIFY | |
105 | r->magnitude = 1; | |
106 | r->normalized = 1; | |
21f81a84 | 107 | secp256k1_fe_verify(r); |
e6d142a8 PW |
108 | #endif |
109 | } | |
110 | ||
910d0de4 | 111 | // TODO: not constant time! |
fba1d58d | 112 | int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) { |
910d0de4 | 113 | #ifdef VERIFY |
1c7fa133 | 114 | VERIFY_CHECK(a->normalized); |
21f81a84 | 115 | secp256k1_fe_verify(a); |
e6d142a8 | 116 | #endif |
910d0de4 | 117 | return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0 && a->n[4] == 0); |
e6d142a8 PW |
118 | } |
119 | ||
fba1d58d | 120 | int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) { |
910d0de4 | 121 | #ifdef VERIFY |
1c7fa133 | 122 | VERIFY_CHECK(a->normalized); |
21f81a84 | 123 | secp256k1_fe_verify(a); |
e6d142a8 | 124 | #endif |
910d0de4 | 125 | return a->n[0] & 1; |
e6d142a8 PW |
126 | } |
127 | ||
2f6c8019 GM |
128 | void static inline secp256k1_fe_clear(secp256k1_fe_t *a) { |
129 | #ifdef VERIFY | |
130 | a->magnitude = 0; | |
131 | a->normalized = 0; | |
132 | #endif | |
133 | for (int i=0; i<5; i++) { | |
134 | a->n[i] = 0; | |
135 | } | |
136 | } | |
137 | ||
910d0de4 | 138 | // TODO: not constant time! |
fba1d58d | 139 | int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { |
910d0de4 | 140 | #ifdef VERIFY |
1c7fa133 PW |
141 | VERIFY_CHECK(a->normalized); |
142 | VERIFY_CHECK(b->normalized); | |
21f81a84 PW |
143 | secp256k1_fe_verify(a); |
144 | secp256k1_fe_verify(b); | |
e6d142a8 | 145 | #endif |
910d0de4 PW |
146 | return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3] && a->n[4] == b->n[4]); |
147 | } | |
148 | ||
149 | void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { | |
150 | r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; | |
e6d142a8 | 151 | for (int i=0; i<32; i++) { |
e6d142a8 PW |
152 | for (int j=0; j<2; j++) { |
153 | int limb = (8*i+4*j)/52; | |
154 | int shift = (8*i+4*j)%52; | |
910d0de4 | 155 | r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; |
e6d142a8 | 156 | } |
e6d142a8 | 157 | } |
910d0de4 PW |
158 | #ifdef VERIFY |
159 | r->magnitude = 1; | |
eb0be8ee | 160 | r->normalized = 1; |
21f81a84 | 161 | secp256k1_fe_verify(r); |
910d0de4 | 162 | #endif |
e6d142a8 PW |
163 | } |
164 | ||
910d0de4 PW |
165 | /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ |
166 | void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { | |
167 | #ifdef VERIFY | |
1c7fa133 | 168 | VERIFY_CHECK(a->normalized); |
21f81a84 | 169 | secp256k1_fe_verify(a); |
910d0de4 | 170 | #endif |
e6d142a8 | 171 | for (int i=0; i<32; i++) { |
910d0de4 | 172 | int c = 0; |
e6d142a8 PW |
173 | for (int j=0; j<2; j++) { |
174 | int limb = (8*i+4*j)/52; | |
175 | int shift = (8*i+4*j)%52; | |
910d0de4 | 176 | c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); |
e6d142a8 | 177 | } |
910d0de4 | 178 | r[31-i] = c; |
e6d142a8 | 179 | } |
e6d142a8 PW |
180 | } |
181 | ||
fba1d58d | 182 | void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { |
910d0de4 | 183 | #ifdef VERIFY |
1c7fa133 | 184 | VERIFY_CHECK(a->magnitude <= m); |
21f81a84 | 185 | secp256k1_fe_verify(a); |
e6d142a8 | 186 | #endif |
910d0de4 PW |
187 | r->n[0] = 0xFFFFEFFFFFC2FULL * (m + 1) - a->n[0]; |
188 | r->n[1] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[1]; | |
189 | r->n[2] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[2]; | |
190 | r->n[3] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[3]; | |
191 | r->n[4] = 0x0FFFFFFFFFFFFULL * (m + 1) - a->n[4]; | |
910d0de4 | 192 | #ifdef VERIFY |
21f81a84 | 193 | r->magnitude = m + 1; |
eb0be8ee | 194 | r->normalized = 0; |
21f81a84 | 195 | secp256k1_fe_verify(r); |
e6d142a8 | 196 | #endif |
21f81a84 PW |
197 | } |
198 | ||
199 | void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { | |
910d0de4 PW |
200 | r->n[0] *= a; |
201 | r->n[1] *= a; | |
202 | r->n[2] *= a; | |
203 | r->n[3] *= a; | |
204 | r->n[4] *= a; | |
910d0de4 | 205 | #ifdef VERIFY |
21f81a84 | 206 | r->magnitude *= a; |
910d0de4 | 207 | r->normalized = 0; |
21f81a84 | 208 | secp256k1_fe_verify(r); |
e6d142a8 | 209 | #endif |
21f81a84 PW |
210 | } |
211 | ||
212 | void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | |
910d0de4 PW |
213 | r->n[0] += a->n[0]; |
214 | r->n[1] += a->n[1]; | |
215 | r->n[2] += a->n[2]; | |
216 | r->n[3] += a->n[3]; | |
217 | r->n[4] += a->n[4]; | |
21f81a84 PW |
218 | #ifdef VERIFY |
219 | r->magnitude += a->magnitude; | |
220 | r->normalized = 0; | |
221 | secp256k1_fe_verify(r); | |
222 | secp256k1_fe_verify(a); | |
223 | #endif | |
e6d142a8 PW |
224 | } |
225 | ||
910d0de4 PW |
226 | void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { |
227 | #ifdef VERIFY | |
1c7fa133 PW |
228 | VERIFY_CHECK(a->magnitude <= 8); |
229 | VERIFY_CHECK(b->magnitude <= 8); | |
21f81a84 PW |
230 | secp256k1_fe_verify(a); |
231 | secp256k1_fe_verify(b); | |
232 | #endif | |
233 | secp256k1_fe_mul_inner(a->n, b->n, r->n); | |
234 | #ifdef VERIFY | |
910d0de4 PW |
235 | r->magnitude = 1; |
236 | r->normalized = 0; | |
21f81a84 | 237 | secp256k1_fe_verify(r); |
e6d142a8 PW |
238 | #endif |
239 | } | |
240 | ||
910d0de4 PW |
241 | void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
242 | #ifdef VERIFY | |
1c7fa133 | 243 | VERIFY_CHECK(a->magnitude <= 8); |
21f81a84 PW |
244 | #endif |
245 | secp256k1_fe_sqr_inner(a->n, r->n); | |
246 | #ifdef VERIFY | |
fba1d58d PW |
247 | r->magnitude = 1; |
248 | r->normalized = 0; | |
e6d142a8 PW |
249 | #endif |
250 | } | |
7a4b7691 PW |
251 | |
252 | #endif |