Skip to content

Commit ff33018

Browse files
Merge #232: Backports from libsecp256k1 v0.3.2
39407c3 Mark stack variables as early clobber for technical correctness (Pieter Wuille) 56a5d41 Bugfix: mark outputs as early clobber in scalar x86_64 asm (Pieter Wuille) c8c0f55 ct: Be cautious and use volatile trick in more "conditional" paths (Tim Ruffing) 3e94289 ct: Use volatile trick in scalar_cond_negate (Tim Ruffing) Pull request description: ACKs for top commit: real-or-random: ACK 39407c3 I also verified that the ct time tests pass on GCC 13.1.1 and Clang 15.0.7. Tree-SHA512: b7e695527ea58cc7b94a5f2fff6473b6779a469bc5c38baf92624b655cbdf303fbd204e6c1395fa02b98db3bc47bab32afe64bae4ab4fab18da856b621aab070
2 parents edcba04 + 39407c3 commit ff33018

6 files changed

+47
-37
lines changed

src/ecmult_const_impl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *p
2929
#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \
3030
int m = 0; \
3131
/* Extract the sign-bit for a constant time absolute-value. */ \
32-
int mask = (n) >> (sizeof(n) * CHAR_BIT - 1); \
32+
int volatile mask = (n) >> (sizeof(n) * CHAR_BIT - 1); \
3333
int abs_n = ((n) + mask) ^ mask; \
3434
int idx_n = abs_n >> 1; \
3535
secp256k1_fe neg_y; \

src/field_5x52_asm_impl.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ __asm__ __volatile__(
278278
"addq %%rsi,%%r8\n"
279279
/* r[4] = c */
280280
"movq %%r8,32(%%rdi)\n"
281-
: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3)
281+
: "+S"(a), "=&m"(tmp1), "=&m"(tmp2), "=&m"(tmp3)
282282
: "b"(b), "D"(r)
283283
: "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory"
284284
);
@@ -493,7 +493,7 @@ __asm__ __volatile__(
493493
"addq %%rsi,%%r8\n"
494494
/* r[4] = c */
495495
"movq %%r8,32(%%rdi)\n"
496-
: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3)
496+
: "+S"(a), "=&m"(tmp1), "=&m"(tmp2), "=&m"(tmp3)
497497
: "D"(r)
498498
: "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory"
499499
);

src/modinv32_impl.h

