Skip to content

Clear sensitive memory without getting optimized out. #448

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 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ AC_INIT([libsecp256k1],[0.1])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([build-aux/m4])
AC_CANONICAL_HOST
AC_USE_SYSTEM_EXTENSIONS
AH_TOP([#ifndef LIBSECP256K1_CONFIG_H])
AH_TOP([#define LIBSECP256K1_CONFIG_H])
AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/])
Expand Down Expand Up @@ -153,6 +154,8 @@ AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto]

AC_CHECK_TYPES([__int128])

AC_CHECK_FUNCS([explicit_bzero])

AC_MSG_CHECKING([for __builtin_expect])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])],
[ AC_MSG_RESULT([yes]);AC_DEFINE(HAVE_BUILTIN_EXPECT,1,[Define this symbol if __builtin_expect is available]) ],
Expand Down
2 changes: 0 additions & 2 deletions src/bench_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#include <stdio.h>

#include "include/secp256k1.h"

#include "util.h"
Expand Down
6 changes: 3 additions & 3 deletions src/ecdsa_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,9 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
secp256k1_scalar_add(&n, &n, message);
secp256k1_scalar_inverse(sigs, nonce);
secp256k1_scalar_mul(sigs, sigs, &n);
secp256k1_scalar_clear(&n);
secp256k1_gej_clear(&rp);
secp256k1_ge_clear(&r);
SECP256K1_CLEANSE(n);
SECP256K1_CLEANSE(rp);
SECP256K1_CLEANSE(r);
if (secp256k1_scalar_is_zero(sigs)) {
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ecmult.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx);
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb);
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst,
const secp256k1_ecmult_context *src, const secp256k1_callback *cb);
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx);
static void secp256k1_ecmult_context_teardown(secp256k1_ecmult_context *ctx);
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx);

/** Double multiply: R = na*A + ng*G */
Expand Down
4 changes: 2 additions & 2 deletions src/ecmult_const_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,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_zero(&(r)->x)); \
VERIFY_SETUP(secp256k1_fe_set_zero(&(r)->y)); \
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
4 changes: 3 additions & 1 deletion src/ecmult_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx)
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb);
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst,
const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb);
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx);
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
static void secp256k1_ecmult_gen_context_teardown(secp256k1_ecmult_gen_context* ctx);
#endif
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx);

/** Multiply with the generator: R = a*G */
Expand Down
23 changes: 10 additions & 13 deletions src/ecmult_gen_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,11 @@ static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst
}
}

static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) {
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
static void secp256k1_ecmult_gen_context_teardown(secp256k1_ecmult_gen_context *ctx) {
free(ctx->prec);
#endif
secp256k1_scalar_clear(&ctx->blind);
secp256k1_gej_clear(&ctx->initial);
ctx->prec = NULL;
}
#endif

static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) {
secp256k1_ge add;
Expand Down Expand Up @@ -150,9 +147,9 @@ 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;
secp256k1_ge_clear(&add);
secp256k1_scalar_clear(&gnb);
SECP256K1_CLEANSE(bits);
SECP256K1_CLEANSE(add);
SECP256K1_CLEANSE(gnb);
}

/* Setup blinding values for secp256k1_ecmult_gen. */
Expand Down Expand Up @@ -181,7 +178,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));
SECP256K1_CLEANSE(keydata);
/* Retry for out of range results to achieve uniformity. */
do {
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
Expand All @@ -190,21 +187,21 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */
/* Randomize the projection to defend against multiplier sidechannels. */
secp256k1_gej_rescale(&ctx->initial, &s);
secp256k1_fe_clear(&s);
SECP256K1_CLEANSE(s);
do {
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
secp256k1_scalar_set_b32(&b, nonce32, &retry);
/* A blinding value of 0 works, but would undermine the projection hardening. */
retry |= secp256k1_scalar_is_zero(&b);
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
memset(nonce32, 0, 32);
SECP256K1_CLEANSE(nonce32);
secp256k1_ecmult_gen(ctx, &gb, &b);
secp256k1_scalar_negate(&b, &b);
ctx->blind = b;
ctx->initial = gb;
secp256k1_scalar_clear(&b);
secp256k1_gej_clear(&gb);
SECP256K1_CLEANSE(b);
SECP256K1_CLEANSE(gb);
}

#endif
3 changes: 1 addition & 2 deletions src/ecmult_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,11 @@ static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx
return ctx->pre_g != NULL;
}

