Skip to content

Clear sensitive memory without getting optimized out #636

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed
4 changes: 2 additions & 2 deletions src/ecmult_const_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
VERIFY_CHECK(((n) & 1) == 1); \
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \
VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \
VERIFY_SETUP(secp256k1_fe_set_int(&(r)->x, 0)); \
VERIFY_SETUP(secp256k1_fe_set_int(&(r)->y, 0)); \
for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \
/* This loop is used to avoid secret data in array indices. See
* the comment in ecmult_gen_impl.h for rationale. */ \
Expand Down
8 changes: 5 additions & 3 deletions src/ecmult_gen_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
secp256k1_ge_from_storage(&add, &adds);
secp256k1_gej_add_ge(r, r, &add);
}
bits = 0;
memclear(&bits, sizeof(bits));
secp256k1_ge_clear(&add);
secp256k1_scalar_clear(&gnb);
}
Expand Down Expand Up @@ -182,7 +182,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
memcpy(keydata + 32, seed32, 32);
}
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32);
memset(keydata, 0, sizeof(keydata));
memclear(keydata, sizeof(keydata));
/* Accept unobservably small non-uniformity. */
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
overflow = !secp256k1_fe_set_b32(&s, nonce32);
Expand All @@ -196,13 +196,15 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
/* A blinding value of 0 works, but would undermine the projection hardening. */
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);
secp256k1_scalar_negate(&b, &b);
ctx->blind = b;
ctx->initial = gb;

memclear(nonce32, sizeof(nonce32));
secp256k1_scalar_clear(&b);
secp256k1_gej_clear(&gb);
secp256k1_rfc6979_hmac_sha256_clear(&rng);
}

#endif /* SECP256K1_ECMULT_GEN_IMPL_H */
18 changes: 4 additions & 14 deletions src/ecmult_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,14 +406,17 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
VERIFY_CHECK(a != NULL);
VERIFY_CHECK(2 <= w && w <= 31);

memset(wnaf, 0, len * sizeof(wnaf[0]));
for (bit = 0; bit < len; bit++) {
wnaf[bit] = 0;
}

s = *a;
if (secp256k1_scalar_get_bits(&s, 255, 1)) {
secp256k1_scalar_negate(&s, &s);
sign = -1;
}

bit = 0;
while (bit < len) {
int now;
int word;
Expand Down Expand Up @@ -1005,7 +1008,6 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
struct secp256k1_pippenger_state *state_space;
size_t idx = 0;
size_t point_idx = 0;
int i, j;
int bucket_window;

(void)ctx;
Expand Down Expand Up @@ -1055,18 +1057,6 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
}

secp256k1_ecmult_pippenger_wnaf(buckets, bucket_window, state_space, r, scalars, points, idx);

/* Clear data */
for(i = 0; (size_t)i < idx; i++) {
secp256k1_scalar_clear(&scalars[i]);
state_space->ps[i].skew_na = 0;
for(j = 0; j < WNAF_SIZE(bucket_window+1); j++) {
state_space->wnaf_na[i * WNAF_SIZE(bucket_window+1) + j] = 0;
}
}
for(i = 0; i < 1<<bucket_window; i++) {
secp256k1_gej_clear(&buckets[i]);
}
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
return 1;
}
Expand Down
9 changes: 5 additions & 4 deletions src/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
* - Each field element can be normalized or not.
* - Each field element has a magnitude, which represents how far away
* its representation is away from normalization. Normalized elements
* always have a magnitude of 1, but a magnitude of 1 doesn't imply
* normality.
* always have a magnitude of 0 or 1, but a magnitude of 1 doesn't
* imply normality.
*/

#if defined HAVE_CONFIG_H
Expand Down Expand Up @@ -51,10 +51,11 @@ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r);
* implementation may optionally normalize the input, but this should not be relied upon. */
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r);

/** Set a field element equal to a small integer. Resulting field element is normalized. */
/** Set a field element equal to a small integer. Resulting field element is normalized; it has
* magnitude 0 if a == 0, and magnitude 1 otherwise. */
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I wondered why this accepts int. An unsigned type seems more appropriate. For type safety, we would even want to exclude too large values and use something as small as unsigned char. But I guess this is slower and just not worth the hassle)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, though this seems like something for another patch.


