Skip to content
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

Clear sensitive memory without getting optimized out (revival of #636) #1579

Merged
2 changes: 1 addition & 1 deletion src/bench_ecmult.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset
secp256k1_scalar sum_scalars;

secp256k1_gej_set_infinity(&sum_output);
secp256k1_scalar_clear(&sum_scalars);
secp256k1_scalar_set_int(&sum_scalars, 0);
for (i = 0; i < iters; ++i) {
secp256k1_gej_add_var(&sum_output, &sum_output, &data->output[i], NULL);
if (scalar_gen_offset != NULL) {
Expand Down
9 changes: 5 additions & 4 deletions src/ecmult_gen_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,8 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25
/* Cleanup. */
secp256k1_fe_clear(&neg);
secp256k1_ge_clear(&add);
memset(&adds, 0, sizeof(adds));
memset(&recoded, 0, sizeof(recoded));
secp256k1_memclear(&adds, sizeof(adds));
secp256k1_memclear(&recoded, sizeof(recoded));
}

/* Setup blinding values for secp256k1_ecmult_gen. */
Expand Down Expand Up @@ -310,7 +310,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
VERIFY_CHECK(seed32 != NULL);
memcpy(keydata + 32, seed32, 32);
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64);
memset(keydata, 0, sizeof(keydata));
secp256k1_memclear(keydata, sizeof(keydata));

/* Compute projective blinding factor (cannot be 0). */
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
Expand All @@ -325,16 +325,17 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
* which secp256k1_gej_add_ge cannot handle. */
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);
secp256k1_scalar_add(&ctx->scalar_offset, &b, &diff);
secp256k1_ge_set_gej(&ctx->ge_offset, &gb);

/* Clean up. */
secp256k1_memclear(nonce32, sizeof(nonce32));
secp256k1_scalar_clear(&b);
secp256k1_gej_clear(&gb);
secp256k1_fe_clear(&f);
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 @@ -171,14 +171,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_limb32(&s, 255, 1)) {
secp256k1_scalar_negate(&s, &s);
sign = -1;
}

bit = 0;
while (bit < len) {
int now;
int word;
Expand Down Expand Up @@ -660,7 +663,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;

secp256k1_gej_set_infinity(r);
Expand Down Expand Up @@ -708,18 +710,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
7 changes: 1 addition & 6 deletions src/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
# define secp256k1_fe_normalizes_to_zero secp256k1_fe_impl_normalizes_to_zero
# define secp256k1_fe_normalizes_to_zero_var secp256k1_fe_impl_normalizes_to_zero_var
# define secp256k1_fe_set_int secp256k1_fe_impl_set_int
# define secp256k1_fe_clear secp256k1_fe_impl_clear
# define secp256k1_fe_is_zero secp256k1_fe_impl_is_zero
# define secp256k1_fe_is_odd secp256k1_fe_impl_is_odd
# define secp256k1_fe_cmp_var secp256k1_fe_impl_cmp_var
Expand Down Expand Up @@ -144,11 +143,7 @@ static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r);
*/
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);

/** Set a field element to 0.
*
* On input, a does not need to be initialized.
* On output, a represents 0, is normalized and has magnitude 0.
*/
/** Clear a field element to prevent leaking sensitive information. */
static void secp256k1_fe_clear(secp256k1_fe *a);

/** Determine whether a represents field element 0.
Expand Down
7 changes: 0 additions & 7 deletions src/field_10x26_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,6 @@ SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) {
return a->n[0] & 1;
}

SECP256K1_INLINE static void secp256k1_fe_impl_clear(secp256k1_fe *a) {
int i;
for (i=0; i<10; i++) {
a->n[i] = 0;
}
}

static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
int i;
for (i = 9; i >= 0; i--) {
Expand Down
7 changes: 0 additions & 7 deletions src/field_5x52_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,6 @@ SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) {
return a->n[0] & 1;
}

SECP256K1_INLINE static void secp256k1_fe_impl_clear(secp256k1_fe *a) {
int i;
for (i=0; i<5; i++) {
a->n[i] = 0;
}
}

static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
int i;
for (i = 4; i >= 0; i--) {
Expand Down
13 changes: 4 additions & 9 deletions src/field_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#error "Please select wide multiplication implementation"
#endif

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

SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) {
secp256k1_fe na;
SECP256K1_FE_VERIFY(a);
Expand Down Expand Up @@ -232,15 +236,6 @@ SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
SECP256K1_FE_VERIFY(r);
}

static void secp256k1_fe_impl_clear(secp256k1_fe *a);
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
a->magnitude = 0;
a->normalized = 1;
secp256k1_fe_impl_clear(a);

SECP256K1_FE_VERIFY(a);
}

static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a);
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) {
SECP256K1_FE_VERIFY(a);
Expand Down
23 changes: 7 additions & 16 deletions src/group_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,36 +283,27 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se

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);

SECP256K1_GEJ_VERIFY(r);
}

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);

SECP256K1_GE_VERIFY(r);
}

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);

SECP256K1_GEJ_VERIFY(r);
secp256k1_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);

SECP256K1_GE_VERIFY(r);
secp256k1_memclear(r, sizeof(secp256k1_ge));
}

static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
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 */
19 changes: 14 additions & 5 deletions src/hash_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const uns
secp256k1_sha256_write(hash, buf, 32);
}

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