static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) {
static void secp256k1_ecmult_context_teardown(secp256k1_ecmult_context *ctx) {
free(ctx->pre_g);
#ifdef USE_ENDOMORPHISM
free(ctx->pre_g_128);
#endif
secp256k1_ecmult_context_init(ctx);
}

/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
Expand Down
2 changes: 1 addition & 1 deletion src/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r);
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);

/** Sets a field element equal to zero, initializing all fields. */
static void secp256k1_fe_clear(secp256k1_fe *a);
static void secp256k1_fe_set_zero(secp256k1_fe *a);

/** Verify whether a field element is zero. Requires the input to be normalized. */
static int secp256k1_fe_is_zero(const secp256k1_fe *a);
Expand Down
2 changes: 1 addition & 1 deletion src/field_10x26_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ 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) {
SECP256K1_INLINE static void secp256k1_fe_set_zero(secp256k1_fe *a) {
int i;
#ifdef VERIFY
a->magnitude = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/field_5x52_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ 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) {
SECP256K1_INLINE static void secp256k1_fe_set_zero(secp256k1_fe *a) {
int i;
#ifdef VERIFY
a->magnitude = 0;
Expand Down
7 changes: 5 additions & 2 deletions src/gen_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ int main(int argc, char **argv) {
}
}
fprintf(fp,"};\n");
secp256k1_ecmult_gen_context_clear(&ctx);

#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
secp256k1_ecmult_gen_context_teardown(&ctx);
#endif
SECP256K1_CLEANSE(ctx);

fprintf(fp, "#undef SC\n");
fprintf(fp, "#endif\n");
fclose(fp);
Expand Down
6 changes: 0 additions & 6 deletions src/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,6 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a,
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a);
#endif

/** Clear a secp256k1_gej to prevent leaking sensitive information. */
static void secp256k1_gej_clear(secp256k1_gej *r);

/** Clear a secp256k1_ge to prevent leaking sensitive information. */
static void secp256k1_ge_clear(secp256k1_ge *r);

/** Convert a group element to the storage type. */
static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a);

Expand Down
19 changes: 3 additions & 16 deletions src/group_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,22 +195,9 @@ 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);
}

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

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

static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
Expand Down
4 changes: 2 additions & 2 deletions src/hash_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, cons
rkey[n] ^= 0x5c ^ 0x36;
}
secp256k1_sha256_write(&hash->inner, rkey, 64);
memset(rkey, 0, 64);
SECP256K1_CLEANSE(rkey);
}

static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) {
Expand All @@ -197,7 +197,7 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsign
unsigned char temp[32];
secp256k1_sha256_finalize(&hash->inner, temp);
secp256k1_sha256_write(&hash->outer, temp, 32);
memset(temp, 0, 32);
SECP256K1_CLEANSE(temp);
secp256k1_sha256_finalize(&hash->outer, out32);
}

Expand Down
2 changes: 1 addition & 1 deletion src/modules/ecdh/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se
ret = 1;
}

secp256k1_scalar_clear(&s);
SECP256K1_CLEANSE(s);
return ret;
}

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 @@ -154,10 +154,10 @@ int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecd
}
count++;
}
memset(nonce32, 0, 32);
secp256k1_scalar_clear(&msg);
secp256k1_scalar_clear(&non);
secp256k1_scalar_clear(&sec);
SECP256K1_CLEANSE(nonce32);
SECP256K1_CLEANSE(msg);
SECP256K1_CLEANSE(non);
SECP256K1_CLEANSE(sec);
}
if (ret) {
secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid);
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));
SECP256K1_CLEANSE(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));
SECP256K1_CLEANSE(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));
SECP256K1_CLEANSE(g);
SECP256K1_CLEANSE(u);
SECP256K1_CLEANSE(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));
SECP256K1_CLEANSE(tmp);
}

static void secp256k1_num_shift(secp256k1_num *r, int bits) {
Expand Down
3 changes: 0 additions & 3 deletions src/scalar.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
#error "Please select scalar implementation"
#endif

/** Clear a scalar to prevent the leak of sensitive data. */
static void secp256k1_scalar_clear(secp256k1_scalar *r);

/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */
static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count);

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 @@ -24,13 +24,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
11 changes: 0 additions & 11 deletions src/scalar_8x32_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,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;
Expand Down
1 change: 0 additions & 1 deletion src/scalar_low_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,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; }

SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
Expand Down
Loading