+18-15
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static void secp256k1_modinv32_normalize_30(secp256k1_modinv32_signed30 *r, int3
6464
const int32_t M30 = (int32_t)(UINT32_MAX >> 2);
6565
int32_t r0 = r->v[0], r1 = r->v[1], r2 = r->v[2], r3 = r->v[3], r4 = r->v[4],
6666
r5 = r->v[5], r6 = r->v[6], r7 = r->v[7], r8 = r->v[8];
67-
int32_t cond_add, cond_negate;
67+
volatile int32_t cond_add, cond_negate;
6868

6969
#ifdef VERIFY
7070
/* Verify that all limbs are in range (-2^30,2^30). */
@@ -186,7 +186,8 @@ static int32_t secp256k1_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_
186186
* being inside [-2^31,2^31) means that casting to signed works correctly.
187187
*/
188188
uint32_t u = 1, v = 0, q = 0, r = 1;
189-
uint32_t c1, c2, f = f0, g = g0, x, y, z;
189+
volatile uint32_t c1, c2;
190+
uint32_t mask1, mask2, f = f0, g = g0, x, y, z;
190191
int i;
191192

192193
for (i = 0; i < 30; ++i) {
@@ -195,23 +196,25 @@ static int32_t secp256k1_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_
195196
VERIFY_CHECK((q * f0 + r * g0) == g << i);
196197
/* Compute conditional masks for (zeta < 0) and for (g & 1). */
197198
c1 = zeta >> 31;
198-
c2 = -(g & 1);
199+
mask1 = c1;
200+
c2 = g & 1;
201+
mask2 = -c2;
199202
/* Compute x,y,z, conditionally negated versions of f,u,v. */
200-
x = (f ^ c1) - c1;
201-
y = (u ^ c1) - c1;
202-
z = (v ^ c1) - c1;
203+
x = (f ^ mask1) - mask1;
204+
y = (u ^ mask1) - mask1;
205+
z = (v ^ mask1) - mask1;
203206
/* Conditionally add x,y,z to g,q,r. */
204-
g += x & c2;
205-
q += y & c2;
206-
r += z & c2;
207-
/* In what follows, c1 is a condition mask for (zeta < 0) and (g & 1). */
208-
c1 &= c2;
207+
g += x & mask2;
208+
q += y & mask2;
209+
r += z & mask2;
210+
/* In what follows, mask1 is a condition mask for (zeta < 0) and (g & 1). */
211+
mask1 &= mask2;
209212
/* Conditionally change zeta into -zeta-2 or zeta-1. */
210-
zeta = (zeta ^ c1) - 1;
213+
zeta = (zeta ^ mask1) - 1;
211214
/* Conditionally add g,q,r to f,u,v. */
212-
f += g & c1;
213-
u += q & c1;
214-
v += r & c1;
215+
f += g & mask1;
216+
u += q & mask1;
217+
v += r & mask1;
215218
/* Shifts */
216219
g >>= 1;
217220
u <<= 1;

src/modinv64_impl.h

+17-14
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static int secp256k1_modinv64_mul_cmp_62(const secp256k1_modinv64_signed62 *a, i
6969
static void secp256k1_modinv64_normalize_62(secp256k1_modinv64_signed62 *r, int64_t sign, const secp256k1_modinv64_modinfo *modinfo) {
7070
const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
7171
int64_t r0 = r->v[0], r1 = r->v[1], r2 = r->v[2], r3 = r->v[3], r4 = r->v[4];
72-
int64_t cond_add, cond_negate;
72+
volatile int64_t cond_add, cond_negate;
7373

7474
#ifdef VERIFY
7575
/* Verify that all limbs are in range (-2^62,2^62). */
@@ -165,7 +165,8 @@ static int64_t secp256k1_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_
165165
* being inside [-2^63,2^63) means that casting to signed works correctly.
166166
*/
167167
uint64_t u = 8, v = 0, q = 0, r = 8;
168-
uint64_t c1, c2, f = f0, g = g0, x, y, z;
168+
volatile uint64_t c1, c2;
169+
uint64_t mask1, mask2, f = f0, g = g0, x, y, z;
169170
int i;
170171

171172
for (i = 3; i < 62; ++i) {
@@ -174,23 +175,25 @@ static int64_t secp256k1_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_
174175
VERIFY_CHECK((q * f0 + r * g0) == g << i);
175176
/* Compute conditional masks for (zeta < 0) and for (g & 1). */
176177
c1 = zeta >> 63;
177-
c2 = -(g & 1);
178+
mask1 = c1;
179+
c2 = g & 1;
180+
mask2 = -c2;
178181
/* Compute x,y,z, conditionally negated versions of f,u,v. */
179-
x = (f ^ c1) - c1;
180-
y = (u ^ c1) - c1;
181-
z = (v ^ c1) - c1;
182+
x = (f ^ mask1) - mask1;
183+
y = (u ^ mask1) - mask1;
184+
z = (v ^ mask1) - mask1;
182185
/* Conditionally add x,y,z to g,q,r. */
183-
g += x & c2;
184-
q += y & c2;
185-
r += z & c2;
186+
g += x & mask2;
187+
q += y & mask2;
188+
r += z & mask2;
186189
/* In what follows, c1 is a condition mask for (zeta < 0) and (g & 1). */
187-
c1 &= c2;
190+
mask1 &= mask2;
188191
/* Conditionally change zeta into -zeta-2 or zeta-1. */
189-
zeta = (zeta ^ c1) - 1;
192+
zeta = (zeta ^ mask1) - 1;
190193
/* Conditionally add g,q,r to f,u,v. */
191-
f += g & c1;
192-
u += q & c1;
193-
v += r & c1;
194+
f += g & mask1;
195+
u += q & mask1;
196+
v += r & mask1;
194197
/* Shifts */
195198
g >>= 1;
196199
u <<= 1;

src/scalar_4x64_impl.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a,
110110

111111
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
112112
uint128_t t;
113+
volatile int vflag = flag;
113114
VERIFY_CHECK(bit < 256);
114-
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */
115+
bit += ((uint32_t) vflag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */
115116
t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
116117
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
117118
t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
@@ -180,7 +181,8 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar *a) {
180181
static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
181182
/* If we are flag = 0, mask = 00...00 and this is a no-op;
182183
* if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */
183-
uint64_t mask = !flag - 1;
184+
volatile int vflag = flag;
185+
uint64_t mask = -vflag;
184186
uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1;
185187
uint128_t t = (uint128_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask);
186188
r->d[0] = t & nonzero; t >>= 64;
@@ -387,7 +389,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
387389
"movq %%r10, %q5\n"
388390
/* extract m6 */
389391
"movq %%r8, %q6\n"
390-
: "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6)
392+
: "=&g"(m0), "=&g"(m1), "=&g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6)
391393
: "S"(l), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1)
392394
: "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc");
393395

src/scalar_8x32_impl.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,9 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a,
153153

154154
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
155155
uint64_t t;
156+
volatile int vflag = flag;
156157
VERIFY_CHECK(bit < 256);
157-
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */
158+
bit += ((uint32_t) vflag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */
158159
t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F));
159160
r->d[0] = t & 0xFFFFFFFFULL; t >>= 32;
160161
t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F));
@@ -253,7 +254,8 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar *a) {
253254
static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
254255
/* If we are flag = 0, mask = 00...00 and this is a no-op;
255256
* if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */
256-
uint32_t mask = !flag - 1;
257+
volatile int vflag = flag;
258+
uint32_t mask = -vflag;
257259
uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0);
258260
uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask);
259261
r->d[0] = t & nonzero; t >>= 32;

0 commit comments

Comments
 (0)