@@ -28,29 +28,21 @@ SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const
28
28
return secp256k1_fe_normalizes_to_zero_var (& na );
29
29
}
30
30
31
- static int secp256k1_fe_sqrt_var (secp256k1_fe * r , const secp256k1_fe * a ) {
32
- /** Given that p is congruent to 3 mod 4, we can compute the square root of
33
- * a mod p as the (p+1)/4'th power of a.
34
- *
35
- * As (p+1)/4 is an even number, it will have the same result for a and for
36
- * (-a). Only one of these two numbers actually has a square root however,
37
- * so we test at the end by squaring and comparing to the input.
38
- * Also because (p+1)/4 is an even number, the computed square root is
39
- * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
40
- */
41
- secp256k1_fe x2 , x3 , x6 , x9 , x11 , x22 , x44 , x88 , x176 , x220 , x223 , t1 ;
31
+ static void secp256k1_fe_common_exp (secp256k1_fe * r1 , secp256k1_fe * r2 , const secp256k1_fe * a ) {
32
+ secp256k1_fe t , x , x2 , x3 , x6 , x9 , x11 , x22 , x44 , x88 , x176 , x220 , x223 ;
42
33
int j ;
43
34
44
- /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
45
- * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
46
- * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
47
- */
35
+ CHECK (r1 != r2 );
36
+
37
+ x = * a ;
38
+
39
+ secp256k1_fe_sqr (& x2 , & x );
40
+ secp256k1_fe_mul (& x2 , & x2 , & x );
48
41
49
- secp256k1_fe_sqr (& x2 , a );
50
- secp256k1_fe_mul (& x2 , & x2 , a );
42
+ * r2 = x2 ;
51
43
52
44
secp256k1_fe_sqr (& x3 , & x2 );
53
- secp256k1_fe_mul (& x3 , & x3 , a );
45
+ secp256k1_fe_mul (& x3 , & x3 , & x );
54
46
55
47
x6 = x3 ;
56
48
for (j = 0 ; j < 3 ; j ++ ) {
@@ -108,112 +100,112 @@ static int secp256k1_fe_sqrt_var(secp256k1_fe *r, const secp256k1_fe *a) {
108
100
109
101
/* The final result is then assembled using a sliding window over the blocks. */
110
102
111
- t1 = x223 ;
103
+ t = x223 ;
112
104
for (j = 0 ; j < 23 ; j ++ ) {
113
- secp256k1_fe_sqr (& t1 , & t1 );
105
+ secp256k1_fe_sqr (& t , & t );
114
106
}
115
- secp256k1_fe_mul (& t1 , & t1 , & x22 );
116
- for (j = 0 ; j < 6 ; j ++ ) {
117
- secp256k1_fe_sqr (& t1 , & t1 );
107
+ secp256k1_fe_mul (& t , & t , & x22 );
108
+
109
+ for (j = 0 ; j < 5 ; j ++ ) {
110
+ secp256k1_fe_sqr (& t , & t );
118
111
}
119
- secp256k1_fe_mul (& t1 , & t1 , & x2 );
120
- secp256k1_fe_sqr (& t1 , & t1 );
121
- secp256k1_fe_sqr (r , & t1 );
112
+ * r1 = t ;
113
+ }
114
+
115
+ static int secp256k1_fe_sqrt_var (secp256k1_fe * r , const secp256k1_fe * a ) {
116
+ secp256k1_fe t , x , x2 ;
117
+
118
+ x = * a ;
119
+
120
+ secp256k1_fe_common_exp (& t , & x2 , & x );
121
+
122
+ secp256k1_fe_sqr (& t , & t );
123
+ secp256k1_fe_mul (& t , & t , & x2 );
124
+ secp256k1_fe_sqr (& t , & t );
125
+ secp256k1_fe_sqr (& t , & t );
126
+
127
+ * r = t ;
122
128
123
129
/* Check that a square root was actually calculated */
124
130
125
- secp256k1_fe_sqr (& t1 , r );
126
- return secp256k1_fe_equal_var (& t1 , a );
131
+ secp256k1_fe_sqr (& t , & t );
132
+ return secp256k1_fe_equal_var (& t , & x );
127
133
}
128
134
129
- static void secp256k1_fe_inv (secp256k1_fe * r , const secp256k1_fe * a ) {
130
- secp256k1_fe x2 , x3 , x6 , x9 , x11 , x22 , x44 , x88 , x176 , x220 , x223 , t1 ;
135
+ static int secp256k1_fe_rsqrt_var (secp256k1_fe * rs , secp256k1_fe * rr , const secp256k1_fe * a ) {
136
+ secp256k1_fe t , x , x2 ;
131
137
int j ;
132
138
133
- /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in
134
- * { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
135
- * [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
136
- */
139
+ CHECK (rs != rr );
137
140
138
- secp256k1_fe_sqr (& x2 , a );
139
- secp256k1_fe_mul (& x2 , & x2 , a );
141
+ x = * a ;
140
142
141
- secp256k1_fe_sqr (& x3 , & x2 );
142
- secp256k1_fe_mul (& x3 , & x3 , a );
143
+ secp256k1_fe_common_exp (& t , & x2 , & x );
143
144
144
- x6 = x3 ;
145
+ secp256k1_fe_mul ( & t , & t , & x ) ;
145
146
for (j = 0 ; j < 3 ; j ++ ) {
146
- secp256k1_fe_sqr (& x6 , & x6 );
147
+ secp256k1_fe_sqr (& t , & t );
147
148
}
148
- secp256k1_fe_mul (& x6 , & x6 , & x3 );
149
+ secp256k1_fe_mul (& t , & t , & x2 );
149
150
150
- x9 = x6 ;
151
- for (j = 0 ; j < 3 ; j ++ ) {
152
- secp256k1_fe_sqr (& x9 , & x9 );
153
- }
154
- secp256k1_fe_mul (& x9 , & x9 , & x3 );
151
+ * rr = t ;
155
152
156
- x11 = x9 ;
157
- for (j = 0 ; j < 2 ; j ++ ) {
158
- secp256k1_fe_sqr (& x11 , & x11 );
159
- }
160
- secp256k1_fe_mul (& x11 , & x11 , & x2 );
153
+ secp256k1_fe_mul (& t , & t , & x );
161
154
162
- x22 = x11 ;
163
- for (j = 0 ; j < 11 ; j ++ ) {
164
- secp256k1_fe_sqr (& x22 , & x22 );
165
- }
166
- secp256k1_fe_mul (& x22 , & x22 , & x11 );
155
+ * rs = t ;
167
156
168
- x44 = x22 ;
169
- for (j = 0 ; j < 22 ; j ++ ) {
170
- secp256k1_fe_sqr (& x44 , & x44 );
171
- }
172
- secp256k1_fe_mul (& x44 , & x44 , & x22 );
157
+ /* Check that a square root was actually calculated */
173
158
174
- x88 = x44 ;
175
- for (j = 0 ; j < 44 ; j ++ ) {
176
- secp256k1_fe_sqr (& x88 , & x88 );
177
- }
178
- secp256k1_fe_mul (& x88 , & x88 , & x44 );
159
+ secp256k1_fe_sqr (& t , & t );
160
+ return secp256k1_fe_equal_var (& t , & x );
161
+ }
179
162
180
- x176 = x88 ;
181
- for (j = 0 ; j < 88 ; j ++ ) {
182
- secp256k1_fe_sqr (& x176 , & x176 );
183
- }
184
- secp256k1_fe_mul (& x176 , & x176 , & x88 );
163
+ static int secp256k1_fe_par_rsqrt_inv_var (secp256k1_fe * rr , secp256k1_fe * ri , const secp256k1_fe * a , const secp256k1_fe * b ) {
185
164
186
- x220 = x176 ;
187
- for (j = 0 ; j < 44 ; j ++ ) {
188
- secp256k1_fe_sqr (& x220 , & x220 );
189
- }
190
- secp256k1_fe_mul (& x220 , & x220 , & x44 );
165
+ secp256k1_fe b2 , ab2 , ab4 , sqrt , recip , t ;
166
+ int ret ;
191
167
192
- x223 = x220 ;
193
- for (j = 0 ; j < 3 ; j ++ ) {
194
- secp256k1_fe_sqr (& x223 , & x223 );
195
- }
196
- secp256k1_fe_mul (& x223 , & x223 , & x3 );
168
+ CHECK (rr != ri );
197
169
198
- /* The final result is then assembled using a sliding window over the blocks. */
170
+ /* Zero inputs could possibly be handled with conditional moves, if necessary */
171
+ CHECK (!secp256k1_fe_normalizes_to_zero (a ) && !secp256k1_fe_normalizes_to_zero (b ));
199
172
200
- t1 = x223 ;
201
- for (j = 0 ; j < 23 ; j ++ ) {
202
- secp256k1_fe_sqr (& t1 , & t1 );
203
- }
204
- secp256k1_fe_mul (& t1 , & t1 , & x22 );
205
- for (j = 0 ; j < 5 ; j ++ ) {
206
- secp256k1_fe_sqr (& t1 , & t1 );
207
- }
208
- secp256k1_fe_mul (& t1 , & t1 , a );
173
+ /* Calculate the reciprocal sqrt of a.b^4 */
174
+
175
+ secp256k1_fe_sqr (& b2 , b );
176
+ secp256k1_fe_mul (& ab2 , & b2 , a );
177
+ secp256k1_fe_mul (& ab4 , & ab2 , & b2 );
178
+
179
+ ret = secp256k1_fe_rsqrt_var (& sqrt , & recip , & ab4 );
180
+
181
+ /* Inverse */
182
+ secp256k1_fe_sqr (& t , & recip );
183
+ secp256k1_fe_mul (& t , & t , & ab2 );
184
+ secp256k1_fe_mul (& t , & t , b );
185
+ secp256k1_fe_sqr (& t , & t );
186
+ secp256k1_fe_mul (ri , b , & t );
187
+
188
+ /* Reciprocal */
189
+ secp256k1_fe_mul (rr , & recip , & b2 );
190
+
191
+ return ret ;
192
+ }
193
+
194
+ static void secp256k1_fe_inv (secp256k1_fe * r , const secp256k1_fe * a ) {
195
+ secp256k1_fe t , x2 ;
196
+ int j ;
197
+
198
+ secp256k1_fe_common_exp (& t , & x2 , a );
199
+
200
+ secp256k1_fe_mul (& t , & t , a );
209
201
for (j = 0 ; j < 3 ; j ++ ) {
210
- secp256k1_fe_sqr (& t1 , & t1 );
202
+ secp256k1_fe_sqr (& t , & t );
211
203
}
212
- secp256k1_fe_mul (& t1 , & t1 , & x2 );
204
+ secp256k1_fe_mul (& t , & t , & x2 );
213
205
for (j = 0 ; j < 2 ; j ++ ) {
214
- secp256k1_fe_sqr (& t1 , & t1 );
206
+ secp256k1_fe_sqr (& t , & t );
215
207
}
216
- secp256k1_fe_mul (r , a , & t1 );
208
+ secp256k1_fe_mul (r , a , & t );
217
209
}
218
210
219
211
static void secp256k1_fe_inv_var (secp256k1_fe * r , const secp256k1_fe * a ) {
0 commit comments