/*********************************************************************** * Copyright (c) 2022 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ /* The code here is inspired by Kris Kwiatkowski's approach in * https://github.com/kriskwiatkowski/pqc/blob/main/src/common/ct_check.h * to provide a general interface for memory-checking mechanisms, primarily * for constant-time checking. */ /* These macros are defined by this header file: * * - SECP256K1_CHECKMEM_ENABLED: * - 1 if memory-checking integration is available, 0 otherwise. * This is just a compile-time macro. Use the next macro to check it is actually * available at runtime. * - SECP256K1_CHECKMEM_RUNNING(): * - Acts like a function call, returning 1 if memory checking is available * at runtime. * - SECP256K1_CHECKMEM_CHECK(p, len): * - Assert or otherwise fail in case the len-byte memory block pointed to by p is * not considered entirely defined. * - SECP256K1_CHECKMEM_CHECK_VERIFY(p, len): * - Like SECP256K1_CHECKMEM_CHECK, but only works in VERIFY mode. * - SECP256K1_CHECKMEM_UNDEFINE(p, len): * - marks the len-byte memory block pointed to by p as undefined data (secret data, * in the context of constant-time checking). * - SECP256K1_CHECKMEM_DEFINE(p, len): * - marks the len-byte memory pointed to by p as defined data (public data, in the * context of constant-time checking). * */ #ifndef SECP256K1_CHECKMEM_H #define SECP256K1_CHECKMEM_H /* Define a statement-like macro that ignores the arguments. */ #define SECP256K1_CHECKMEM_NOOP(p, len) do { (void)(p); (void)(len); } while(0) /* If compiling under msan, map the SECP256K1_CHECKMEM_* functionality to msan. * Choose this preferentially, even when VALGRIND is defined, as msan-compiled * binaries can't be run under valgrind anyway. */ #if defined(__has_feature) # if __has_feature(memory_sanitizer) # include # define SECP256K1_CHECKMEM_ENABLED 1 # define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len)) # define SECP256K1_CHECKMEM_DEFINE(p, len) __msan_unpoison((p), (len)) # define SECP256K1_CHECKMEM_CHECK(p, len) __msan_check_mem_is_initialized((p), (len)) # define SECP256K1_CHECKMEM_RUNNING() (1) # endif #endif /* If valgrind integration is desired (through the VALGRIND define), implement the * SECP256K1_CHECKMEM_* macros using valgrind. */ #if !defined SECP256K1_CHECKMEM_ENABLED # if defined VALGRIND # include # if defined(__clang__) && defined(__APPLE__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wreserved-identifier" # endif # include # if defined(__clang__) && defined(__APPLE__) # pragma clang diagnostic pop # endif # define SECP256K1_CHECKMEM_ENABLED 1 # define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len)) # define SECP256K1_CHECKMEM_DEFINE(p, len) VALGRIND_MAKE_MEM_DEFINED((p), (len)) # define SECP256K1_CHECKMEM_CHECK(p, len) VALGRIND_CHECK_MEM_IS_DEFINED((p), (len)) /* VALGRIND_MAKE_MEM_DEFINED returns 0 iff not running on memcheck. * This is more precise than the RUNNING_ON_VALGRIND macro, which * checks for valgrind in general instead of memcheck specifically. */ # define SECP256K1_CHECKMEM_RUNNING() (VALGRIND_MAKE_MEM_DEFINED(NULL, 0) != 0) # endif #endif /* As a fall-back, map these macros to dummy statements. */ #if !defined SECP256K1_CHECKMEM_ENABLED # define SECP256K1_CHECKMEM_ENABLED 0 # define SECP256K1_CHECKMEM_UNDEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) # define SECP256K1_CHECKMEM_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) # define SECP256K1_CHECKMEM_CHECK(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) # define SECP256K1_CHECKMEM_RUNNING() (0) #endif #if defined VERIFY #define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_CHECK((p), (len)) #else #define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) #endif #endif /* SECP256K1_CHECKMEM_H */