/** Sets a field element equal to zero, initializing all fields. */
/** Clear a field element to prevent leaking sensitive information. */
static void secp256k1_fe_clear(secp256k1_fe *a);

/** Verify whether a field element is zero. Requires the input to be normalized. */
Expand Down
13 changes: 1 addition & 12 deletions src/field_10x26_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
r->n[0] = a;
r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
#ifdef VERIFY
r->magnitude = 1;
r->magnitude = (a != 0);
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
Expand All @@ -289,17 +289,6 @@ SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
return a->n[0] & 1;
}

SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
int i;
#ifdef VERIFY
a->magnitude = 0;
a->normalized = 1;
#endif
for (i=0; i<10; i++) {
a->n[i] = 0;
}
}

static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
int i;
#ifdef VERIFY
Expand Down
13 changes: 1 addition & 12 deletions src/field_5x52_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
r->n[0] = a;
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
#ifdef VERIFY
r->magnitude = 1;
r->magnitude = (a != 0);
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
Expand All @@ -252,17 +252,6 @@ SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
return a->n[0] & 1;
}

SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
int i;
#ifdef VERIFY
a->magnitude = 0;
a->normalized = 1;
#endif
for (i=0; i<5; i++) {
a->n[i] = 0;
}
}

static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
int i;
#ifdef VERIFY
Expand Down
4 changes: 4 additions & 0 deletions src/field_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const
return secp256k1_fe_normalizes_to_zero_var(&na);
}

SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
memclear(a, sizeof(secp256k1_fe));
}

static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
/** Given that p is congruent to 3 mod 4, we can compute the square root of
* a mod p as the (p+1)/4'th power of a.
Expand Down
19 changes: 7 additions & 12 deletions src/group_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,28 +194,23 @@ static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp

static void secp256k1_gej_set_infinity(secp256k1_gej *r) {
r->infinity = 1;
secp256k1_fe_clear(&r->x);
secp256k1_fe_clear(&r->y);
secp256k1_fe_clear(&r->z);
secp256k1_fe_set_int(&r->x, 0);
secp256k1_fe_set_int(&r->y, 0);
secp256k1_fe_set_int(&r->z, 0);
}

static void secp256k1_ge_set_infinity(secp256k1_ge *r) {
r->infinity = 1;
secp256k1_fe_clear(&r->x);
secp256k1_fe_clear(&r->y);
secp256k1_fe_set_int(&r->x, 0);
secp256k1_fe_set_int(&r->y, 0);
}

static void secp256k1_gej_clear(secp256k1_gej *r) {
r->infinity = 0;
secp256k1_fe_clear(&r->x);
secp256k1_fe_clear(&r->y);
secp256k1_fe_clear(&r->z);
memclear(r, sizeof(secp256k1_gej));
}

static void secp256k1_ge_clear(secp256k1_ge *r) {
r->infinity = 0;
secp256k1_fe_clear(&r->x);
secp256k1_fe_clear(&r->y);
memclear(r, sizeof(secp256k1_ge));
}

static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
Expand Down
3 changes: 3 additions & 0 deletions src/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ typedef struct {
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash);
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32);
static void secp256k1_sha256_clear(secp256k1_sha256 *hash);

typedef struct {
secp256k1_sha256 inner, outer;
Expand All @@ -27,6 +28,7 @@ typedef struct {
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size);
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32);
static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash);

typedef struct {
unsigned char v[32];
Expand All @@ -37,5 +39,6 @@ typedef struct {
static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen);
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen);
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng);
static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng);

#endif /* SECP256K1_HASH_H */
22 changes: 17 additions & 5 deletions src/hash_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@ static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out
hash->s[i] = 0;
}
memcpy(out32, (const unsigned char*)out, 32);

memclear(sizedesc, sizeof(sizedesc));
memclear(out, sizeof(out));
}

static void secp256k1_sha256_clear(secp256k1_sha256 *hash) {
memclear(hash, sizeof(*hash));
}

