12
12
#include "ecdh.h"
13
13
#include "ecmult_impl.h"
14
14
15
- #define WNAF_BITS 256
15
+ #ifdef USE_ENDOMORPHISM
16
+ #define WNAF_BITS 128
17
+ #else
18
+ #define WNAF_BITS 256
19
+ #endif
16
20
#define WNAF_SIZE (w ) ((WNAF_BITS + (w) - 1) / (w))
17
21
18
22
/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val)
27
31
*
28
32
* Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335
29
33
*/
30
- static void secp256k1_ecdh_wnaf (int * wnaf , const secp256k1_scalar_t * a , int w ) {
31
- secp256k1_scalar_t s = * a ;
32
- /* Negate to force oddness */
33
- int is_even = secp256k1_scalar_is_even (& s );
34
- int global_sign = secp256k1_scalar_wnaf_cond_negate (& s , is_even );
35
-
34
+ static int secp256k1_ecdh_wnaf (int * wnaf , secp256k1_scalar_t s , int w ) {
35
+ int global_sign = 1 ;
36
+ int skew = 0 ;
36
37
int word = 0 ;
37
38
/* 1 2 3 */
38
- int u_last = secp256k1_scalar_shr_int ( & s , w ) ;
39
+ int u_last ;
39
40
int u ;
41
+
42
+ #ifdef USE_ENDOMORPHISM
43
+ /* If we are using the endomorphism, we cannot handle even numbers by negating
44
+ * them, since we are working with 128-bit numbers whose negations would be 256
45
+ * bits, eliminating the performance advantage. Instead we use a technique from
46
+ * Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even)
47
+ * or 2 (for odd) to the number we are encoding, then compensating after the
48
+ * multiplication. */
49
+ /* Negative 128-bit numbers will be negated, since otherwise they are 256-bit */
50
+ int flip = secp256k1_scalar_is_high (& s );
51
+ /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */
52
+ int bit = flip ^ (s .d [0 ] & 1 );
53
+ /* We check for negative one, since adding 2 to it will cause an overflow */
54
+ secp256k1_scalar_t neg_s ;
55
+ int not_neg_one ;
56
+ secp256k1_scalar_negate (& neg_s , & s );
57
+ not_neg_one = !secp256k1_scalar_is_one (& neg_s );
58
+ secp256k1_scalar_cadd_bit (& s , bit , not_neg_one );
59
+ /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects
60
+ * that we added two to it and flipped it. In fact for -1 these operations are
61
+ * identical. We only flipped, but since skewing is required (in the sense that
62
+ * the skew must be 1 or 2, never zero) and flipping is not, we need to change
63
+ * our flags to claim that we only skewed. */
64
+ global_sign = secp256k1_scalar_wnaf_cond_negate (& s , flip );
65
+ global_sign *= not_neg_one * 2 - 1 ;
66
+ skew = 1 << bit ;
67
+ #else
68
+ /* Otherwise, we just negate to force oddness */
69
+ int is_even = secp256k1_scalar_is_even (& s );
70
+ global_sign = secp256k1_scalar_wnaf_cond_negate (& s , is_even );
71
+ #endif
72
+
40
73
/* 4 */
74
+ u_last = secp256k1_scalar_shr_int (& s , w );
41
75
while (word * w < WNAF_BITS ) {
42
76
int sign ;
43
77
int even ;
@@ -59,6 +93,7 @@ static void secp256k1_ecdh_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) {
59
93
60
94
VERIFY_CHECK (secp256k1_scalar_is_zero (& s ));
61
95
VERIFY_CHECK (word == WNAF_SIZE (w ));
96
+ return skew ;
62
97
}
63
98
64
99
@@ -67,17 +102,37 @@ static void secp256k1_ecdh_point_multiply(secp256k1_gej_t *r, const secp256k1_ge
67
102
secp256k1_ge_t tmpa ;
68
103
secp256k1_fe_t Z ;
69
104
105
+ #ifdef USE_ENDOMORPHISM
106
+ secp256k1_ge_t pre_a_lam [ECMULT_TABLE_SIZE (WINDOW_A )];
107
+ int wnaf_1 [1 + WNAF_SIZE (WINDOW_A - 1 )];
108
+ int wnaf_lam [1 + WNAF_SIZE (WINDOW_A - 1 )];
109
+ int skew_1 ;
110
+ int skew_lam ;
111
+ secp256k1_scalar_t q_1 , q_lam ;
112
+ #else
70
113
int wnaf [1 + WNAF_SIZE (WINDOW_A - 1 )];
114
+ #endif
71
115
72
116
int i ;
73
- int is_zero = secp256k1_scalar_is_zero (scalar );
74
117
secp256k1_scalar_t sc = * scalar ;
118
+
119
+ /* build wnaf representation for q. */
120
+ #ifdef USE_ENDOMORPHISM
121
+ /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
122
+ secp256k1_scalar_split_lambda (& q_1 , & q_lam , & sc );
123
+ /* no need for zero correction when using endomorphism since even
124
+ * numbers have one added to them anyway */
125
+ skew_1 = secp256k1_ecdh_wnaf (wnaf_1 , q_1 , WINDOW_A - 1 );
126
+ skew_lam = secp256k1_ecdh_wnaf (wnaf_lam , q_lam , WINDOW_A - 1 );
127
+ #else
128
+ int is_zero = secp256k1_scalar_is_zero (scalar );
75
129
/* the wNAF ladder cannot handle zero, so bump this to one .. we will
76
130
* correct the result after the fact */
77
131
sc .d [0 ] += is_zero ;
132
+ VERIFY_CHECK (!secp256k1_scalar_is_zero (& sc ));
78
133
79
- /* build wnaf representation for q. */
80
- secp256k1_ecdh_wnaf ( wnaf , & sc , WINDOW_A - 1 );
134
+ secp256k1_ecdh_wnaf ( wnaf , sc , WINDOW_A - 1 );
135
+ #endif
81
136
82
137
/* Calculate odd multiples of a.
83
138
* All multiples are brought to the same Z 'denominator', which is stored
@@ -87,6 +142,11 @@ static void secp256k1_ecdh_point_multiply(secp256k1_gej_t *r, const secp256k1_ge
87
142
*/
88
143
secp256k1_gej_set_ge (r , a );
89
144
secp256k1_ecmult_odd_multiples_table_globalz_windowa (pre_a , & Z , r );
145
+ #ifdef USE_ENDOMORPHISM
146
+ for (i = 0 ; i < ECMULT_TABLE_SIZE (WINDOW_A ); i ++ ) {
147
+ secp256k1_ge_mul_lambda (& pre_a_lam [i ], & pre_a [i ]);
148
+ }
149
+ #endif
90
150
secp256k1_gej_set_infinity (r );
91
151
92
152
for (i = WNAF_SIZE (WINDOW_A - 1 ); i >= 0 ; i -- ) {
@@ -95,18 +155,61 @@ static void secp256k1_ecdh_point_multiply(secp256k1_gej_t *r, const secp256k1_ge
95
155
for (j = 0 ; j < WINDOW_A - 1 ; ++ j ) {
96
156
secp256k1_gej_double_var (r , r , NULL );
97
157
}
158
+ #ifdef USE_ENDOMORPHISM
159
+ n = wnaf_1 [i ];
160
+ ECMULT_TABLE_GET_GE (& tmpa , pre_a , n , WINDOW_A );
161
+ VERIFY_CHECK (n != 0 );
162
+ secp256k1_gej_add_ge (r , r , & tmpa );
163
+
164
+ n = wnaf_lam [i ];
165
+ ECMULT_TABLE_GET_GE (& tmpa , pre_a_lam , n , WINDOW_A );
166
+ VERIFY_CHECK (n != 0 );
167
+ secp256k1_gej_add_ge (r , r , & tmpa );
168
+ #else
98
169
n = wnaf [i ];
99
170
VERIFY_CHECK (n != 0 );
100
171
ECMULT_TABLE_GET_GE (& tmpa , pre_a , n , WINDOW_A );
101
172
secp256k1_gej_add_ge (r , r , & tmpa );
173
+ #endif
102
174
}
103
175
104
176
if (!r -> infinity ) {
105
177
secp256k1_fe_mul (& r -> z , & r -> z , & Z );
106
178
}
107
179
180
+ #ifdef USE_ENDOMORPHISM
181
+ {
182
+ /* Correct for wNAF skew */
183
+ secp256k1_ge_t correction = * a ;
184
+ secp256k1_ge_storage_t correction_1_stor ;
185
+ secp256k1_ge_storage_t correction_lam_stor ;
186
+ secp256k1_ge_storage_t a2_stor ;
187
+ secp256k1_gej_t tmpj ;
188
+ secp256k1_gej_set_ge (& tmpj , & correction );
189
+ secp256k1_gej_double_var (& tmpj , & tmpj , NULL );
190
+ secp256k1_ge_set_gej (& correction , & tmpj );
191
+ secp256k1_ge_to_storage (& correction_1_stor , a );
192
+ secp256k1_ge_to_storage (& correction_lam_stor , a );
193
+ secp256k1_ge_to_storage (& a2_stor , & correction );
194
+
195
+ /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */
196
+ secp256k1_ge_storage_cmov (& correction_1_stor , & a2_stor , skew_1 == 2 );
197
+ secp256k1_ge_storage_cmov (& correction_lam_stor , & a2_stor , skew_lam == 2 );
198
+
199
+ /* Apply the correction */
200
+ secp256k1_ge_from_storage (& correction , & correction_1_stor );
201
+ secp256k1_ge_neg (& correction , & correction );
202
+ secp256k1_gej_add_ge (r , r , & correction );
203
+
204
+ secp256k1_ge_from_storage (& correction , & correction_lam_stor );
205
+ secp256k1_ge_neg (& correction , & correction );
206
+ secp256k1_ge_mul_lambda (& correction , & correction );
207
+ secp256k1_gej_add_ge (r , r , & correction );
208
+ }
209
+ #else
108
210
/* correct for zero */
109
211
r -> infinity |= is_zero ;
212
+ #endif
110
213
}
111
214
112
215
#endif
0 commit comments