Eliminate harmless non-constant time operations on secret data.
There were several places where the code was non-constant time for invalid secret inputs. These are harmless under sane use but get in the way of automatic const-time validation. (Nonce overflow in signing is not addressed, nor is s==0 in signing)
This commit is contained in:
parent
856a01d6ad
commit
34a67c773b
|
@ -280,6 +280,7 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
|
|||
secp256k1_ge r;
|
||||
secp256k1_scalar n;
|
||||
int overflow = 0;
|
||||
int high;
|
||||
|
||||
secp256k1_ecmult_gen(ctx, &rp, nonce);
|
||||
secp256k1_ge_set_gej(&r, &rp);
|
||||
|
@ -295,7 +296,7 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
|
|||
/* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log
|
||||
* of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria.
|
||||
*/
|
||||
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
|
||||
*recid = (overflow << 1) | secp256k1_fe_is_odd(&r.y);
|
||||
}
|
||||
secp256k1_scalar_mul(&n, sigr, seckey);
|
||||
secp256k1_scalar_add(&n, &n, message);
|
||||
|
@ -304,16 +305,12 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
|
|||
secp256k1_scalar_clear(&n);
|
||||
secp256k1_gej_clear(&rp);
|
||||
secp256k1_ge_clear(&r);
|
||||
if (secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
if (secp256k1_scalar_is_high(sigs)) {
|
||||
secp256k1_scalar_negate(sigs, sigs);
|
||||
high = secp256k1_scalar_is_high(sigs);
|
||||
secp256k1_scalar_cond_negate(sigs, high);
|
||||
if (recid) {
|
||||
*recid ^= 1;
|
||||
*recid ^= high;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return !secp256k1_scalar_is_zero(sigs);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_ECDSA_IMPL_H */
|
||||
|
|
|
@ -75,12 +75,11 @@ static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx,
|
|||
}
|
||||
|
||||
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
|
||||
if (secp256k1_scalar_is_zero(tweak)) {
|
||||
return 0;
|
||||
}
|
||||
int ret;
|
||||
ret = !secp256k1_scalar_is_zero(tweak);
|
||||
|
||||
secp256k1_scalar_mul(key, key, tweak);
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) {
|
||||
|
|
|
@ -163,7 +163,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
|
|||
secp256k1_fe s;
|
||||
unsigned char nonce32[32];
|
||||
secp256k1_rfc6979_hmac_sha256 rng;
|
||||
int retry;
|
||||
int overflow;
|
||||
unsigned char keydata[64] = {0};
|
||||
if (seed32 == NULL) {
|
||||
/* When seed is NULL, reset the initial point and blinding value. */
|
||||
|
@ -183,21 +183,18 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
|
|||
}
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32);
|
||||
memset(keydata, 0, sizeof(keydata));
|
||||
/* Retry for out of range results to achieve uniformity. */
|
||||
do {
|
||||
/* Accept unobservably small non-uniformity. */
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
||||
retry = !secp256k1_fe_set_b32(&s, nonce32);
|
||||
retry = retry || secp256k1_fe_is_zero(&s);
|
||||
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */
|
||||
overflow = !secp256k1_fe_set_b32(&s, nonce32);
|
||||
overflow |= secp256k1_fe_is_zero(&s);
|
||||
secp256k1_fe_cmov(&s, &secp256k1_fe_one, overflow);
|
||||
/* Randomize the projection to defend against multiplier sidechannels. */
|
||||
secp256k1_gej_rescale(&ctx->initial, &s);
|
||||
secp256k1_fe_clear(&s);
|
||||
do {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
||||
secp256k1_scalar_set_b32(&b, nonce32, &retry);
|
||||
secp256k1_scalar_set_b32(&b, nonce32, NULL);
|
||||
/* A blinding value of 0 works, but would undermine the projection hardening. */
|
||||
retry = retry || secp256k1_scalar_is_zero(&b);
|
||||
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */
|
||||
secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b));
|
||||
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
|
||||
memset(nonce32, 0, 32);
|
||||
secp256k1_ecmult_gen(ctx, &gb, &b);
|
||||
|
|
|
@ -320,6 +320,7 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
|||
}
|
||||
|
||||
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
||||
int ret;
|
||||
r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24);
|
||||
r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22);
|
||||
r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20);
|
||||
|
@ -331,15 +332,17 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
|||
r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24);
|
||||
r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14);
|
||||
|
||||
if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) {
|
||||
return 0;
|
||||
}
|
||||
ret = !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL));
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
if (ret) {
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
} else {
|
||||
r->normalized = 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||
|
@ -1107,10 +1110,10 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_
|
|||
r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1);
|
||||
r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1);
|
||||
#ifdef VERIFY
|
||||
if (a->magnitude > r->magnitude) {
|
||||
if (flag) {
|
||||
r->magnitude = a->magnitude;
|
||||
r->normalized = a->normalized;
|
||||
}
|
||||
r->normalized &= a->normalized;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -283,6 +283,7 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
|||
}
|
||||
|
||||
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
||||
int ret;
|
||||
r->n[0] = (uint64_t)a[31]
|
||||
| ((uint64_t)a[30] << 8)
|
||||
| ((uint64_t)a[29] << 16)
|
||||
|
@ -317,15 +318,17 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
|||
| ((uint64_t)a[2] << 24)
|
||||
| ((uint64_t)a[1] << 32)
|
||||
| ((uint64_t)a[0] << 40);
|
||||
if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) {
|
||||
return 0;
|
||||
}
|
||||
ret = !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL));
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
if (ret) {
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
} else {
|
||||
r->normalized = 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||
|
@ -454,10 +457,10 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_
|
|||
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
||||
r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
|
||||
#ifdef VERIFY
|
||||
if (a->magnitude > r->magnitude) {
|
||||
if (flag) {
|
||||
r->magnitude = a->magnitude;
|
||||
r->normalized = a->normalized;
|
||||
}
|
||||
r->normalized &= a->normalized;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -315,4 +315,6 @@ static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
|
||||
|
||||
#endif /* SECP256K1_FIELD_IMPL_H */
|
||||
|
|
|
@ -32,21 +32,23 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
|
|||
secp256k1_gej res;
|
||||
secp256k1_ge pt;
|
||||
secp256k1_scalar s;
|
||||
unsigned char x[32];
|
||||
unsigned char y[32];
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(output != NULL);
|
||||
ARG_CHECK(point != NULL);
|
||||
ARG_CHECK(scalar != NULL);
|
||||
|
||||
if (hashfp == NULL) {
|
||||
hashfp = secp256k1_ecdh_hash_function_default;
|
||||
}
|
||||
|
||||
secp256k1_pubkey_load(ctx, &pt, point);
|
||||
secp256k1_scalar_set_b32(&s, scalar, &overflow);
|
||||
if (overflow || secp256k1_scalar_is_zero(&s)) {
|
||||
ret = 0;
|
||||
} else {
|
||||
unsigned char x[32];
|
||||
unsigned char y[32];
|
||||
|
||||
overflow |= secp256k1_scalar_is_zero(&s);
|
||||
secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow);
|
||||
|
||||
secp256k1_ecmult_const(&res, &pt, &s, 256);
|
||||
secp256k1_ge_set_gej(&pt, &res);
|
||||
|
@ -58,10 +60,12 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
|
|||
secp256k1_fe_get_b32(y, &pt.y);
|
||||
|
||||
ret = hashfp(output, x, y, data);
|
||||
}
|
||||
|
||||
memset(x, 0, 32);
|
||||
memset(y, 0, 32);
|
||||
secp256k1_scalar_clear(&s);
|
||||
return ret;
|
||||
|
||||
return !!ret & !overflow;
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_MODULE_ECDH_MAIN_H */
|
||||
|
|
|
@ -107,4 +107,7 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
|
|||
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
|
||||
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift);
|
||||
|
||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
|
||||
static void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag);
|
||||
|
||||
#endif /* SECP256K1_SCALAR_H */
|
||||
|
|
|
@ -946,4 +946,14 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
|
|||
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1);
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
|
||||
uint64_t mask0, mask1;
|
||||
mask0 = flag + ~((uint64_t)0);
|
||||
mask1 = ~mask0;
|
||||
r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1);
|
||||
r->d[1] = (r->d[1] & mask0) | (a->d[1] & mask1);
|
||||
r->d[2] = (r->d[2] & mask0) | (a->d[2] & mask1);
|
||||
r->d[3] = (r->d[3] & mask0) | (a->d[3] & mask1);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_IMPL_H */
|
||||
|
|
|
@ -718,4 +718,18 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
|
|||
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1);
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
|
||||
uint32_t mask0, mask1;
|
||||
mask0 = flag + ~((uint32_t)0);
|
||||
mask1 = ~mask0;
|
||||
r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1);
|
||||
r->d[1] = (r->d[1] & mask0) | (a->d[1] & mask1);
|
||||
r->d[2] = (r->d[2] & mask0) | (a->d[2] & mask1);
|
||||
r->d[3] = (r->d[3] & mask0) | (a->d[3] & mask1);
|
||||
r->d[4] = (r->d[4] & mask0) | (a->d[4] & mask1);
|
||||
r->d[5] = (r->d[5] & mask0) | (a->d[5] & mask1);
|
||||
r->d[6] = (r->d[6] & mask0) | (a->d[6] & mask1);
|
||||
r->d[7] = (r->d[7] & mask0) | (a->d[7] & mask1);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_IMPL_H */
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#error "Please select scalar implementation"
|
||||
#endif
|
||||
|
||||
static const secp256k1_scalar secp256k1_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1);
|
||||
static const secp256k1_scalar secp256k1_scalar_zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
#ifndef USE_NUM_NONE
|
||||
static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a) {
|
||||
unsigned char c[32];
|
||||
|
|
|
@ -12,4 +12,6 @@
|
|||
/** A scalar modulo the group order of the secp256k1 curve. */
|
||||
typedef uint32_t secp256k1_scalar;
|
||||
|
||||
#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) (d0)
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_H */
|
||||
|
|
|
@ -114,4 +114,11 @@ SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const
|
|||
return *a == *b;
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
|
||||
uint32_t mask0, mask1;
|
||||
mask0 = flag + ~((uint32_t)0);
|
||||
mask1 = ~mask0;
|
||||
*r = (*r & mask0) | (*a & mask1);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_IMPL_H */
|
||||
|
|
|
@ -451,6 +451,8 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
|
|||
secp256k1_scalar sec, non, msg;
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
unsigned char nonce32[32];
|
||||
unsigned int count = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
ARG_CHECK(msg32 != NULL);
|
||||
|
@ -462,17 +464,17 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
|
|||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
||||
/* Fail if the secret key is invalid. */
|
||||
if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
|
||||
unsigned char nonce32[32];
|
||||
unsigned int count = 0;
|
||||
overflow |= secp256k1_scalar_is_zero(&sec);
|
||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, overflow);
|
||||
secp256k1_scalar_set_b32(&msg, msg32, NULL);
|
||||
while (1) {
|
||||
int koverflow;
|
||||
ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count);
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
|
||||
if (!overflow && !secp256k1_scalar_is_zero(&non)) {
|
||||
secp256k1_scalar_set_b32(&non, nonce32, &koverflow);
|
||||
if (!koverflow && !secp256k1_scalar_is_zero(&non)) {
|
||||
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) {
|
||||
break;
|
||||
}
|
||||
|
@ -483,13 +485,10 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
|
|||
secp256k1_scalar_clear(&msg);
|
||||
secp256k1_scalar_clear(&non);
|
||||
secp256k1_scalar_clear(&sec);
|
||||
}
|
||||
if (ret) {
|
||||
secp256k1_scalar_cmov(&r, &secp256k1_scalar_zero, (!ret) | overflow);
|
||||
secp256k1_scalar_cmov(&s, &secp256k1_scalar_zero, (!ret) | overflow);
|
||||
secp256k1_ecdsa_signature_save(signature, &r, &s);
|
||||
} else {
|
||||
memset(signature, 0, sizeof(*signature));
|
||||
}
|
||||
return ret;
|
||||
return !!ret & !overflow;
|
||||
}
|
||||
|
||||
int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) {
|
||||
|
@ -500,7 +499,7 @@ int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char
|
|||
ARG_CHECK(seckey != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
||||
ret = !overflow && !secp256k1_scalar_is_zero(&sec);
|
||||
ret = !overflow & !secp256k1_scalar_is_zero(&sec);
|
||||
secp256k1_scalar_clear(&sec);
|
||||
return ret;
|
||||
}
|
||||
|
@ -518,12 +517,14 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p
|
|||
ARG_CHECK(seckey != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
||||
ret = !overflow && !secp256k1_scalar_is_zero(&sec);
|
||||
if (ret) {
|
||||
ret = !overflow & !secp256k1_scalar_is_zero(&sec);
|
||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, !ret);
|
||||
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
|
||||
secp256k1_ge_set_gej(&p, &pj);
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
}
|
||||
memczero(pubkey, sizeof(*pubkey), !ret);
|
||||
|
||||
secp256k1_scalar_clear(&sec);
|
||||
return ret;
|
||||
}
|
||||
|
@ -568,11 +569,9 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *
|
|||
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
||||
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
||||
|
||||
ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term);
|
||||
memset(seckey, 0, 32);
|
||||
if (ret) {
|
||||
ret = (!overflow) & secp256k1_eckey_privkey_tweak_add(&sec, &term);
|
||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret);
|
||||
secp256k1_scalar_get_b32(seckey, &sec);
|
||||
}
|
||||
|
||||
secp256k1_scalar_clear(&sec);
|
||||
secp256k1_scalar_clear(&term);
|
||||
|
@ -614,11 +613,9 @@ int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *
|
|||
|
||||
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
|
||||
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
||||
ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor);
|
||||
memset(seckey, 0, 32);
|
||||
if (ret) {
|
||||
ret = (!overflow) & secp256k1_eckey_privkey_tweak_mul(&sec, &factor);
|
||||
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret);
|
||||
secp256k1_scalar_get_b32(seckey, &sec);
|
||||
}
|
||||
|
||||
secp256k1_scalar_clear(&sec);
|
||||
secp256k1_scalar_clear(&factor);
|
||||
|
|
|
@ -1822,7 +1822,7 @@ void run_field_misc(void) {
|
|||
q = x;
|
||||
secp256k1_fe_cmov(&x, &z, 0);
|
||||
#ifdef VERIFY
|
||||
CHECK(!x.normalized && x.magnitude == z.magnitude);
|
||||
CHECK(x.normalized && x.magnitude == 1);
|
||||
#endif
|
||||
secp256k1_fe_cmov(&x, &x, 1);
|
||||
CHECK(fe_memcmp(&x, &z) != 0);
|
||||
|
@ -1845,7 +1845,7 @@ void run_field_misc(void) {
|
|||
secp256k1_fe_normalize_var(&q);
|
||||
secp256k1_fe_cmov(&q, &z, (j&1));
|
||||
#ifdef VERIFY
|
||||
CHECK(!q.normalized && q.magnitude == (j+2));
|
||||
CHECK((q.normalized != (j&1)) && q.magnitude == ((j&1) ? z.magnitude : 1));
|
||||
#endif
|
||||
}
|
||||
secp256k1_fe_normalize_var(&z);
|
||||
|
|
12
src/util.h
12
src/util.h
|
@ -160,4 +160,16 @@ static SECP256K1_INLINE void *manual_alloc(void** prealloc_ptr, size_t alloc_siz
|
|||
SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
|
||||
#endif
|
||||
|
||||
/* Zero memory if flag == 1. Constant time. */
|
||||
static SECP256K1_INLINE void memczero(void *s, size_t len, int flag) {
|
||||
unsigned char *p;
|
||||
unsigned char mask = -(unsigned char)flag;
|
||||
p = (unsigned char *)s;
|
||||
while (len) {
|
||||
*p ^= *p & mask;
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_UTIL_H */
|
||||
|
|
Loading…
Reference in New Issue