Add secp256k1_memclear() for clearing secret data
We rely on memset() and an __asm__ memory barrier where it's available or on SecureZeroMemory() on Windows. The fallback implementation uses a volatile function pointer to memset which the compiler is not clever enough to optimize.
This commit is contained in:
committed by
Sebastian Falbesoner
parent
e7d384488e
commit
1c08126222
34
src/util.h
34
src/util.h
@@ -8,11 +8,17 @@
|
||||
#define SECP256K1_UTIL_H
|
||||
|
||||
#include "../include/secp256k1.h"
|
||||
#include "checkmem.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#if defined(_MSC_VER)
|
||||
/* For SecureZeroMemory */
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#define STR_(x) #x
|
||||
#define STR(x) STR_(x)
|
||||
@@ -221,6 +227,34 @@ 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 <agl@google.com> 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 is 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
|
||||
#ifdef VERIFY
|
||||
SECP256K1_CHECKMEM_UNDEFINE(ptr, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Semantics like memcmp. Variable-time.
|
||||
*
|
||||
* We use this to avoid possible compiler bugs with memcmp, e.g.
|
||||
|
||||
Reference in New Issue
Block a user