static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) {
size_t n;
unsigned char rkey[64];
Expand All @@ -196,7 +200,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));
secp256k1_memclear(rkey, sizeof(rkey));
}

static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) {
Expand All @@ -207,10 +211,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);
secp256k1_memclear(temp, sizeof(temp));
secp256k1_sha256_finalize(&hash->outer, out32);
}

static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash) {
secp256k1_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 @@ -274,9 +281,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) {
secp256k1_memclear(rng, sizeof(*rng));
}

#undef Round
Expand Down
7 changes: 5 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,11 @@ 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);
secp256k1_memclear(x, sizeof(x));
secp256k1_memclear(y, sizeof(y));
secp256k1_scalar_clear(&s);
secp256k1_ge_clear(&pt);
secp256k1_gej_clear(&res);

return !!ret & !overflow;
}
Expand Down
4 changes: 3 additions & 1 deletion src/modules/ellswift/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsign
secp256k1_sha256_write(&sha, ell_b64, 64);
secp256k1_sha256_write(&sha, x32, 32);
secp256k1_sha256_finalize(&sha, output);
secp256k1_sha256_clear(&sha);

return 1;
}
Expand Down Expand Up @@ -539,6 +540,7 @@ static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsign
secp256k1_sha256_write(&sha, ell_b64, 64);
secp256k1_sha256_write(&sha, x32, 32);
secp256k1_sha256_finalize(&sha, output);
secp256k1_sha256_clear(&sha);

return 1;
}
Expand Down Expand Up @@ -580,7 +582,7 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output,
/* Invoke hasher */
ret = hashfp(output, sx, ell_a64, ell_b64, data);

memset(sx, 0, 32);
secp256k1_memclear(sx, sizeof(sx));
secp256k1_fe_clear(&px);
secp256k1_scalar_clear(&s);

Expand Down
11 changes: 6 additions & 5 deletions src/modules/musig/session_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,11 +385,11 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c
secp256k1_scalar_set_b32(&k[i], buf, NULL);

/* Attempt to erase secret data */
memset(buf, 0, sizeof(buf));
memset(&sha_tmp, 0, sizeof(sha_tmp));
secp256k1_memclear(buf, sizeof(buf));
secp256k1_sha256_clear(&sha_tmp);
}
memset(rand, 0, sizeof(rand));
memset(&sha, 0, sizeof(sha));
secp256k1_memclear(rand, sizeof(rand));
secp256k1_sha256_clear(&sha);
}

int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) {
Expand Down Expand Up @@ -450,6 +450,7 @@ int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_m
secp256k1_ge_set_gej(&nonce_pts[i], &nonce_ptj);
secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts));
secp256k1_scalar_clear(&k[i]);
secp256k1_gej_clear(&nonce_ptj);
}
/* None of the nonce_pts will be infinity because k != 0 with overwhelming
* probability */
Expand Down Expand Up @@ -509,7 +510,7 @@ int secp256k1_musig_nonce_gen_counter(const secp256k1_context* ctx, secp256k1_mu
if (!secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32)) {
return 0;
}
memset(seckey, 0, sizeof(seckey));
secp256k1_memclear(seckey, sizeof(seckey));
return 1;
}

Expand Down
4 changes: 3 additions & 1 deletion src/modules/schnorrsig/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms
secp256k1_sha256_write(&sha, xonly_pk32, 32);
secp256k1_sha256_write(&sha, msg, msglen);
secp256k1_sha256_finalize(&sha, nonce32);
secp256k1_sha256_clear(&sha);
return 1;
}

Expand Down Expand Up @@ -187,7 +188,8 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
secp256k1_memczero(sig64, 64, !ret);
secp256k1_scalar_clear(&k);
secp256k1_scalar_clear(&sk);
memset(seckey, 0, sizeof(seckey));
secp256k1_memclear(seckey, sizeof(seckey));
secp256k1_gej_clear(&rj);

return ret;
}
Expand Down
7 changes: 0 additions & 7 deletions src/scalar_4x64_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,6 @@
#define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL)
#define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL)

SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) {
r->d[0] = 0;
r->d[1] = 0;
r->d[2] = 0;
r->d[3] = 0;
}

SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) {
r->d[0] = v;
r->d[1] = 0;
Expand Down
Loading