Try to not leave secret data on the stack or heap.
This makes a basic effort and has not been audited. Doesn't appear to have a measurable performance impact on bench. It also adds a secp256k1_num_free to secp256k1_ecdsa_pubkey_create.
This commit is contained in:
parent
13e44df743
commit
2f6c801911
|
@ -186,7 +186,10 @@ int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_
|
||||||
secp256k1_num_mod(&n, &c->order);
|
secp256k1_num_mod(&n, &c->order);
|
||||||
secp256k1_num_mod_inverse(&sig->s, nonce, &c->order);
|
secp256k1_num_mod_inverse(&sig->s, nonce, &c->order);
|
||||||
secp256k1_num_mod_mul(&sig->s, &sig->s, &n, &c->order);
|
secp256k1_num_mod_mul(&sig->s, &sig->s, &n, &c->order);
|
||||||
|
secp256k1_num_clear(&n);
|
||||||
secp256k1_num_free(&n);
|
secp256k1_num_free(&n);
|
||||||
|
secp256k1_gej_clear(&rp);
|
||||||
|
secp256k1_ge_clear(&r);
|
||||||
if (secp256k1_num_is_zero(&sig->s))
|
if (secp256k1_num_is_zero(&sig->s))
|
||||||
return 0;
|
return 0;
|
||||||
if (secp256k1_num_cmp(&sig->s, &c->half_order) > 0) {
|
if (secp256k1_num_cmp(&sig->s, &c->half_order) > 0) {
|
||||||
|
|
|
@ -190,13 +190,17 @@ void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn)
|
||||||
secp256k1_num_copy(&n, gn);
|
secp256k1_num_copy(&n, gn);
|
||||||
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
|
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
|
||||||
secp256k1_gej_set_infinity(r);
|
secp256k1_gej_set_infinity(r);
|
||||||
|
secp256k1_ge_t add;
|
||||||
|
int bits;
|
||||||
for (int j=0; j<64; j++) {
|
for (int j=0; j<64; j++) {
|
||||||
secp256k1_ge_t add;
|
bits = secp256k1_num_shift(&n, 4);
|
||||||
int bits = secp256k1_num_shift(&n, 4);
|
|
||||||
for (int k=0; k<sizeof(secp256k1_ge_t); k++)
|
for (int k=0; k<sizeof(secp256k1_ge_t); k++)
|
||||||
((unsigned char*)(&add))[k] = c->prec[j][k][bits];
|
((unsigned char*)(&add))[k] = c->prec[j][k][bits];
|
||||||
secp256k1_gej_add_ge(r, r, &add);
|
secp256k1_gej_add_ge(r, r, &add);
|
||||||
}
|
}
|
||||||
|
bits = 0;
|
||||||
|
secp256k1_ge_clear(&add);
|
||||||
|
secp256k1_num_clear(&n);
|
||||||
secp256k1_num_free(&n);
|
secp256k1_num_free(&n);
|
||||||
secp256k1_gej_add_ge(r, r, &c->fin);
|
secp256k1_gej_add_ge(r, r, &c->fin);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,16 @@ int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
|
||||||
return a->n[0] & 1;
|
return a->n[0] & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void static inline secp256k1_fe_clear(secp256k1_fe_t *a) {
|
||||||
|
#ifdef VERIFY
|
||||||
|
a->normalized = 0;
|
||||||
|
a->magnitude = 0;
|
||||||
|
#endif
|
||||||
|
for (int i=0; i<10; i++) {
|
||||||
|
a->n[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: not constant time!
|
// TODO: not constant time!
|
||||||
int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
|
int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
|
||||||
#ifdef VERIFY
|
#ifdef VERIFY
|
||||||
|
|
|
@ -124,6 +124,16 @@ int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
|
||||||
return a->n[0] & 1;
|
return a->n[0] & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void static inline secp256k1_fe_clear(secp256k1_fe_t *a) {
|
||||||
|
#ifdef VERIFY
|
||||||
|
a->magnitude = 0;
|
||||||
|
a->normalized = 0;
|
||||||
|
#endif
|
||||||
|
for (int i=0; i<5; i++) {
|
||||||
|
a->n[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: not constant time!
|
// TODO: not constant time!
|
||||||
int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
|
int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
|
||||||
#ifdef VERIFY
|
#ifdef VERIFY
|
||||||
|
|
|
@ -50,6 +50,11 @@ void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
|
||||||
r->n[i] = 0;
|
r->n[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void static inline secp256k1_fe_clear(secp256k1_fe_t *r) {
|
||||||
|
for (int i=0; i<FIELD_LIMBS+1; i++)
|
||||||
|
r->n[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
|
int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
for (int i=0; i<FIELD_LIMBS+1; i++)
|
for (int i=0; i<FIELD_LIMBS+1; i++)
|
||||||
|
|
|
@ -112,4 +112,11 @@ void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *
|
||||||
void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a);
|
void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Clear a secp256k1_gej_t to prevent leaking sensitive information. */
|
||||||
|
void static secp256k1_gej_clear(secp256k1_gej_t *r);
|
||||||
|
|
||||||
|
/** Clear a secp256k1_ge_t to prevent leaking sensitive information. */
|
||||||
|
void static secp256k1_ge_clear(secp256k1_ge_t *r);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -102,6 +102,19 @@ void static secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, co
|
||||||
secp256k1_fe_set_int(&r->z, 1);
|
secp256k1_fe_set_int(&r->z, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void static secp256k1_gej_clear(secp256k1_gej_t *r) {
|
||||||
|
r->infinity = 0;
|
||||||
|
secp256k1_fe_clear(&r->x);
|
||||||
|
secp256k1_fe_clear(&r->y);
|
||||||
|
secp256k1_fe_clear(&r->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void static secp256k1_ge_clear(secp256k1_ge_t *r) {
|
||||||
|
r->infinity = 0;
|
||||||
|
secp256k1_fe_clear(&r->x);
|
||||||
|
secp256k1_fe_clear(&r->y);
|
||||||
|
}
|
||||||
|
|
||||||
int static secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd) {
|
int static secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd) {
|
||||||
r->x = *x;
|
r->x = *x;
|
||||||
secp256k1_fe_t x2; secp256k1_fe_sqr(&x2, x);
|
secp256k1_fe_t x2; secp256k1_fe_sqr(&x2, x);
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
/** Initialize a number. */
|
/** Initialize a number. */
|
||||||
void static secp256k1_num_init(secp256k1_num_t *r);
|
void static secp256k1_num_init(secp256k1_num_t *r);
|
||||||
|
|
||||||
|
/** Clear a number to prevent the leak of sensitive data. */
|
||||||
|
void static secp256k1_num_clear(secp256k1_num_t *r);
|
||||||
|
|
||||||
/** Free a number. */
|
/** Free a number. */
|
||||||
void static secp256k1_num_free(secp256k1_num_t *r);
|
void static secp256k1_num_free(secp256k1_num_t *r);
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,10 @@ void static secp256k1_num_init(secp256k1_num_t *r) {
|
||||||
r->data[0] = 0;
|
r->data[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void static secp256k1_num_clear(secp256k1_num_t *r) {
|
||||||
|
memset(r, 0, sizeof(*r));
|
||||||
|
}
|
||||||
|
|
||||||
void static secp256k1_num_free(secp256k1_num_t *r) {
|
void static secp256k1_num_free(secp256k1_num_t *r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,8 +58,10 @@ void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const sec
|
||||||
while (shift < len && tmp[shift] == 0) shift++;
|
while (shift < len && tmp[shift] == 0) shift++;
|
||||||
assert(len-shift <= rlen);
|
assert(len-shift <= rlen);
|
||||||
memset(r, 0, rlen - len + shift);
|
memset(r, 0, rlen - len + shift);
|
||||||
if (len > shift)
|
if (len > shift) {
|
||||||
memcpy(r + rlen - len + shift, tmp + shift, len - shift);
|
memcpy(r + rlen - len + shift, tmp + shift, len - shift);
|
||||||
|
}
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) {
|
void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) {
|
||||||
|
@ -97,6 +103,7 @@ void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) {
|
||||||
if (r->limbs >= m->limbs) {
|
if (r->limbs >= m->limbs) {
|
||||||
mp_limb_t t[2*NUM_LIMBS];
|
mp_limb_t t[2*NUM_LIMBS];
|
||||||
mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs);
|
mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs);
|
||||||
|
memset(t, 0, sizeof(t));
|
||||||
r->limbs = m->limbs;
|
r->limbs = m->limbs;
|
||||||
while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
|
while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +148,9 @@ void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t
|
||||||
} else {
|
} else {
|
||||||
r->limbs = sn;
|
r->limbs = sn;
|
||||||
}
|
}
|
||||||
|
memset(g, 0, sizeof(g));
|
||||||
|
memset(u, 0, sizeof(u));
|
||||||
|
memset(v, 0, sizeof(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
int static secp256k1_num_is_zero(const secp256k1_num_t *a) {
|
int static secp256k1_num_is_zero(const secp256k1_num_t *a) {
|
||||||
|
@ -213,6 +223,7 @@ void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, cons
|
||||||
assert(r->limbs <= 2*NUM_LIMBS);
|
assert(r->limbs <= 2*NUM_LIMBS);
|
||||||
mpn_copyi(r->data, tmp, r->limbs);
|
mpn_copyi(r->data, tmp, r->limbs);
|
||||||
r->neg = a->neg ^ b->neg;
|
r->neg = a->neg ^ b->neg;
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
||||||
|
|
|
@ -21,6 +21,10 @@ void static secp256k1_num_free(secp256k1_num_t *r) {
|
||||||
BN_free(&r->bn);
|
BN_free(&r->bn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void static secp256k1_num_clear(secp256k1_num_t *r) {
|
||||||
|
BN_clear(&r->bn);
|
||||||
|
}
|
||||||
|
|
||||||
void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
|
void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
|
||||||
BN_copy(&r->bn, &a->bn);
|
BN_copy(&r->bn, &a->bn);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,9 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned
|
||||||
secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
|
secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
|
||||||
}
|
}
|
||||||
secp256k1_ecdsa_sig_free(&sig);
|
secp256k1_ecdsa_sig_free(&sig);
|
||||||
|
secp256k1_num_clear(&msg);
|
||||||
|
secp256k1_num_clear(&non);
|
||||||
|
secp256k1_num_clear(&sec);
|
||||||
secp256k1_num_free(&msg);
|
secp256k1_num_free(&msg);
|
||||||
secp256k1_num_free(&non);
|
secp256k1_num_free(&non);
|
||||||
secp256k1_num_free(&sec);
|
secp256k1_num_free(&sec);
|
||||||
|
@ -94,6 +97,9 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u
|
||||||
secp256k1_num_get_bin(sig64 + 32, 32, &sig.s);
|
secp256k1_num_get_bin(sig64 + 32, 32, &sig.s);
|
||||||
}
|
}
|
||||||
secp256k1_ecdsa_sig_free(&sig);
|
secp256k1_ecdsa_sig_free(&sig);
|
||||||
|
secp256k1_num_clear(&msg);
|
||||||
|
secp256k1_num_clear(&non);
|
||||||
|
secp256k1_num_clear(&sec);
|
||||||
secp256k1_num_free(&msg);
|
secp256k1_num_free(&msg);
|
||||||
secp256k1_num_free(&non);
|
secp256k1_num_free(&non);
|
||||||
secp256k1_num_free(&sec);
|
secp256k1_num_free(&sec);
|
||||||
|
@ -126,6 +132,7 @@ int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey) {
|
||||||
secp256k1_num_set_bin(&sec, seckey, 32);
|
secp256k1_num_set_bin(&sec, seckey, 32);
|
||||||
int ret = !secp256k1_num_is_zero(&sec) &&
|
int ret = !secp256k1_num_is_zero(&sec) &&
|
||||||
(secp256k1_num_cmp(&sec, &secp256k1_ge_consts->order) < 0);
|
(secp256k1_num_cmp(&sec, &secp256k1_ge_consts->order) < 0);
|
||||||
|
secp256k1_num_clear(&sec);
|
||||||
secp256k1_num_free(&sec);
|
secp256k1_num_free(&sec);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +148,8 @@ int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const u
|
||||||
secp256k1_num_set_bin(&sec, seckey, 32);
|
secp256k1_num_set_bin(&sec, seckey, 32);
|
||||||
secp256k1_gej_t pj;
|
secp256k1_gej_t pj;
|
||||||
secp256k1_ecmult_gen(&pj, &sec);
|
secp256k1_ecmult_gen(&pj, &sec);
|
||||||
|
secp256k1_num_clear(&sec);
|
||||||
|
secp256k1_num_free(&sec);
|
||||||
secp256k1_ge_t p;
|
secp256k1_ge_t p;
|
||||||
secp256k1_ge_set_gej(&p, &pj);
|
secp256k1_ge_set_gej(&p, &pj);
|
||||||
secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, compressed);
|
secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, compressed);
|
||||||
|
@ -173,6 +182,8 @@ int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char
|
||||||
}
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
secp256k1_num_get_bin(seckey, 32, &sec);
|
secp256k1_num_get_bin(seckey, 32, &sec);
|
||||||
|
secp256k1_num_clear(&sec);
|
||||||
|
secp256k1_num_clear(&term);
|
||||||
secp256k1_num_free(&sec);
|
secp256k1_num_free(&sec);
|
||||||
secp256k1_num_free(&term);
|
secp256k1_num_free(&term);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue