Skip to content

Commit a39c2b0

Browse files
committed
Fixed UB(arithmetics on uninit values) in cmovs
1 parent 3a6fd7f commit a39c2b0

File tree

5 files changed

+12
-7
lines changed

5 files changed

+12
-7
lines changed

src/ecmult_const_impl.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
/* This is like `ECMULT_TABLE_GET_GE` but is constant time */
1616
#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \
17-
int m; \
17+
int m = 0; \
1818
/* Extract the sign-bit for a constant time absolute-value. */ \
1919
int mask = (n) >> (sizeof(n) * CHAR_BIT - 1); \
2020
int abs_n = ((n) + mask) ^ mask; \
@@ -25,7 +25,11 @@
2525
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
2626
VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \
2727
VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \
28-
for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \
28+
/* Unconditionally set r->x = (pre)[m].x. r->y = (pre)[m].y. because it's either the correct one \
29+
* or will get replaced in the later iterations, this is needed to make sure `r` is initialized. */ \
30+
(r)->x = (pre)[m].x; \
31+
(r)->y = (pre)[m].y; \
32+
for (m = 1; m < ECMULT_TABLE_SIZE(w); m++) { \
2933
/* This loop is used to avoid secret data in array indices. See
3034
* the comment in ecmult_gen_impl.h for rationale. */ \
3135
secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \

src/field.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,10 @@ static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe
125125
/** Convert a field element back from the storage type. */
126126
static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
127127

128-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
128+
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
129129
static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag);
130130

131-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
131+
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
132132
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
133133

134134
#endif /* SECP256K1_FIELD_H */

src/group.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge
132132
/** Convert a group element back from the storage type. */
133133
static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a);
134134

135-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
135+
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
136136
static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag);
137137

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

src/scalar.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
111111
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
112112
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift);
113113

114-
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
114+
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
115115
static void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag);
116116

117117
#endif /* SECP256K1_SCALAR_H */

src/secp256k1.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,8 @@ const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function
468468
const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979;
469469

470470
int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
471-
secp256k1_scalar r, s;
471+
/* Default initialization here is important so we won't pass uninit values to the cmov in the end */
472+
secp256k1_scalar r = secp256k1_scalar_zero, s = secp256k1_scalar_zero;
472473
secp256k1_scalar sec, non, msg;
473474
int ret = 0;
474475
int is_sec_valid;

0 commit comments

Comments
 (0)