]> Git Repo - secp256k1.git/blame - src/field_5x52_impl.h
Add VERIFY_CHECK/DEBUG_CHECK and use CHECK macros more
[secp256k1.git] / src / field_5x52_impl.h
CommitLineData
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
34void static secp256k1_fe_inner_start(void) {}
35void static secp256k1_fe_inner_stop(void) {}
36
59447da3 37#ifdef VERIFY
21f81a84 38void 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
55void static secp256k1_fe_verify(const secp256k1_fe_t *a) {}
59447da3
PD
56#endif
57
910d0de4 58void 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 101void 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 112int 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 120int 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
128void 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 139int 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
149void 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 */
166void 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 182void 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
199void 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
212void 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
226void 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
241void 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
This page took 0.061204 seconds and 4 git commands to generate.