[PATCH] Use explicit_bzero for wipememory

Jussi Kivilinna jussi.kivilinna at iki.fi
Tue Nov 20 19:51:02 CET 2018


* configure.ac (AC_CHECK_FUNCS): Check for 'explicit_bzero'.
* src/g10lib.h (wipememory2): Use _gcry_fast_wipememory if _SET is
zero.
(_gcry_fast_wipememory): New.
(_gcry_wipememory2): Rename to...
(_gcry_fast_wipememory2): ...this.
* src/misc.c (_gcry_wipememory): New.
(_gcry_wipememory2): Rename to...
(_gcry_fast_wipememory2): ...this.
(_gcry_fast_wipememory2) [HAVE_EXPLICIT_BZERO]: Use explicit_bzero if
SET is zero.
(_gcry_burn_stack): Use _gcry_fast_wipememory.
--

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 0 files changed

diff --git a/configure.ac b/configure.ac
index 9803d518b..5843884c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1772,6 +1772,7 @@ AC_CHECK_FUNCS(strtoul memmove stricmp atexit raise)
 AC_CHECK_FUNCS(strerror rand mmap getpagesize sysconf waitpid wait4)
 AC_CHECK_FUNCS(gettimeofday getrusage gethrtime clock_gettime syslog)
 AC_CHECK_FUNCS(syscall fcntl ftruncate flockfile)
+AC_CHECK_FUNCS(explicit_bzero)
 
 GNUPG_CHECK_MLOCK
 
diff --git a/src/g10lib.h b/src/g10lib.h
index 9b2147812..694c2d83e 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -334,15 +334,16 @@ 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_wipememory. */
-void _gcry_wipememory2(void *ptr, int set, size_t len);
+   memory is wiped with memset through _gcry_fast_wipememory. */
 #define wipememory2(_ptr,_set,_len) do { \
 	      if (!CONSTANT_P(_len) || _len > 64) { \
-		_gcry_wipememory2((void *)_ptr, _set, _len); \
+		if (CONSTANT_P(_set) && (_set) == 0) \
+		  _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); \
@@ -353,6 +354,9 @@ void _gcry_wipememory2(void *ptr, int set, size_t len);
 	    } while(0)
 #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)
diff --git a/src/misc.c b/src/misc.c
index 420ce74db..bb39e1c2f 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -32,6 +32,8 @@
 
 static int verbosity_level = 0;
 
+/* Prevent compiler from optimizing away the call to memset by accessing
+   memset through volatile pointer. */
 static void *(*volatile memset_ptr)(void *, int, size_t) = (void *)memset;
 
 static void (*fatal_error_handler)(void*,int, const char*) = NULL;
@@ -500,8 +502,37 @@ _gcry_strtokenize (const char *string, const char *delim)
 
 
 void
-_gcry_wipememory2 (void *ptr, int set, size_t len)
+_gcry_fast_wipememory (void *ptr, size_t len)
 {
+  /* Note: This function is called from wipememory/wipememory2 only if LEN
+     is large or unknown at compile time. New wipe function alternatives
+     need to be checked before adding to this function. New implementations
+     need to be faster than wipememory/wipememory2 macros in 'misc.h'.
+
+     Following implementations were found to have suboptimal performance:
+
+     - [_WIN32/mingw32] SecureZeroMemory; Inline function, equivalent to
+       volatile byte buffer set: while(buflen--) (volatile char *)(buf++)=set;
+   */
+#ifdef HAVE_EXPLICIT_BZERO
+  explicit_bzero (ptr, len);
+#else
+  memset_ptr (ptr, 0, len);
+#endif
+}
+
+
+void
+_gcry_fast_wipememory2 (void *ptr, int set, size_t len)
+{
+#ifdef HAVE_EXPLICIT_BZERO
+  if (set == 0)
+    {
+      explicit_bzero (ptr, len);
+      return;
+    }
+#endif
+
   memset_ptr (ptr, set, len);
 }
 
@@ -514,11 +545,11 @@ __gcry_burn_stack (unsigned int bytes)
   unsigned int buflen = ((!bytes + bytes) + 63) & ~63;
   char buf[buflen];
 
-  memset_ptr (buf, 0, buflen);
+  _gcry_fast_wipememory (buf, buflen);
 #else
   volatile char buf[64];
 
-  wipememory (buf, sizeof buf);
+  _gcry_fast_wipememory (buf, sizeof buf);
 
   if (bytes > sizeof buf)
       _gcry_burn_stack (bytes - sizeof buf);




More information about the Gcrypt-devel mailing list