|
| 1 | +/*********************************************************************** |
| 2 | + * Copyright (c) 2022 Pieter Wuille * |
| 3 | + * Distributed under the MIT software license, see the accompanying * |
| 4 | + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* |
| 5 | + ***********************************************************************/ |
| 6 | + |
| 7 | +/* The code here is inspired by Kris Kwiatkowski's approach in |
| 8 | + * https://github.com/kriskwiatkowski/pqc/blob/main/src/common/ct_check.h |
| 9 | + * to provide a general interface for memory-checking mechanisms, primarily |
| 10 | + * for constant-time checking. |
| 11 | + */ |
| 12 | + |
| 13 | +/* These macros are defined by this header file: |
| 14 | + * |
| 15 | + * - SECP256K1_CHECKMEM_ENABLED: |
| 16 | + * - 1 if memory-checking integration is available, 0 otherwise. |
| 17 | + * This is just a compile-time macro. Use the next macro to check it is actually |
| 18 | + * available at runtime. |
| 19 | + * - SECP256K1_CHECKMEM_RUNNING(): |
| 20 | + * - Acts like a function call, returning 1 if memory checking is available |
| 21 | + * at runtime. |
| 22 | + * - SECP256K1_CHECKMEM_CHECK(p, len): |
| 23 | + * - Assert or otherwise fail in case the len-byte memory block pointed to by p is |
| 24 | + * not considered entirely defined. |
| 25 | + * - SECP256K1_CHECKMEM_CHECK_VERIFY(p, len): |
| 26 | + * - Like SECP256K1_CHECKMEM_CHECK, but only works in VERIFY mode. |
| 27 | + * - SECP256K1_CHECKMEM_UNDEFINE(p, len): |
| 28 | + * - marks the len-byte memory block pointed to by p as undefined data (secret data, |
| 29 | + * in the context of constant-time checking). |
| 30 | + * - SECP256K1_CHECKMEM_DEFINE(p, len): |
| 31 | + * - marks the len-byte memory pointed to by p as defined data (public data, in the |
| 32 | + * context of constant-time checking). |
| 33 | + * |
| 34 | + */ |
| 35 | + |
| 36 | +#ifndef SECP256K1_CHECKMEM_H |
| 37 | +#define SECP256K1_CHECKMEM_H |
| 38 | + |
| 39 | +/* Define a statement-like macro that ignores the arguments. */ |
| 40 | +#define SECP256K1_CHECKMEM_NOOP(p, len) do { (void)(p); (void)(len); } while(0) |
| 41 | + |
| 42 | +/* If compiling under msan, map the SECP256K1_CHECKMEM_* functionality to msan. |
| 43 | + * Choose this preferentially, even when VALGRIND is defined, as msan-compiled |
| 44 | + * binaries can't be run under valgrind anyway. */ |
| 45 | +#if defined(__has_feature) |
| 46 | +# if __has_feature(memory_sanitizer) |
| 47 | +# include <sanitizer/msan_interface.h> |
| 48 | +# define SECP256K1_CHECKMEM_ENABLED 1 |
| 49 | +# define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len)) |
| 50 | +# define SECP256K1_CHECKMEM_DEFINE(p, len) __msan_unpoison((p), (len)) |
| 51 | +# define SECP256K1_CHECKMEM_CHECK(p, len) __msan_check_mem_is_initialized((p), (len)) |
| 52 | +# define SECP256K1_CHECKMEM_RUNNING() (1) |
| 53 | +# endif |
| 54 | +#endif |
| 55 | + |
| 56 | +/* If valgrind integration is desired (through the VALGRIND define), implement the |
| 57 | + * SECP256K1_CHECKMEM_* macros using valgrind. */ |
| 58 | +#if !defined SECP256K1_CHECKMEM_ENABLED |
| 59 | +# if defined VALGRIND |
| 60 | +# include <stddef.h> |
| 61 | +# include <valgrind/memcheck.h> |
| 62 | +# define SECP256K1_CHECKMEM_ENABLED 1 |
| 63 | +# define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len)) |
| 64 | +# define SECP256K1_CHECKMEM_DEFINE(p, len) VALGRIND_MAKE_MEM_DEFINED((p), (len)) |
| 65 | +# define SECP256K1_CHECKMEM_CHECK(p, len) VALGRIND_CHECK_MEM_IS_DEFINED((p), (len)) |
| 66 | + /* VALGRIND_MAKE_MEM_DEFINED returns 0 iff not running on memcheck. |
| 67 | + * This is more precise than the RUNNING_ON_VALGRIND macro, which |
| 68 | + * checks for valgrind in general instead of memcheck specifically. */ |
| 69 | +# define SECP256K1_CHECKMEM_RUNNING() (VALGRIND_MAKE_MEM_DEFINED(NULL, 0) != 0) |
| 70 | +# endif |
| 71 | +#endif |
| 72 | + |
| 73 | +/* As a fall-back, map these macros to dummy statements. */ |
| 74 | +#if !defined SECP256K1_CHECKMEM_ENABLED |
| 75 | +# define SECP256K1_CHECKMEM_ENABLED 0 |
| 76 | +# define SECP256K1_CHECKMEM_UNDEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) |
| 77 | +# define SECP256K1_CHECKMEM_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) |
| 78 | +# define SECP256K1_CHECKMEM_CHECK(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) |
| 79 | +# define SECP256K1_CHECKMEM_RUNNING() (0) |
| 80 | +#endif |
| 81 | + |
| 82 | +#if defined VERIFY |
| 83 | +#define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_CHECK((p), (len)) |
| 84 | +#else |
| 85 | +#define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) |
| 86 | +#endif |
| 87 | + |
| 88 | +#endif /* SECP256K1_CHECKMEM_H */ |
0 commit comments