/src/secp256k1/src/field_impl.h
Line | Count | Source |
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 | | |
21 | 4.80M | SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { |
22 | 4.80M | secp256k1_fe na; |
23 | 4.80M | SECP256K1_FE_VERIFY(a); |
24 | 4.80M | SECP256K1_FE_VERIFY(b); |
25 | 4.80M | SECP256K1_FE_VERIFY_MAGNITUDE(a, 1); |
26 | 4.80M | SECP256K1_FE_VERIFY_MAGNITUDE(b, 31); |
27 | | |
28 | 4.80M | secp256k1_fe_negate(&na, a, 1); |
29 | 4.80M | secp256k1_fe_add(&na, b); |
30 | 4.80M | return secp256k1_fe_normalizes_to_zero(&na); |
31 | 4.80M | } secp256k1_api.c:secp256k1_fe_equal Line | Count | Source | 21 | 3.03k | SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { | 22 | 3.03k | secp256k1_fe na; | 23 | 3.03k | SECP256K1_FE_VERIFY(a); | 24 | 3.03k | SECP256K1_FE_VERIFY(b); | 25 | 3.03k | SECP256K1_FE_VERIFY_MAGNITUDE(a, 1); | 26 | 3.03k | SECP256K1_FE_VERIFY_MAGNITUDE(b, 31); | 27 | | | 28 | 3.03k | secp256k1_fe_negate(&na, a, 1); | 29 | 3.03k | secp256k1_fe_add(&na, b); | 30 | 3.03k | return secp256k1_fe_normalizes_to_zero(&na); | 31 | 3.03k | } |
secp256k1.c:secp256k1_fe_equal Line | Count | Source | 21 | 4.80M | SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { | 22 | 4.80M | secp256k1_fe na; | 23 | 4.80M | SECP256K1_FE_VERIFY(a); | 24 | 4.80M | SECP256K1_FE_VERIFY(b); | 25 | 4.80M | SECP256K1_FE_VERIFY_MAGNITUDE(a, 1); | 26 | 4.80M | SECP256K1_FE_VERIFY_MAGNITUDE(b, 31); | 27 | | | 28 | 4.80M | secp256k1_fe_negate(&na, a, 1); | 29 | 4.80M | secp256k1_fe_add(&na, b); | 30 | 4.80M | return secp256k1_fe_normalizes_to_zero(&na); | 31 | 4.80M | } |
|
32 | | |
33 | 4.65M | static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a) { |
34 | | /** Given that p is congruent to 3 mod 4, we can compute the square root of |
35 | | * a mod p as the (p+1)/4'th power of a. |
36 | | * |
37 | | * As (p+1)/4 is an even number, it will have the same result for a and for |
38 | | * (-a). Only one of these two numbers actually has a square root however, |
39 | | * so we test at the end by squaring and comparing to the input. |
40 | | * Also because (p+1)/4 is an even number, the computed square root is |
41 | | * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). |
42 | | */ |
43 | 4.65M | secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; |
44 | 4.65M | int j, ret; |
45 | | |
46 | 4.65M | VERIFY_CHECK(r != a); |
47 | 4.65M | SECP256K1_FE_VERIFY(a); |
48 | 4.65M | SECP256K1_FE_VERIFY_MAGNITUDE(a, 8); |
49 | | |
50 | | /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in |
51 | | * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: |
52 | | * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] |
53 | | */ |
54 | | |
55 | 4.65M | secp256k1_fe_sqr(&x2, a); |
56 | 4.65M | secp256k1_fe_mul(&x2, &x2, a); |
57 | | |
58 | 4.65M | secp256k1_fe_sqr(&x3, &x2); |
59 | 4.65M | secp256k1_fe_mul(&x3, &x3, a); |
60 | | |
61 | 4.65M | x6 = x3; |
62 | 18.6M | for (j=0; j<3; j++) { |
63 | 13.9M | secp256k1_fe_sqr(&x6, &x6); |
64 | 13.9M | } |
65 | 4.65M | secp256k1_fe_mul(&x6, &x6, &x3); |
66 | | |
67 | 4.65M | x9 = x6; |
68 | 18.6M | for (j=0; j<3; j++) { |
69 | 13.9M | secp256k1_fe_sqr(&x9, &x9); |
70 | 13.9M | } |
71 | 4.65M | secp256k1_fe_mul(&x9, &x9, &x3); |
72 | | |
73 | 4.65M | x11 = x9; |
74 | 13.9M | for (j=0; j<2; j++) { |
75 | 9.31M | secp256k1_fe_sqr(&x11, &x11); |
76 | 9.31M | } |
77 | 4.65M | secp256k1_fe_mul(&x11, &x11, &x2); |
78 | | |
79 | 4.65M | x22 = x11; |
80 | 55.9M | for (j=0; j<11; j++) { |
81 | 51.2M | secp256k1_fe_sqr(&x22, &x22); |
82 | 51.2M | } |
83 | 4.65M | secp256k1_fe_mul(&x22, &x22, &x11); |
84 | | |
85 | 4.65M | x44 = x22; |
86 | 107M | for (j=0; j<22; j++) { |
87 | 102M | secp256k1_fe_sqr(&x44, &x44); |
88 | 102M | } |
89 | 4.65M | secp256k1_fe_mul(&x44, &x44, &x22); |
90 | | |
91 | 4.65M | x88 = x44; |
92 | 209M | for (j=0; j<44; j++) { |
93 | 205M | secp256k1_fe_sqr(&x88, &x88); |
94 | 205M | } |
95 | 4.65M | secp256k1_fe_mul(&x88, &x88, &x44); |
96 | | |
97 | 4.65M | x176 = x88; |
98 | 414M | for (j=0; j<88; j++) { |
99 | 410M | secp256k1_fe_sqr(&x176, &x176); |
100 | 410M | } |
101 | 4.65M | secp256k1_fe_mul(&x176, &x176, &x88); |
102 | | |
103 | 4.65M | x220 = x176; |
104 | 209M | for (j=0; j<44; j++) { |
105 | 205M | secp256k1_fe_sqr(&x220, &x220); |
106 | 205M | } |
107 | 4.65M | secp256k1_fe_mul(&x220, &x220, &x44); |
108 | | |
109 | 4.65M | x223 = x220; |
110 | 18.6M | for (j=0; j<3; j++) { |
111 | 13.9M | secp256k1_fe_sqr(&x223, &x223); |
112 | 13.9M | } |
113 | 4.65M | secp256k1_fe_mul(&x223, &x223, &x3); |
114 | | |
115 | | /* The final result is then assembled using a sliding window over the blocks. */ |
116 | | |
117 | 4.65M | t1 = x223; |
118 | 111M | for (j=0; j<23; j++) { |
119 | 107M | secp256k1_fe_sqr(&t1, &t1); |
120 | 107M | } |
121 | 4.65M | secp256k1_fe_mul(&t1, &t1, &x22); |
122 | 32.6M | for (j=0; j<6; j++) { |
123 | 27.9M | secp256k1_fe_sqr(&t1, &t1); |
124 | 27.9M | } |
125 | 4.65M | secp256k1_fe_mul(&t1, &t1, &x2); |
126 | 4.65M | secp256k1_fe_sqr(&t1, &t1); |
127 | 4.65M | secp256k1_fe_sqr(r, &t1); |
128 | | |
129 | | /* Check that a square root was actually calculated */ |
130 | | |
131 | 4.65M | secp256k1_fe_sqr(&t1, r); |
132 | 4.65M | ret = secp256k1_fe_equal(&t1, a); |
133 | | |
134 | | #ifdef VERIFY |
135 | | if (!ret) { |
136 | | secp256k1_fe_negate(&t1, &t1, 1); |
137 | | secp256k1_fe_normalize_var(&t1); |
138 | | VERIFY_CHECK(secp256k1_fe_equal(&t1, a)); |
139 | | } |
140 | | #endif |
141 | 4.65M | return ret; |
142 | 4.65M | } Unexecuted instantiation: secp256k1_api.c:secp256k1_fe_sqrt secp256k1.c:secp256k1_fe_sqrt Line | Count | Source | 33 | 4.65M | static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a) { | 34 | | /** Given that p is congruent to 3 mod 4, we can compute the square root of | 35 | | * a mod p as the (p+1)/4'th power of a. | 36 | | * | 37 | | * As (p+1)/4 is an even number, it will have the same result for a and for | 38 | | * (-a). Only one of these two numbers actually has a square root however, | 39 | | * so we test at the end by squaring and comparing to the input. | 40 | | * Also because (p+1)/4 is an even number, the computed square root is | 41 | | * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). | 42 | | */ | 43 | 4.65M | secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; | 44 | 4.65M | int j, ret; | 45 | | | 46 | 4.65M | VERIFY_CHECK(r != a); | 47 | 4.65M | SECP256K1_FE_VERIFY(a); | 48 | 4.65M | SECP256K1_FE_VERIFY_MAGNITUDE(a, 8); | 49 | | | 50 | | /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in | 51 | | * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: | 52 | | * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] | 53 | | */ | 54 | | | 55 | 4.65M | secp256k1_fe_sqr(&x2, a); | 56 | 4.65M | secp256k1_fe_mul(&x2, &x2, a); | 57 | | | 58 | 4.65M | secp256k1_fe_sqr(&x3, &x2); | 59 | 4.65M | secp256k1_fe_mul(&x3, &x3, a); | 60 | | | 61 | 4.65M | x6 = x3; | 62 | 18.6M | for (j=0; j<3; j++) { | 63 | 13.9M | secp256k1_fe_sqr(&x6, &x6); | 64 | 13.9M | } | 65 | 4.65M | secp256k1_fe_mul(&x6, &x6, &x3); | 66 | | | 67 | 4.65M | x9 = x6; | 68 | 18.6M | for (j=0; j<3; j++) { | 69 | 13.9M | secp256k1_fe_sqr(&x9, &x9); | 70 | 13.9M | } | 71 | 4.65M | secp256k1_fe_mul(&x9, &x9, &x3); | 72 | | | 73 | 4.65M | x11 = x9; | 74 | 13.9M | for (j=0; j<2; j++) { | 75 | 9.31M | secp256k1_fe_sqr(&x11, &x11); | 76 | 9.31M | } | 77 | 4.65M | secp256k1_fe_mul(&x11, &x11, &x2); | 78 | | | 79 | 4.65M | x22 = x11; | 80 | 55.9M | for (j=0; j<11; j++) { | 81 | 51.2M | secp256k1_fe_sqr(&x22, &x22); | 82 | 51.2M | } | 83 | 4.65M | secp256k1_fe_mul(&x22, &x22, &x11); | 84 | | | 85 | 4.65M | x44 = x22; | 86 | 107M | for (j=0; j<22; j++) { | 87 | 102M | secp256k1_fe_sqr(&x44, &x44); | 88 | 102M | } | 89 | 4.65M | secp256k1_fe_mul(&x44, &x44, &x22); | 90 | | | 91 | 4.65M | x88 = x44; | 92 | 209M | for (j=0; j<44; j++) { | 93 | 205M | secp256k1_fe_sqr(&x88, &x88); | 94 | 205M | } | 95 | 4.65M | secp256k1_fe_mul(&x88, &x88, &x44); | 96 | | | 97 | 4.65M | x176 = x88; | 98 | 414M | for (j=0; j<88; j++) { | 99 | 410M | secp256k1_fe_sqr(&x176, &x176); | 100 | 410M | } | 101 | 4.65M | secp256k1_fe_mul(&x176, &x176, &x88); | 102 | | | 103 | 4.65M | x220 = x176; | 104 | 209M | for (j=0; j<44; j++) { | 105 | 205M | secp256k1_fe_sqr(&x220, &x220); | 106 | 205M | } | 107 | 4.65M | secp256k1_fe_mul(&x220, &x220, &x44); | 108 | | | 109 | 4.65M | x223 = x220; | 110 | 18.6M | for (j=0; j<3; j++) { | 111 | 13.9M | secp256k1_fe_sqr(&x223, &x223); | 112 | 13.9M | } | 113 | 4.65M | secp256k1_fe_mul(&x223, &x223, &x3); | 114 | | | 115 | | /* The final result is then assembled using a sliding window over the blocks. */ | 116 | | | 117 | 4.65M | t1 = x223; | 118 | 111M | for (j=0; j<23; j++) { | 119 | 107M | secp256k1_fe_sqr(&t1, &t1); | 120 | 107M | } | 121 | 4.65M | secp256k1_fe_mul(&t1, &t1, &x22); | 122 | 32.6M | for (j=0; j<6; j++) { | 123 | 27.9M | secp256k1_fe_sqr(&t1, &t1); | 124 | 27.9M | } | 125 | 4.65M | secp256k1_fe_mul(&t1, &t1, &x2); | 126 | 4.65M | secp256k1_fe_sqr(&t1, &t1); | 127 | 4.65M | secp256k1_fe_sqr(r, &t1); | 128 | | | 129 | | /* Check that a square root was actually calculated */ | 130 | | | 131 | 4.65M | secp256k1_fe_sqr(&t1, r); | 132 | 4.65M | ret = secp256k1_fe_equal(&t1, a); | 133 | | | 134 | | #ifdef VERIFY | 135 | | if (!ret) { | 136 | | secp256k1_fe_negate(&t1, &t1, 1); | 137 | | secp256k1_fe_normalize_var(&t1); | 138 | | VERIFY_CHECK(secp256k1_fe_equal(&t1, a)); | 139 | | } | 140 | | #endif | 141 | 4.65M | return ret; | 142 | 4.65M | } |
|
143 | | |
144 | | #ifndef VERIFY |
145 | 6.94G | static void secp256k1_fe_verify(const secp256k1_fe *a) { (void)a; } secp256k1_api.c:secp256k1_fe_verify Line | Count | Source | 145 | 3.24M | static void secp256k1_fe_verify(const secp256k1_fe *a) { (void)a; } |
secp256k1.c:secp256k1_fe_verify Line | Count | Source | 145 | 6.94G | static void secp256k1_fe_verify(const secp256k1_fe *a) { (void)a; } |
|
146 | 6.77G | static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) { (void)a; (void)m; } secp256k1_api.c:secp256k1_fe_verify_magnitude Line | Count | Source | 146 | 3.12M | static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) { (void)a; (void)m; } |
secp256k1.c:secp256k1_fe_verify_magnitude Line | Count | Source | 146 | 6.77G | static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) { (void)a; (void)m; } |
|
147 | | #else |
148 | | static void secp256k1_fe_impl_verify(const secp256k1_fe *a); |
149 | | static void secp256k1_fe_verify(const secp256k1_fe *a) { |
150 | | /* Magnitude between 0 and 32. */ |
151 | | SECP256K1_FE_VERIFY_MAGNITUDE(a, 32); |
152 | | /* Normalized is 0 or 1. */ |
153 | | VERIFY_CHECK((a->normalized == 0) || (a->normalized == 1)); |
154 | | /* If normalized, magnitude must be 0 or 1. */ |
155 | | if (a->normalized) SECP256K1_FE_VERIFY_MAGNITUDE(a, 1); |
156 | | /* Invoke implementation-specific checks. */ |
157 | | secp256k1_fe_impl_verify(a); |
158 | | } |
159 | | |
160 | | static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) { |
161 | | VERIFY_CHECK(m >= 0); |
162 | | VERIFY_CHECK(m <= 32); |
163 | | VERIFY_CHECK(a->magnitude <= m); |
164 | | } |
165 | | |
166 | | static void secp256k1_fe_impl_normalize(secp256k1_fe *r); |
167 | | SECP256K1_INLINE static void secp256k1_fe_normalize(secp256k1_fe *r) { |
168 | | SECP256K1_FE_VERIFY(r); |
169 | | |
170 | | secp256k1_fe_impl_normalize(r); |
171 | | r->magnitude = 1; |
172 | | r->normalized = 1; |
173 | | |
174 | | SECP256K1_FE_VERIFY(r); |
175 | | } |
176 | | |
177 | | static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r); |
178 | | SECP256K1_INLINE static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { |
179 | | SECP256K1_FE_VERIFY(r); |
180 | | |
181 | | secp256k1_fe_impl_normalize_weak(r); |
182 | | r->magnitude = 1; |
183 | | |
184 | | SECP256K1_FE_VERIFY(r); |
185 | | } |
186 | | |
187 | | static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r); |
188 | | SECP256K1_INLINE static void secp256k1_fe_normalize_var(secp256k1_fe *r) { |
189 | | SECP256K1_FE_VERIFY(r); |
190 | | |
191 | | secp256k1_fe_impl_normalize_var(r); |
192 | | r->magnitude = 1; |
193 | | r->normalized = 1; |
194 | | |
195 | | SECP256K1_FE_VERIFY(r); |
196 | | } |
197 | | |
198 | | static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r); |
199 | | SECP256K1_INLINE static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) { |
200 | | SECP256K1_FE_VERIFY(r); |
201 | | |
202 | | return secp256k1_fe_impl_normalizes_to_zero(r); |
203 | | } |
204 | | |
205 | | static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r); |
206 | | SECP256K1_INLINE static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) { |
207 | | SECP256K1_FE_VERIFY(r); |
208 | | |
209 | | return secp256k1_fe_impl_normalizes_to_zero_var(r); |
210 | | } |
211 | | |
212 | | static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a); |
213 | | SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { |
214 | | VERIFY_CHECK(0 <= a && a <= 0x7FFF); |
215 | | |
216 | | secp256k1_fe_impl_set_int(r, a); |
217 | | r->magnitude = (a != 0); |
218 | | r->normalized = 1; |
219 | | |
220 | | SECP256K1_FE_VERIFY(r); |
221 | | } |
222 | | |
223 | | static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a); |
224 | | SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) { |
225 | | VERIFY_CHECK(0 <= a && a <= 0x7FFF); |
226 | | SECP256K1_FE_VERIFY(r); |
227 | | |
228 | | secp256k1_fe_impl_add_int(r, a); |
229 | | r->magnitude += 1; |
230 | | r->normalized = 0; |
231 | | |
232 | | SECP256K1_FE_VERIFY(r); |
233 | | } |
234 | | |
235 | | static void secp256k1_fe_impl_clear(secp256k1_fe *a); |
236 | | SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { |
237 | | a->magnitude = 0; |
238 | | a->normalized = 1; |
239 | | secp256k1_fe_impl_clear(a); |
240 | | |
241 | | SECP256K1_FE_VERIFY(a); |
242 | | } |
243 | | |
244 | | static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a); |
245 | | SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { |
246 | | SECP256K1_FE_VERIFY(a); |
247 | | VERIFY_CHECK(a->normalized); |
248 | | |
249 | | return secp256k1_fe_impl_is_zero(a); |
250 | | } |
251 | | |
252 | | static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a); |
253 | | SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { |
254 | | SECP256K1_FE_VERIFY(a); |
255 | | VERIFY_CHECK(a->normalized); |
256 | | |
257 | | return secp256k1_fe_impl_is_odd(a); |
258 | | } |
259 | | |
260 | | static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b); |
261 | | SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { |
262 | | SECP256K1_FE_VERIFY(a); |
263 | | SECP256K1_FE_VERIFY(b); |
264 | | VERIFY_CHECK(a->normalized); |
265 | | VERIFY_CHECK(b->normalized); |
266 | | |
267 | | return secp256k1_fe_impl_cmp_var(a, b); |
268 | | } |
269 | | |
270 | | static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a); |
271 | | SECP256K1_INLINE static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a) { |
272 | | secp256k1_fe_impl_set_b32_mod(r, a); |
273 | | r->magnitude = 1; |
274 | | r->normalized = 0; |
275 | | |
276 | | SECP256K1_FE_VERIFY(r); |
277 | | } |
278 | | |
279 | | static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a); |
280 | | SECP256K1_INLINE static int secp256k1_fe_set_b32_limit(secp256k1_fe *r, const unsigned char *a) { |
281 | | if (secp256k1_fe_impl_set_b32_limit(r, a)) { |
282 | | r->magnitude = 1; |
283 | | r->normalized = 1; |
284 | | SECP256K1_FE_VERIFY(r); |
285 | | return 1; |
286 | | } else { |
287 | | /* Mark the output field element as invalid. */ |
288 | | r->magnitude = -1; |
289 | | return 0; |
290 | | } |
291 | | } |
292 | | |
293 | | static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a); |
294 | | SECP256K1_INLINE static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { |
295 | | SECP256K1_FE_VERIFY(a); |
296 | | VERIFY_CHECK(a->normalized); |
297 | | |
298 | | secp256k1_fe_impl_get_b32(r, a); |
299 | | } |
300 | | |
301 | | static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m); |
302 | | SECP256K1_INLINE static void secp256k1_fe_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) { |
303 | | SECP256K1_FE_VERIFY(a); |
304 | | VERIFY_CHECK(m >= 0 && m <= 31); |
305 | | SECP256K1_FE_VERIFY_MAGNITUDE(a, m); |
306 | | |
307 | | secp256k1_fe_impl_negate_unchecked(r, a, m); |
308 | | r->magnitude = m + 1; |
309 | | r->normalized = 0; |
310 | | |
311 | | SECP256K1_FE_VERIFY(r); |
312 | | } |
313 | | |
314 | | static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a); |
315 | | SECP256K1_INLINE static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a) { |
316 | | SECP256K1_FE_VERIFY(r); |
317 | | |
318 | | VERIFY_CHECK(a >= 0 && a <= 32); |
319 | | VERIFY_CHECK(a*r->magnitude <= 32); |
320 | | secp256k1_fe_impl_mul_int_unchecked(r, a); |
321 | | r->magnitude *= a; |
322 | | r->normalized = 0; |
323 | | |
324 | | SECP256K1_FE_VERIFY(r); |
325 | | } |
326 | | |
327 | | static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a); |
328 | | SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { |
329 | | SECP256K1_FE_VERIFY(r); |
330 | | SECP256K1_FE_VERIFY(a); |
331 | | VERIFY_CHECK(r->magnitude + a->magnitude <= 32); |
332 | | |
333 | | secp256k1_fe_impl_add(r, a); |
334 | | r->magnitude += a->magnitude; |
335 | | r->normalized = 0; |
336 | | |
337 | | SECP256K1_FE_VERIFY(r); |
338 | | } |
339 | | |
340 | | static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b); |
341 | | SECP256K1_INLINE static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { |
342 | | SECP256K1_FE_VERIFY(a); |
343 | | SECP256K1_FE_VERIFY(b); |
344 | | SECP256K1_FE_VERIFY_MAGNITUDE(a, 8); |
345 | | SECP256K1_FE_VERIFY_MAGNITUDE(b, 8); |
346 | | VERIFY_CHECK(r != b); |
347 | | VERIFY_CHECK(a != b); |
348 | | |
349 | | secp256k1_fe_impl_mul(r, a, b); |
350 | | r->magnitude = 1; |
351 | | r->normalized = 0; |
352 | | |
353 | | SECP256K1_FE_VERIFY(r); |
354 | | } |
355 | | |
356 | | static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a); |
357 | | SECP256K1_INLINE static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { |
358 | | SECP256K1_FE_VERIFY(a); |
359 | | SECP256K1_FE_VERIFY_MAGNITUDE(a, 8); |
360 | | |
361 | | secp256k1_fe_impl_sqr(r, a); |
362 | | r->magnitude = 1; |
363 | | r->normalized = 0; |
364 | | |
365 | | SECP256K1_FE_VERIFY(r); |
366 | | } |
367 | | |
368 | | static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); |
369 | | SECP256K1_INLINE static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { |
370 | | VERIFY_CHECK(flag == 0 || flag == 1); |
371 | | SECP256K1_FE_VERIFY(a); |
372 | | SECP256K1_FE_VERIFY(r); |
373 | | |
374 | | secp256k1_fe_impl_cmov(r, a, flag); |
375 | | if (a->magnitude > r->magnitude) r->magnitude = a->magnitude; |
376 | | if (!a->normalized) r->normalized = 0; |
377 | | |
378 | | SECP256K1_FE_VERIFY(r); |
379 | | } |
380 | | |
381 | | static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a); |
382 | | SECP256K1_INLINE static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { |
383 | | SECP256K1_FE_VERIFY(a); |
384 | | VERIFY_CHECK(a->normalized); |
385 | | |
386 | | secp256k1_fe_impl_to_storage(r, a); |
387 | | } |
388 | | |
389 | | static void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a); |
390 | | SECP256K1_INLINE static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { |
391 | | secp256k1_fe_impl_from_storage(r, a); |
392 | | r->magnitude = 1; |
393 | | r->normalized = 1; |
394 | | |
395 | | SECP256K1_FE_VERIFY(r); |
396 | | } |
397 | | |
398 | | static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x); |
399 | | SECP256K1_INLINE static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) { |
400 | | int input_is_zero = secp256k1_fe_normalizes_to_zero(x); |
401 | | SECP256K1_FE_VERIFY(x); |
402 | | |
403 | | secp256k1_fe_impl_inv(r, x); |
404 | | r->magnitude = x->magnitude > 0; |
405 | | r->normalized = 1; |
406 | | |
407 | | VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero); |
408 | | SECP256K1_FE_VERIFY(r); |
409 | | } |
410 | | |
411 | | static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x); |
412 | | SECP256K1_INLINE static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) { |
413 | | int input_is_zero = secp256k1_fe_normalizes_to_zero(x); |
414 | | SECP256K1_FE_VERIFY(x); |
415 | | |
416 | | secp256k1_fe_impl_inv_var(r, x); |
417 | | r->magnitude = x->magnitude > 0; |
418 | | r->normalized = 1; |
419 | | |
420 | | VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero); |
421 | | SECP256K1_FE_VERIFY(r); |
422 | | } |
423 | | |
424 | | static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x); |
425 | | SECP256K1_INLINE static int secp256k1_fe_is_square_var(const secp256k1_fe *x) { |
426 | | int ret; |
427 | | secp256k1_fe tmp = *x, sqrt; |
428 | | SECP256K1_FE_VERIFY(x); |
429 | | |
430 | | ret = secp256k1_fe_impl_is_square_var(x); |
431 | | secp256k1_fe_normalize_weak(&tmp); |
432 | | VERIFY_CHECK(ret == secp256k1_fe_sqrt(&sqrt, &tmp)); |
433 | | return ret; |
434 | | } |
435 | | |
436 | | static void secp256k1_fe_impl_get_bounds(secp256k1_fe* r, int m); |
437 | | SECP256K1_INLINE static void secp256k1_fe_get_bounds(secp256k1_fe* r, int m) { |
438 | | VERIFY_CHECK(m >= 0); |
439 | | VERIFY_CHECK(m <= 32); |
440 | | |
441 | | secp256k1_fe_impl_get_bounds(r, m); |
442 | | r->magnitude = m; |
443 | | r->normalized = (m == 0); |
444 | | |
445 | | SECP256K1_FE_VERIFY(r); |
446 | | } |
447 | | |
448 | | static void secp256k1_fe_impl_half(secp256k1_fe *r); |
449 | | SECP256K1_INLINE static void secp256k1_fe_half(secp256k1_fe *r) { |
450 | | SECP256K1_FE_VERIFY(r); |
451 | | SECP256K1_FE_VERIFY_MAGNITUDE(r, 31); |
452 | | |
453 | | secp256k1_fe_impl_half(r); |
454 | | r->magnitude = (r->magnitude >> 1) + 1; |
455 | | r->normalized = 0; |
456 | | |
457 | | SECP256K1_FE_VERIFY(r); |
458 | | } |
459 | | |
460 | | #endif /* defined(VERIFY) */ |
461 | | |
462 | | #endif /* SECP256K1_FIELD_IMPL_H */ |