Skip to content

Commit 5639e72

Browse files
committed
Make secp256k1_scalar_add_bit conditional; make secp256k1_scalar_split_lambda_var constant time
This has the effect of making `secp256k1_scalar_mul_shift_var` constant time in both input scalars. Keep the _var name because it is NOT constant time in the shift amount. As used in `secp256k1_scalar_split_lambda_var`, the shift is always the constant 272, so this function becomes constant time, and it loses the `_var` suffix.
1 parent a943d84 commit 5639e72

7 files changed

+19
-17
lines changed

src/bench_internal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ void bench_scalar_split(void* arg) {
9797

9898
for (i = 0; i < 20000; i++) {
9999
secp256k1_scalar_t l, r;
100-
secp256k1_scalar_split_lambda_var(&l, &r, &data->scalar_x);
100+
secp256k1_scalar_split_lambda(&l, &r, &data->scalar_x);
101101
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
102102
}
103103
}

src/ecmult_impl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w)
242242
}
243243
word = secp256k1_scalar_get_bits_var(&s, bit, now);
244244
if (word & (1 << (w-1))) {
245-
secp256k1_scalar_add_bit(&s, bit + w);
245+
secp256k1_scalar_cadd_bit(&s, bit + w, 1);
246246
wnaf[set_bits++] = sign * (word - (1 << w));
247247
} else {
248248
wnaf[set_bits++] = sign * word;
@@ -280,7 +280,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
280280

281281
#ifdef USE_ENDOMORPHISM
282282
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
283-
secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na);
283+
secp256k1_scalar_split_lambda(&na_1, &na_lam, na);
284284

285285
/* build wnaf representation for na_1 and na_lam. */
286286
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);

src/scalar.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_
4242
/** Add two scalars together (modulo the group order). Returns whether it overflowed. */
4343
static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
4444

45-
/** Add a power of two to a scalar. The result is not allowed to overflow. */
46-
static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit);
45+
/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */
46+
static void secp256k1_scalar_cadd_bit(secp256k1_scalar_t *r, unsigned int bit, int flag);
4747

4848
/** Multiply two scalars (modulo the group order). */
4949
static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
@@ -95,7 +95,7 @@ static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scal
9595
/** Find r1 and r2 such that r1+r2*2^128 = a. */
9696
static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
9797
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */
98-
static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
98+
static void secp256k1_scalar_split_lambda(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
9999
#endif
100100

101101
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */

src/scalar_4x64_impl.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,10 @@ static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t
9696
return overflow;
9797
}
9898

99-
static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
99+
static void secp256k1_scalar_cadd_bit(secp256k1_scalar_t *r, unsigned int bit, int flag) {
100100
uint128_t t;
101101
VERIFY_CHECK(bit < 256);
102+
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */
102103
t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
103104
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
104105
t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
@@ -940,9 +941,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar_t *
940941
r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0;
941942
r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0;
942943
r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0;
943-
if ((l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1) {
944-
secp256k1_scalar_add_bit(r, 0);
945-
}
944+
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1);
946945
}
947946

948947
#endif

src/scalar_8x32_impl.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,10 @@ static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t
136136
return overflow;
137137
}
138138

139-
static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
139+
static void secp256k1_scalar_cadd_bit(secp256k1_scalar_t *r, unsigned int bit, int flag) {
140140
uint64_t t;
141141
VERIFY_CHECK(bit < 256);
142+
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */
142143
t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F));
143144
r->d[0] = t & 0xFFFFFFFFULL; t >>= 32;
144145
t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F));
@@ -714,9 +715,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar_t *
714715
r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0;
715716
r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0;
716717
r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0;
717-
if ((l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1) {
718-
secp256k1_scalar_add_bit(r, 0);
719-
}
718+
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1);
720719
}
721720

722721
#endif

src/scalar_impl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_
295295
* The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order).
296296
*/
297297

298-
static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
298+
static void secp256k1_scalar_split_lambda(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
299299
secp256k1_scalar_t c1, c2;
300300
static const secp256k1_scalar_t minus_lambda = SECP256K1_SCALAR_CONST(
301301
0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL,
@@ -319,6 +319,7 @@ static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_
319319
);
320320
VERIFY_CHECK(r1 != a);
321321
VERIFY_CHECK(r2 != a);
322+
/* these _var calls are constant time since the shift amount is constant */
322323
secp256k1_scalar_mul_shift_var(&c1, a, &g1, 272);
323324
secp256k1_scalar_mul_shift_var(&c2, a, &g2, 272);
324325
secp256k1_scalar_mul(&c1, &c1, &minus_b1);

src/tests.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,10 @@ void scalar_test(void) {
562562
r2 = s1;
563563
if (!secp256k1_scalar_add(&r1, &r1, &b)) {
564564
/* No overflow happened. */
565-
secp256k1_scalar_add_bit(&r2, bit);
565+
secp256k1_scalar_cadd_bit(&r2, bit, 1);
566+
CHECK(secp256k1_scalar_eq(&r1, &r2));
567+
/* cadd is a noop when flag is zero */
568+
secp256k1_scalar_cadd_bit(&r2, bit, 0);
566569
CHECK(secp256k1_scalar_eq(&r1, &r2));
567570
}
568571
}
@@ -1705,7 +1708,7 @@ void test_scalar_split(void) {
17051708
unsigned char tmp[32];
17061709

17071710
random_scalar_order_test(&full);
1708-
secp256k1_scalar_split_lambda_var(&s1, &slam, &full);
1711+
secp256k1_scalar_split_lambda(&s1, &slam, &full);
17091712
CHECK(!secp256k1_scalar_is_zero(&s1));
17101713
CHECK(!secp256k1_scalar_is_zero(&slam));
17111714

0 commit comments

Comments
 (0)