diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index 7dc52ad87b..3974af75f4 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -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) { diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 2fbf623ca3..070a121308 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -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. */ @@ -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); @@ -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 */ diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 07d8477eb0..0b53b3fcb9 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -171,7 +171,9 @@ 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)) { @@ -179,6 +181,7 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, sign = -1; } + bit = 0; while (bit < len) { int now; int word; @@ -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); @@ -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<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--) { diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index 76031f755e..46dca6b981 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -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--) { diff --git a/src/field_impl.h b/src/field_impl.h index 989e9cdb2f..896507a3a4 100644 --- a/src/field_impl.h +++ b/src/field_impl.h @@ -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); @@ -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); diff --git a/src/group_impl.h b/src/group_impl.h index 537be32ff6..010af6b0ac 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -281,36 +281,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) { diff --git a/src/hash.h b/src/hash.h index 4e0384cfbf..6d903ca7e0 100644 --- a/src/hash.h +++ b/src/hash.h @@ -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; @@ -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]; @@ -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 */ diff --git a/src/hash_impl.h b/src/hash_impl.h index 89f75ace74..956e0ea48b 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -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]; @@ -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) { @@ -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; @@ -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 diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h index 82b082a9f0..a3dc18332b 100644 --- a/src/modules/ecdh/main_impl.h +++ b/src/modules/ecdh/main_impl.h @@ -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; } @@ -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); + secp256k1_memclear(x, sizeof(x)); + secp256k1_memclear(y, sizeof(y)); secp256k1_scalar_clear(&s); + secp256k1_ge_clear(&pt); return !!ret & !overflow; } diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index b54ec08a22..745a969139 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -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; } @@ -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; } @@ -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); diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 57f7eadd3c..00e62592fa 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -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; } @@ -124,6 +125,7 @@ static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned c secp256k1_sha256_write(&sha, pubkey32, 32); secp256k1_sha256_write(&sha, msg, msglen); secp256k1_sha256_finalize(&sha, buf); + secp256k1_sha256_clear(&sha); /* Set scalar e to the challenge hash modulo the curve order as per * BIP340. */ secp256k1_scalar_set_b32(e, buf, NULL); @@ -187,7 +189,7 @@ 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)); return ret; } diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index 4aaec85b99..807b9b70ab 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -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; diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h index c7d87b17d8..2610496052 100644 --- a/src/scalar_8x32_impl.h +++ b/src/scalar_8x32_impl.h @@ -38,17 +38,6 @@ #define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) #define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) -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; - r->d[4] = 0; - r->d[5] = 0; - r->d[6] = 0; - r->d[7] = 0; -} - SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { r->d[0] = v; r->d[1] = 0; diff --git a/src/scalar_impl.h b/src/scalar_impl.h index 972d8041b0..dbb5b0a01c 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -27,6 +27,10 @@ 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); +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { + secp256k1_memclear(r, sizeof(secp256k1_scalar)); +} + static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned char *bin) { int overflow; secp256k1_scalar_set_b32(r, bin, &overflow); diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h index 45d2f3e460..84e1a380a3 100644 --- a/src/scalar_low_impl.h +++ b/src/scalar_low_impl.h @@ -19,8 +19,6 @@ SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) return !(*a & 1); } -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; } - SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v % EXHAUSTIVE_TEST_ORDER; diff --git a/src/secp256k1.c b/src/secp256k1.c index 72d725a74e..11c9b4fa52 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -506,11 +506,13 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m buffer_append(keydata, &offset, algo16, 16); } secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); - memset(keydata, 0, sizeof(keydata)); for (i = 0; i <= counter; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); + + secp256k1_memclear(keydata, sizeof(keydata)); + secp256k1_rfc6979_hmac_sha256_clear(&rng); return 1; } @@ -560,7 +562,7 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc * seckey. As a result is_sec_valid is included in ret only after ret was * used as a branching variable. */ ret &= is_sec_valid; - memset(nonce32, 0, 32); + secp256k1_memclear(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&msg); secp256k1_scalar_clear(&non); secp256k1_scalar_clear(&sec); diff --git a/src/tests.c b/src/tests.c index 70c15f870b..5d8a4518c0 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3671,8 +3671,7 @@ static void test_ge(void) { secp256k1_fe zfi2, zfi3; secp256k1_gej_set_infinity(&gej[0]); - secp256k1_ge_clear(&ge[0]); - secp256k1_ge_set_gej_var(&ge[0], &gej[0]); + secp256k1_ge_set_infinity(&ge[0]); for (i = 0; i < runs; i++) { int j, k; secp256k1_ge g; @@ -4768,12 +4767,12 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi testutil_random_ge_test(&pt[ncount]); } - secp256k1_scalar_clear(&sc[0]); + secp256k1_scalar_set_int(&sc[0], 0); CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 20)); - secp256k1_scalar_clear(&sc[1]); - secp256k1_scalar_clear(&sc[2]); - secp256k1_scalar_clear(&sc[3]); - secp256k1_scalar_clear(&sc[4]); + secp256k1_scalar_set_int(&sc[1], 0); + secp256k1_scalar_set_int(&sc[2], 0); + secp256k1_scalar_set_int(&sc[3], 0); + secp256k1_scalar_set_int(&sc[4], 0); CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 6)); CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 5)); CHECK(secp256k1_gej_is_infinity(&r)); diff --git a/src/testutil.h b/src/testutil.h index fc56854dd3..64b3bb41c0 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -34,7 +34,7 @@ static void testutil_random_fe_magnitude(secp256k1_fe *fe, int m) { if (n == 0) { return; } - secp256k1_fe_clear(&zero); + secp256k1_fe_set_int(&zero, 0); secp256k1_fe_negate(&zero, &zero, 0); secp256k1_fe_mul_int_unchecked(&zero, n - 1); secp256k1_fe_add(fe, &zero); diff --git a/src/util.h b/src/util.h index ca73752ccc..21e632d453 100644 --- a/src/util.h +++ b/src/util.h @@ -8,11 +8,17 @@ #define SECP256K1_UTIL_H #include "../include/secp256k1.h" +#include "checkmem.h" +#include #include #include #include #include +#if defined(_MSC_VER) +// For SecureZeroMemory +#include +#endif #define STR_(x) #x #define STR(x) STR_(x) @@ -221,6 +227,32 @@ static SECP256K1_INLINE void secp256k1_memczero(void *s, size_t len, int flag) { } } +/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */ +static SECP256K1_INLINE void secp256k1_memclear(void *ptr, size_t len) { +#if defined(_MSC_VER) + /* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */ + SecureZeroMemory(ptr, len); +#elif defined(__GNUC__) + /* We use a memory barrier that scares the compiler away from optimizing out the memset. + * + * Quoting Adam Langley in commit ad1907fe73334d6c696c8539646c21b11178f20f + * in BoringSSL (ISC License): + * As best as we can tell, this is sufficient to break any optimisations that + * might try to eliminate "superfluous" memsets. + * This method used in memzero_explicit() the Linux kernel, too. Its advantage is that it is + * pretty efficient, because the compiler can still implement the memset() efficently, + * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by + * Yang et al. (USENIX Security 2017) for more background. + */ + memset(ptr, 0, len); + __asm__ __volatile__("" : : "r"(ptr) : "memory"); +#else + void *(*volatile const volatile_memset)(void *, int, size_t) = memset; + volatile_memset(ptr, 0, len); +#endif + SECP256K1_CHECKMEM_UNDEFINE(ptr, len); +} + /** Semantics like memcmp. Variable-time. * * We use this to avoid possible compiler bugs with memcmp, e.g.