[PATCH v2] Use memset for constant length wipememory2
Jussi Kivilinna
jussi.kivilinna at iki.fi
Tue Mar 30 17:56:24 CEST 2021
* src/g10lib.h (fast_wipememory2_inline): New.
(wipememory2): Use 'fast_wipememory2_inline', remove 'fast_wipememory2'
use; Use _gcry_fast_wipememory* when _len or _set is not constant.
(fast_wipememory_s, fast_wipememory2): Remove.
--
Use of memset allows better code generation by compiler - for example,
use of vector registers for memory clearing. Dead store elimination
of memset by compiler optimization is avoided by using assembly block
after memset:
memset(ptr_mem_wipe, 0, constant_mem_len);
asm volatile ("\n" :: "r" (ptr_mem_wipe) : "memory");
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
src/g10lib.h | 62 +++++++++++++++++-----------------------------------
1 file changed, 20 insertions(+), 42 deletions(-)
diff --git a/src/g10lib.h b/src/g10lib.h
index b0b73852..fb288a30 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -358,57 +358,35 @@ void __gcry_burn_stack (unsigned int bytes);
do { __gcry_burn_stack (bytes); \
__gcry_burn_stack_dummy (); } while(0)
-/* To avoid that a compiler optimizes certain memset calls away, these
- macros may be used instead. For small constant length buffers,
- memory wiping is inlined. For non-constant or large length buffers,
- memory is wiped with memset through _gcry_fast_wipememory. */
+/* To avoid that a compiler optimizes certain memset calls away, this
+ macro may be used instead. For constant length buffers, memory
+ wiping is inlined. Dead store elimination of inlined memset is
+ avoided here by using assembly block after memset. For non-constant
+ length buffers, memory is wiped through _gcry_fast_wipememory. */
+#ifdef HAVE_GCC_ASM_VOLATILE_MEMORY
+#define fast_wipememory2_inline(_ptr,_set,_len) do { \
+ memset((_ptr), (_set), (_len)); \
+ asm volatile ("\n" :: "r" (_ptr) : "memory"); \
+ } while(0)
+#else
+#define fast_wipememory2_inline(_ptr,_set,_len) \
+ _gcry_fast_wipememory2((void *)_ptr, _set, _len)
+#endif
#define wipememory2(_ptr,_set,_len) do { \
- if (!CONSTANT_P(_len) || _len > 64) { \
+ if (!CONSTANT_P(_len) || !CONSTANT_P(_set)) { \
if (CONSTANT_P(_set) && (_set) == 0) \
- _gcry_fast_wipememory((void *)_ptr, _len); \
+ _gcry_fast_wipememory((void *)(_ptr), (_len)); \
else \
- _gcry_fast_wipememory2((void *)_ptr, _set, _len); \
- } else {\
- volatile char *_vptr = (volatile char *)(_ptr); \
- size_t _vlen = (_len); \
- const unsigned char _vset = (_set); \
- fast_wipememory2(_vptr, _vset, _vlen); \
- while(_vlen) { *_vptr = (_vset); _vptr++; _vlen--; } \
+ _gcry_fast_wipememory2((void *)(_ptr), (_set), (_len)); \
+ } else { \
+ fast_wipememory2_inline((void *)(_ptr), (_set), (_len)); \
} \
} while(0)
-#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
+#define wipememory(_ptr,_len) wipememory2((_ptr),0,(_len))
void _gcry_fast_wipememory(void *ptr, size_t len);
void _gcry_fast_wipememory2(void *ptr, int set, size_t len);
-#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
- defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
- defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS)
-typedef struct fast_wipememory_s
-{
- u64 a;
-} __attribute__((packed, aligned(1), may_alias)) fast_wipememory_t;
-/* fast_wipememory may leave tail bytes unhandled, in which case tail bytes
- are handled by wipememory. */
-# define fast_wipememory2(_vptr,_vset,_vlen) do { \
- fast_wipememory_t _vset_long; \
- if (_vlen < sizeof(fast_wipememory_t)) \
- break; \
- _vset_long.a = (_vset); \
- _vset_long.a *= U64_C(0x0101010101010101); \
- do { \
- volatile fast_wipememory_t *_vptr_long = \
- (volatile void *)_vptr; \
- _vptr_long->a = _vset_long.a; \
- _vlen -= sizeof(fast_wipememory_t); \
- _vptr += sizeof(fast_wipememory_t); \
- } while (_vlen >= sizeof(fast_wipememory_t)); \
- } while (0)
-#else
-# define fast_wipememory2(_vptr,_vset,_vlen)
-#endif
-
-
/* Digit predicates. */
#define digitp(p) (*(p) >= '0' && *(p) <= '9')
--
2.27.0
More information about the Gcrypt-devel
mailing list