Skip to content

Commit 9fa11a7

Browse files
committed
Add VERIFY_CHECKs that flags are 0 or 1
Flags for constant-time masking rely on the values being exactly 0 or 1 rather than 0 or true. Add VERIFY_CHECKs to enforce in VERIFY builds as a preventative measure and add documentation where relevant.
1 parent e7f7083 commit 9fa11a7

File tree

10 files changed

+28
-7
lines changed

10 files changed

+28
-7
lines changed

src/field.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@ static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe
307307
*/
308308
static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
309309

310-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
310+
/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time.
311+
* Both *r and *a must be initialized. Flag must be 0 or 1. */
311312
static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag);
312313

313314
/** Conditionally move a field element in constant time.

src/field_10x26_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,7 @@ SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp25
10141014
SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
10151015
uint32_t mask0, mask1;
10161016
volatile int vflag = flag;
1017+
VERIFY_CHECK(flag == 0 || flag == 1);
10171018
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
10181019
mask0 = vflag + ~((uint32_t)0);
10191020
mask1 = ~mask0;
@@ -1097,6 +1098,7 @@ static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r) {
10971098
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
10981099
uint32_t mask0, mask1;
10991100
volatile int vflag = flag;
1101+
VERIFY_CHECK(flag == 0 || flag == 1);
11001102
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
11011103
mask0 = vflag + ~((uint32_t)0);
11021104
mask1 = ~mask0;

src/field_5x52_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp25
349349
SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
350350
uint64_t mask0, mask1;
351351
volatile int vflag = flag;
352+
VERIFY_CHECK(flag == 0 || flag == 1);
352353
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
353354
mask0 = vflag + ~((uint64_t)0);
354355
mask1 = ~mask0;
@@ -416,6 +417,7 @@ static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r) {
416417
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
417418
uint64_t mask0, mask1;
418419
volatile int vflag = flag;
420+
VERIFY_CHECK(flag == 0 || flag == 1);
419421
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
420422
mask0 = vflag + ~((uint64_t)0);
421423
mask1 = ~mask0;

src/group.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,12 @@ static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge
169169
/** Convert a group element back from the storage type. */
170170
static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a);
171171

172-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
172+
/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time.
173+
* Both *r and *a must be initialized. Flag must be 0 or 1. */
173174
static void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag);
174175

175-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
176+
/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time.
177+
* Both *r and *a must be initialized. Flag must be 0 or 1. */
176178
static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag);
177179

178180
/** Rescale a jacobian point by b which must be non-zero. Constant-time. */

src/group_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storag
898898
static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) {
899899
SECP256K1_GEJ_VERIFY(r);
900900
SECP256K1_GEJ_VERIFY(a);
901+
VERIFY_CHECK(flag == 0 || flag == 1);
901902

902903
secp256k1_fe_cmov(&r->x, &a->x, flag);
903904
secp256k1_fe_cmov(&r->y, &a->y, flag);
@@ -908,6 +909,7 @@ static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k
908909
}
909910

910911
static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) {
912+
VERIFY_CHECK(flag == 0 || flag == 1);
911913
secp256k1_fe_storage_cmov(&r->x, &a->x, flag);
912914
secp256k1_fe_storage_cmov(&r->y, &a->y, flag);
913915
}

src/scalar.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar*
4848
/** Add two scalars together (modulo the group order). Returns whether it overflowed. */
4949
static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b);
5050

51-
/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */
51+
/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. Flag must be 0 or 1. */
5252
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag);
5353

5454
/** Multiply two scalars (modulo the group order). */
@@ -78,7 +78,7 @@ static int secp256k1_scalar_is_even(const secp256k1_scalar *a);
7878
/** Check whether a scalar is higher than the group order divided by 2. */
7979
static int secp256k1_scalar_is_high(const secp256k1_scalar *a);
8080

81-
/** Conditionally negate a number, in constant time.
81+
/** Conditionally negate a number, in constant time. Flag must be 0 or 1.
8282
* Returns -1 if the number was negated, 1 otherwise */
8383
static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag);
8484

@@ -95,7 +95,7 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT
9595
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
9696
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift);
9797

98-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
98+
/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time. Both *r and *a must be initialized. Flag must be 0 or 1. */
9999
static void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag);
100100

