Split memclear into two versions

secp256k1_memclear has the side effect of undefining bytes for
valgrind checks. In some cases, we may want to zero bytes
but allow subsequent reads. So we split memclear into
memclear_explicit, which makes no guarantees about the content
of the buffer on return, and memzero_explicit, which guarantees
zero value on return.

Change the memset in partial_sign to use memzero_explicit.
This commit is contained in:
John Moffett committed 2025-09-08 12:26:04 -04:00
1 parent 4985ac0f89
commit 399b582a5f
11 files changed
+41 -28

No files matched your search

+16 -3
View File
@@ -219,8 +219,8 @@ 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) {
/* Zeroes memory to prevent leaking sensitive info. Won't be optimized out. */
static SECP256K1_INLINE void secp256k1_memzero_explicit(void *ptr, size_t len) {
#if defined(_MSC_VER)
/* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */
SecureZeroMemory(ptr, len);
@@ -242,6 +242,19 @@ static SECP256K1_INLINE void secp256k1_memclear(void *ptr, size_t len) {
void *(*volatile const volatile_memset)(void *, int, size_t) = memset;
volatile_memset(ptr, 0, len);
#endif
}
/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out.
* The state of the memory after this call is unspecified so callers must not
* make any assumptions about its contents.
*
* In VERIFY builds, it has the side effect of marking the memory as undefined.
* This helps to detect use-after-clear bugs where code incorrectly reads from
* cleansed memory during testing.
*/
static SECP256K1_INLINE void secp256k1_memclear_explicit(void *ptr, size_t len) {
/* The current implementation zeroes, but callers must not rely on this */
secp256k1_memzero_explicit(ptr, len);
#ifdef VERIFY
SECP256K1_CHECKMEM_UNDEFINE(ptr, len);
#endif
@@ -277,7 +290,7 @@ static SECP256K1_INLINE int secp256k1_is_zero_array(const unsigned char *s, size
}
ret = (acc == 0);
/* acc may contain secret values. Try to explicitly clear it. */
secp256k1_memclear(&acc, sizeof(acc));
secp256k1_memclear_explicit(&acc, sizeof(acc));
return ret;
}