[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