101101
/** Check invariants on a scalar (no-op unless VERIFY is enabled). */

src/scalar_4x64_impl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a,
120120
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
121121
secp256k1_uint128 t;
122122
volatile int vflag = flag;
123+
VERIFY_CHECK(flag == 0 || flag == 1);
123124
SECP256K1_SCALAR_VERIFY(r);
124125
VERIFY_CHECK(bit < 256);
125126

@@ -259,6 +260,7 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
259260
uint64_t mask = -vflag;
260261
uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1;
261262
secp256k1_uint128 t;
263+
VERIFY_CHECK(flag == 0 || flag == 1);
262264
SECP256K1_SCALAR_VERIFY(r);
263265

264266
secp256k1_u128_from_u64(&t, r->d[0] ^ mask);
@@ -911,6 +913,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
911913
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
912914
uint64_t mask0, mask1;
913915
volatile int vflag = flag;
916+
VERIFY_CHECK(flag == 0 || flag == 1);
914917
SECP256K1_SCALAR_VERIFY(a);
915918
SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d));
916919

src/scalar_8x32_impl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a,
147147
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
148148
uint64_t t;
149149
volatile int vflag = flag;
150+
VERIFY_CHECK(flag == 0 || flag == 1);
150151
SECP256K1_SCALAR_VERIFY(r);
151152
VERIFY_CHECK(bit < 256);
152153

@@ -314,6 +315,7 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
314315
uint32_t mask = -vflag;
315316
uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0);
316317
uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask);
318+
VERIFY_CHECK(flag == 0 || flag == 1);
317319
SECP256K1_SCALAR_VERIFY(r);
318320

319321
r->d[0] = t & nonzero; t >>= 32;
@@ -709,6 +711,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
709711
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
710712
uint32_t mask0, mask1;
711713
volatile int vflag = flag;
714+
VERIFY_CHECK(flag == 0 || flag == 1);
712715
SECP256K1_SCALAR_VERIFY(a);
713716
SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d));
714717

src/scalar_low_impl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a,
5656

5757
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
5858
SECP256K1_SCALAR_VERIFY(r);
59+
VERIFY_CHECK(flag == 0 || flag == 1);
5960

6061
if (flag && bit < 32)
6162
*r += ((uint32_t)1 << bit);
@@ -121,6 +122,7 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar *a) {
121122

122123
static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
123124
SECP256K1_SCALAR_VERIFY(r);
125+
VERIFY_CHECK(flag == 0 || flag == 1);
124126

125127
if (flag) secp256k1_scalar_negate(r, r);
126128

@@ -157,6 +159,7 @@ SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const
157159
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
158160
uint32_t mask0, mask1;
159161
volatile int vflag = flag;
162+
VERIFY_CHECK(flag == 0 || flag == 1);
160163
SECP256K1_SCALAR_VERIFY(a);
161164
SECP256K1_CHECKMEM_CHECK_VERIFY(r, sizeof(*r));
162165

src/util.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ static SECP256K1_INLINE void secp256k1_memczero(void *s, size_t len, int flag) {
212212
take only be 0 or 1, which leads to variable time code. */
213213
volatile int vflag = flag;
214214
unsigned char mask = -(unsigned char) vflag;
215+
VERIFY_CHECK(flag == 0 || flag == 1);
215216
while (len) {
216217
*p &= ~mask;
217218
p++;
@@ -294,14 +295,16 @@ static SECP256K1_INLINE int secp256k1_is_zero_array(const unsigned char *s, size
294295
return ret;
295296
}
296297

297-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized and non-negative.*/
298+
/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time.
299+
* Both *r and *a must be initialized and non-negative. Flag must be 0 or 1. */
298300
static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) {
299301
unsigned int mask0, mask1, r_masked, a_masked;
300302
/* Access flag with a volatile-qualified lvalue.
301303
This prevents clang from figuring out (after inlining) that flag can
302304
take only be 0 or 1, which leads to variable time code. */
303305
volatile int vflag = flag;
304306

307+
VERIFY_CHECK(flag == 0 || flag == 1);
305308
/* Casting a negative int to unsigned and back to int is implementation defined behavior */
306309
VERIFY_CHECK(*r >= 0 && *a >= 0);
307310

0 commit comments

Comments
 (0)