diff --git a/examples/ecdh.c b/examples/ecdh.c index ac03c47656..87a46700b6 100644 --- a/examples/ecdh.c +++ b/examples/ecdh.c @@ -16,14 +16,6 @@ #include "random.h" -void secure_erase(void *buf, size_t size) { - volatile char *vbuf = (volatile char *)buf; - size_t i; - for (i = 0; i < size; ++i) { - vbuf[i] = 0; - } -} - int main(void) { unsigned char seckey1[32]; unsigned char seckey2[32]; diff --git a/examples/ecdsa.c b/examples/ecdsa.c index f03e53579a..a1fafd51d8 100644 --- a/examples/ecdsa.c +++ b/examples/ecdsa.c @@ -15,14 +15,6 @@ #include "random.h" -void secure_erase(void *buf, size_t size) { - volatile char *vbuf = (volatile char *)buf; - size_t i; - for (i = 0; i < size; ++i) { - vbuf[i] = 0; - } -} - int main(void) { /* Instead of signing the message directly, we must sign a 32-byte hash. * Here the message is "Hello, world!" and the hash function was SHA-256. diff --git a/examples/random.h b/examples/random.h index 439226f09f..a52b1fa115 100644 --- a/examples/random.h +++ b/examples/random.h @@ -71,3 +71,32 @@ static void print_hex(unsigned char* data, size_t size) { } printf("\n"); } + +#if defined(_MSC_VER) +// For SecureZeroMemory +#include +#endif +/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */ +static SECP256K1_INLINE void secure_erase(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 +} diff --git a/examples/schnorr.c b/examples/schnorr.c index d0b3aa20a5..317ee1dc63 100644 --- a/examples/schnorr.c +++ b/examples/schnorr.c @@ -17,14 +17,6 @@ #include "random.h" -void secure_erase(void *buf, size_t size) { - volatile char *vbuf = (volatile char *)buf; - size_t i; - for (i = 0; i < size; ++i) { - vbuf[i] = 0; - } -} - int main(void) { unsigned char msg[12] = "Hello World!"; unsigned char msg_hash[32];