static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) {
Expand Down Expand Up @@ -188,7 +195,7 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const
rkey[n] ^= 0x5c ^ 0x36;
}
secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey));
memset(rkey, 0, sizeof(rkey));
memclear(rkey, sizeof(rkey));
}

static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) {
Expand All @@ -199,10 +206,13 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned
unsigned char temp[32];
secp256k1_sha256_finalize(&hash->inner, temp);
secp256k1_sha256_write(&hash->outer, temp, 32);
memset(temp, 0, 32);
memclear(temp, sizeof(temp));
secp256k1_sha256_finalize(&hash->outer, out32);
}

static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash) {
memclear(hash, sizeof(*hash));
}

static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) {
secp256k1_hmac_sha256 hmac;
Expand Down Expand Up @@ -266,9 +276,11 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256
}

static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) {
memset(rng->k, 0, 32);
memset(rng->v, 0, 32);
rng->retry = 0;
(void) rng;
}

static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng) {
memclear(rng, sizeof(*rng));
}

#undef BE32
Expand Down
6 changes: 4 additions & 2 deletions src/modules/ecdh/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char
secp256k1_sha256_write(&sha, &version, 1);
secp256k1_sha256_write(&sha, x32, 32);
secp256k1_sha256_finalize(&sha, output);
secp256k1_sha256_clear(&sha);

return 1;
}
Expand Down Expand Up @@ -61,9 +62,10 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se

ret = hashfp(output, x, y, data);

memset(x, 0, 32);
memset(y, 0, 32);
memclear(x, sizeof(x));
memclear(y, sizeof(y));
secp256k1_scalar_clear(&s);
secp256k1_ge_clear(&pt);

return !!ret & !overflow;
}
Expand Down
8 changes: 4 additions & 4 deletions src/modules/recovery/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, cons
}

int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
secp256k1_scalar r, s;
secp256k1_scalar sec, non, msg;
secp256k1_scalar r, s, sec;
int recid;
int ret = 0;
int overflow = 0;
Expand All @@ -138,6 +137,7 @@ int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecd
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
/* Fail if the secret key is invalid. */
if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
secp256k1_scalar non, msg;
unsigned char nonce32[32];
unsigned int count = 0;
secp256k1_scalar_set_b32(&msg, msg32, NULL);
Expand All @@ -154,11 +154,11 @@ int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecd
}
count++;
}
memset(nonce32, 0, 32);
memclear(nonce32, sizeof(nonce32));
secp256k1_scalar_clear(&msg);
secp256k1_scalar_clear(&non);
secp256k1_scalar_clear(&sec);
}
secp256k1_scalar_clear(&sec);
if (ret) {
secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid);
} else {
Expand Down
12 changes: 6 additions & 6 deletions src/num_gmp_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const sec
if (len > shift) {
memcpy(r + rlen - len + shift, tmp + shift, len - shift);
}
memset(tmp, 0, sizeof(tmp));
memclear(tmp, sizeof(tmp));
}

static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen) {
Expand Down Expand Up @@ -85,7 +85,7 @@ static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) {
if (r->limbs >= m->limbs) {
mp_limb_t t[2*NUM_LIMBS];
mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs);
memset(t, 0, sizeof(t));
memclear(t, sizeof(t));
r->limbs = m->limbs;
while (r->limbs > 1 && r->data[r->limbs-1]==0) {
r->limbs--;
Expand Down Expand Up @@ -139,9 +139,9 @@ static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a,
} else {
r->limbs = sn;
}
memset(g, 0, sizeof(g));
memset(u, 0, sizeof(u));
memset(v, 0, sizeof(v));
memclear(g, sizeof(g));
memclear(u, sizeof(u));
memclear(v, sizeof(v));
}

static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b) {
Expand Down Expand Up @@ -256,7 +256,7 @@ static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const se
VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS);
mpn_copyi(r->data, tmp, r->limbs);
r->neg = a->neg ^ b->neg;
memset(tmp, 0, sizeof(tmp));
memclear(tmp, sizeof(tmp));
}

static void secp256k1_num_shift(secp256k1_num *r, int bits) {
Expand Down
Loading